First round of sql injection with stubs
This commit is contained in:
parent
dbcd5cce3a
commit
8b6ad92aea
@ -13,7 +13,7 @@
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_conent1.adoc"></div>
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_content1.adoc"></div>
|
||||
</div>
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
@ -33,6 +33,114 @@
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_content4.adoc"></div>
|
||||
</div>
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_content5.adoc"></div>
|
||||
</div>
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_content5a.adoc"></div>
|
||||
<div class="attack-container">
|
||||
<!-- using attack-form class on your form, will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
||||
<div id="lessonContent">
|
||||
<!-- using attack-form class on your form will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
||||
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
|
||||
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
|
||||
<form class="attack-form" accept-charset="UNKNOWN"
|
||||
method="POST" name="form"
|
||||
action="/WebGoat/SqlInjection/attack5a"
|
||||
enctype="application/json;charset=UTF-8">
|
||||
<table>
|
||||
<tr>
|
||||
<td>Name:</td>
|
||||
<td><input name="answer" value="" type="TEXT" /></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<!-- do not remove the two following div's, this is where your feedback/output will land -->
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_content5a.adoc"></div>
|
||||
<div class="attack-container">
|
||||
<!-- using attack-form class on your form, will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
||||
<div id="lessonContent">
|
||||
<!-- using attack-form class on your form will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
||||
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
|
||||
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
|
||||
<form class="attack-form" accept-charset="UNKNOWN"
|
||||
method="POST" name="form"
|
||||
action="/WebGoat/SqlInjection/attack5b"
|
||||
enctype="application/json;charset=UTF-8">
|
||||
<table>
|
||||
<tr>
|
||||
<td>Name:</td>
|
||||
<td><input name="answer" value="" type="TEXT" /></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<!-- do not remove the two following div's, this is where your feedback/output will land -->
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_content6.adoc"></div>
|
||||
</div>
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_content7.adoc"></div>
|
||||
</div>
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_content8.adoc"></div>
|
||||
</div>
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_content9.adoc"></div>
|
||||
</div>
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_content10.adoc"></div>
|
||||
</div>
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_content11.adoc"></div>
|
||||
</div>
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_content12.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
|
@ -1,17 +1,17 @@
|
||||
== What is SQL
|
||||
|
||||
SQL is a way to interact with databases.
|
||||
SQL is a way to interact with databases and is interpreted by the database.
|
||||
|
||||
= SQL = Structured Query Language
|
||||
=== SQL - Structured Query Language
|
||||
* Not “Standard Query Language”
|
||||
* Multiple versions of SQL. Most databases have some custom functions
|
||||
* Most vendors have a proprietary extension
|
||||
|
||||
= Data Manipulation Language (DML)
|
||||
=== Data Manipulation Language (DML)
|
||||
* SELECT, INSERT, UPDATE, DELETE, …
|
||||
|
||||
= Data Definition Language (DDL)
|
||||
=== Data Definition Language (DDL)
|
||||
* CREATE, ALTER, DROP,TRUNCATE,…
|
||||
|
||||
= Data Control Language (DCL)
|
||||
=== Data Control Language (DCL)
|
||||
* GRANT, REVOKE, …
|
||||
|
@ -0,0 +1,35 @@
|
||||
== Parameterized Queries – Java Example
|
||||
-------------------------------------------------------
|
||||
// Parser returns only valid string data
|
||||
String accountID = getParser().getStringParameter(ACCT_ID, "");
|
||||
String data = null;
|
||||
try
|
||||
{
|
||||
// Read only database connection
|
||||
Statement connection = DatabaseUtilities.getConnection(READ_ONLY);
|
||||
|
||||
// Build a fully qualified query
|
||||
String query = "SELECT first_name, last_name, acct_id, balance
|
||||
FROM user_data WHERE acct_id = ?";
|
||||
PreparedStatement statement = connection.prepareStatement(query);
|
||||
statement.setString(1, accountID);
|
||||
ResultSet results = statement.executeQuery();
|
||||
if ((results != null) && (results.first() == true))
|
||||
{
|
||||
// Only one record should be returned for this query
|
||||
Results.last();
|
||||
if (results.getRow() <= 2)
|
||||
{
|
||||
data = processAccount(results);
|
||||
}
|
||||
else { // Handle the error – Database integrity issue }
|
||||
}
|
||||
else { // Handle the error – no records found }
|
||||
}
|
||||
catch (SQLException sqle) { // Log and handle the SQL Exception }
|
||||
catch (Exception e) { // Log and handle the Exception }
|
||||
finally { // Always close connection in finally block
|
||||
DatabaseUtilities.closeConnection();
|
||||
}
|
||||
return data;
|
||||
-------------------------------------------------------
|
@ -0,0 +1,22 @@
|
||||
== Parameterized Queries – .NET
|
||||
-------------------------------------------------------
|
||||
public static bool isUsernameValid(string username) {
|
||||
RegEx r = new Regex(“^[A-Za-z0-9]{16}$”);
|
||||
Return r.isMatch(username);
|
||||
}
|
||||
|
||||
// SqlConnection conn is set and opened elsewhere for brevity.
|
||||
try {
|
||||
string selectString = “SELECT * FROM user_table WHERE username = @userID”;
|
||||
SqlCommand cmd = new SqlCommand( selectString, conn );
|
||||
if ( isUsernameValid( uid ) ) {
|
||||
cmd.Parameters.Add( "@userID", SqlDbType.VarChar, 16 ).Value = uid;
|
||||
SqlDataReader myReader = cmd.ExecuteReader();
|
||||
if ( myReader ) {
|
||||
// make the user record active in some way.
|
||||
myReader.Close();
|
||||
}
|
||||
} else { // handle invalid input }
|
||||
}
|
||||
catch (Exception e) { // Handle all exceptions… }
|
||||
-------------------------------------------------------
|
@ -0,0 +1,13 @@
|
||||
== Input Validation Required?
|
||||
|
||||
=== Since my queries are no longer injectable do I still need to validate my input?
|
||||
* *YES!*
|
||||
|
||||
=== Prevents other types of attacks from being stored in the database
|
||||
* Stored XSS
|
||||
* Information leakage
|
||||
* Logic errors – business rule validation
|
||||
* SQL Injection
|
||||
|
||||
=== Often the database is considered trusted
|
||||
|
@ -0,0 +1,22 @@
|
||||
== Parameterized Queries – .NET
|
||||
-------------------------------------------------------
|
||||
public static bool isUsernameValid(string username) {
|
||||
RegEx r = new Regex(“^[A-Za-z0-9]{16}$”);
|
||||
Return r.isMatch(username);
|
||||
}
|
||||
|
||||
// SqlConnection conn is set and opened elsewhere for brevity.
|
||||
try {
|
||||
string selectString = “SELECT * FROM user_table WHERE username = @userID”;
|
||||
SqlCommand cmd = new SqlCommand( selectString, conn );
|
||||
if ( isUsernameValid( uid ) ) {
|
||||
cmd.Parameters.Add( "@userID", SqlDbType.VarChar, 16 ).Value = uid;
|
||||
SqlDataReader myReader = cmd.ExecuteReader();
|
||||
if ( myReader ) {
|
||||
// make the user record active in some way.
|
||||
myReader.Close();
|
||||
}
|
||||
} else { // handle invalid input }
|
||||
}
|
||||
catch (Exception e) { // Handle all exceptions… }
|
||||
-------------------------------------------------------
|
@ -1,32 +1,13 @@
|
||||
== Consequences of SQL Injection
|
||||
== What is SQL Injection?
|
||||
|
||||
= SQL injection attacks allow attackers to
|
||||
* Spoof identity
|
||||
* Tamper with existing data
|
||||
* Cause repudiation issues such as voiding transactions or changing balances
|
||||
* Allow the complete disclosure of all data on the system
|
||||
* Destroy the data or make it otherwise unavailable
|
||||
* Become administrator of the database server
|
||||
=== A SQL injection attack consists of insertion or "injection" of an SQL query via the input data from the client to the application
|
||||
|
||||
= SQL Injection is more common in PHP, Classic ASP, Cold Fusion and older languages
|
||||
* Languages do not provide parameterized query support
|
||||
* Parameterized queries have been added to newer versions
|
||||
* Early adopters of web technology
|
||||
=== A successful SQL injection exploit can:
|
||||
* Read and modify sensitive data from the database
|
||||
* Execute administration operations on the database
|
||||
** Shutdown auditing or the DBMS
|
||||
** Truncate tables and logs
|
||||
** Add users
|
||||
* Recover the content of a given file present on the DBMS file system
|
||||
* Issue commands to the operating system
|
||||
|
||||
== Severity of SQL Injection
|
||||
|
||||
= The severity of SQL Injection attacks is limited by
|
||||
* Attacker’s skill and imagination
|
||||
* Defense in depth countermeasures
|
||||
Input validation
|
||||
Least privilege
|
||||
* Database technology
|
||||
|
||||
= Not all databases support command chaining
|
||||
* Microsoft Access
|
||||
* MySQL Connector/J and C
|
||||
* Oracle
|
||||
|
||||
= Not all databases are equal (SQL Server)
|
||||
* Command shell: master.dbo.xp_cmdshell 'cmd.exe dir c:'
|
||||
* Reqistry commands: xp_regread, xp_regdeletekey, …
|
||||
|
@ -1,17 +1,14 @@
|
||||
== Example of SQL Injection
|
||||
== Consequences of SQL Injection
|
||||
|
||||
= Dynamic query in application
|
||||
* select * from users where name = ‘” + userName + “’”;
|
||||
* select * from users where employee_id = ” + userID;
|
||||
=== SQL injection attacks allow attackers to
|
||||
* Spoof identity
|
||||
* Tamper with existing data
|
||||
* Cause repudiation issues such as voiding transactions or changing balances
|
||||
* Allow the complete disclosure of all data on the system
|
||||
* Destroy the data or make it otherwise unavailable
|
||||
* Become administrator of the database server
|
||||
|
||||
= Attacker supplies unexpected text
|
||||
* userName = [red]Smith’ or ‘1’=‘1[red]
|
||||
* userName =[red]‘ or 1=1 --[red]
|
||||
* userID = [red]1234567 or 1=1[red]
|
||||
* UserName = [red]Smith’;drop table users; truncate audit_log;--[red]
|
||||
|
||||
= Application executes query
|
||||
* select * from users where name = [red]‘Smith’ or ‘1’ = ‘1’[red]
|
||||
** select * from users where name = [red]‘Smith’ or TRUE[red]
|
||||
* select * from users where employee_id = 1234567 or 1=1
|
||||
** *All records are returned from database*
|
||||
=== SQL Injection is more common in PHP, Classic ASP, Cold Fusion and older languages
|
||||
* Languages that do not provide parameterized query support
|
||||
* Parameterized queries have been added to newer versions
|
||||
* Early adopters of web technology (i.e. Old Code)
|
@ -1,19 +1,17 @@
|
||||
== Special Characters & Statements
|
||||
== Severity of SQL Injection
|
||||
|
||||
/* */ are inline comments
|
||||
-- , # are line comments
|
||||
'Select * from users where name = ‘admin’--and pass = ‘pass’'
|
||||
=== The severity of SQL Injection attacks is limited by
|
||||
* Attacker’s skill and imagination
|
||||
* Defense in depth countermeasures
|
||||
** Input validation
|
||||
** Least privilege
|
||||
* Database technology
|
||||
|
||||
; allows query chaining
|
||||
'Select * from users; drop table users;'
|
||||
=== Not all databases support command chaining
|
||||
* Microsoft Access
|
||||
* MySQL Connector/J and C
|
||||
* Oracle
|
||||
|
||||
’,+,|| allows string concatenation
|
||||
Char() strings without quotes
|
||||
'Select * from users where name = ‘+char(27) or 1=1'
|
||||
|
||||
|
||||
Unions allows overlapping of database tables
|
||||
'Select id, text from news
|
||||
union all select name, pass from users'
|
||||
|
||||
Joins allows connecting to other tables
|
||||
=== Not all databases are equal (SQL Server)
|
||||
* Command shell: `master.dbo.xp_cmdshell 'cmd.exe dir c:'`
|
||||
* Reqistry commands: `xp_regread`, `xp_regdeletekey`, …
|
||||
|
@ -0,0 +1,23 @@
|
||||
== Example of SQL Injection
|
||||
|
||||
=== Dynamic query in application
|
||||
-------------------------------------------------------
|
||||
"select * from users where name = ‘" + userName + "'";
|
||||
-------------------------------------------------------
|
||||
|
||||
-------------------------------------------------------
|
||||
|
||||
"select * from users where employee_id = " + userID;
|
||||
-------------------------------------------------------
|
||||
|
||||
=== Attacker supplies unexpected text
|
||||
* userName = [red]#Smith’ or ‘1’=‘1#
|
||||
* userName =[red]#‘ or 1=1 --#
|
||||
* userID = [red]#1234567 or 1=1#
|
||||
* UserName = [red]#Smith’;drop table users; truncate audit_log;--#
|
||||
|
||||
=== Application executes query
|
||||
* select * from users where name = [red]#‘Smith’ or ‘1’ = ‘1’#
|
||||
** select * from users where name = [red]#‘Smith’ or TRUE#
|
||||
* select * from users where employee_id = 1234567 or 1=1
|
||||
* *All records are returned from database*
|
@ -0,0 +1,8 @@
|
||||
== Try It! String SQL Injection
|
||||
|
||||
The query in the code builds a dynamic query as seen in the previous example. The query in the code looks like:
|
||||
-------------------------------------------------------
|
||||
"select * from users where name = ‘" + userName + "'";
|
||||
-------------------------------------------------------
|
||||
|
||||
Using the form below try to retrieve all the users from the users table.
|
@ -0,0 +1,8 @@
|
||||
== Try It! Numeric SQL Injection
|
||||
|
||||
The query in the code builds a dynamic query as seen in the previous example. The query in the code looks like:
|
||||
-------------------------------------------------------
|
||||
"select * from users where employee_id = " + userID;
|
||||
-------------------------------------------------------
|
||||
|
||||
Using the form below try to retrieve all the users from the users table.
|
@ -0,0 +1,20 @@
|
||||
== Special Characters
|
||||
|
||||
/* */ are inline comments
|
||||
-- , # are line comments
|
||||
'Select * from users where name = ‘admin’--and pass = ‘pass’'
|
||||
|
||||
; allows query chaining
|
||||
'Select * from users; drop table users;'
|
||||
|
||||
’,+,|| allows string concatenation
|
||||
Char() strings without quotes
|
||||
'Select * from users where name = ‘+char(27) or 1=1'
|
||||
|
||||
== Special Statements
|
||||
|
||||
Unions allows overlapping of database tables
|
||||
'Select id, text from news
|
||||
union all select name, pass from users'
|
||||
|
||||
Joins allows connecting to other tables
|
@ -0,0 +1,23 @@
|
||||
== Immutable Queries
|
||||
|
||||
=== Static queries?
|
||||
-------------------------------------------------------
|
||||
select * from products;
|
||||
-------------------------------------------------------
|
||||
|
||||
-------------------------------------------------------
|
||||
select * from users where user = "'" + session.getAttribute("UserID") + "'";
|
||||
-------------------------------------------------------
|
||||
|
||||
=== Parameterized Queries
|
||||
|
||||
-------------------------------------------------------
|
||||
String query = "SELECT * FROM users WHERE last_name = ?";
|
||||
PreparedStatement statement = connection.prepareStatement(query);
|
||||
statement.setString(1, accountName);
|
||||
ResultSet results = statement.executeQuery();
|
||||
-------------------------------------------------------
|
||||
|
||||
=== Stored Procedures
|
||||
|
||||
Only if stored procedure does not generate dynamic SQL
|
@ -0,0 +1,23 @@
|
||||
== Stored Procedures
|
||||
|
||||
=== Safe Stored Procedure (Microsoft SQL Server)
|
||||
-------------------------------------------------------
|
||||
CREATE PROCEDURE ListCustomers(@Country nvarchar(30))
|
||||
AS
|
||||
SELECT City, COUNT(*)
|
||||
FROM Customers
|
||||
WHERE Country LIKE @Country GROUP BY City
|
||||
|
||||
|
||||
EXEC ListCustomers ‘USA’
|
||||
-------------------------------------------------------
|
||||
|
||||
=== Injectable Stored Procedure (Microsoft SQL Server)
|
||||
-------------------------------------------------------
|
||||
CREATE PROEDURE getUser(@lastName nvarchar(25))
|
||||
AS
|
||||
declare @sql nvarchar(255)
|
||||
set @sql = 'select * from users where
|
||||
LastName = + @LastName + '
|
||||
exec sp_executesql @sql
|
||||
-------------------------------------------------------
|
@ -0,0 +1,24 @@
|
||||
== Parameterized Queries – Java Snippet
|
||||
|
||||
-------------------------------------------------------
|
||||
public static bool isUsernameValid(string username) {
|
||||
RegEx r = new Regex(“^[A-Za-z0-9]{16}$”);
|
||||
return r.isMatch(username);
|
||||
}
|
||||
|
||||
// java.sql.Connection conn is set elsewhere for brevity.
|
||||
PreparedStatement ps = null;
|
||||
RecordSet rs = null;
|
||||
try {
|
||||
pUserName = request.getParameter(“UserName”);
|
||||
if ( isUsernameValid (pUsername);
|
||||
ps = conn.prepareStatement(“SELECT * FROM user_table
|
||||
WHERE username = ? ”);
|
||||
ps.setString(1, pUsername);
|
||||
rs = ps.execute();
|
||||
if ( rs.next() ) {
|
||||
// do the work of making the user record active in some way
|
||||
} else { // handle invalid input }
|
||||
}
|
||||
catch (…) { // handle all exceptions … }
|
||||
-------------------------------------------------------
|
Loading…
x
Reference in New Issue
Block a user