First round of sql injection with stubs

This commit is contained in:
mayhew64 2016-11-15 19:37:11 -05:00
parent dbcd5cce3a
commit 8b6ad92aea
16 changed files with 371 additions and 66 deletions

View File

@ -13,7 +13,7 @@
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson --> <!-- 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, <!-- 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 --> 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>
<div class="lesson-page-wrapper"> <div class="lesson-page-wrapper">
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson --> <!-- 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 --> which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
<div class="adoc-content" th:replace="doc:SqlInjection_content4.adoc"></div> <div class="adoc-content" th:replace="doc:SqlInjection_content4.adoc"></div>
</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"> <div class="lesson-page-wrapper">
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson --> <!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->

View File

@ -1,17 +1,17 @@
== What is SQL == 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” * Not “Standard Query Language”
* Multiple versions of SQL. Most databases have some custom functions * Multiple versions of SQL. Most databases have some custom functions
* Most vendors have a proprietary extension * Most vendors have a proprietary extension
= Data Manipulation Language (DML) === Data Manipulation Language (DML)
* SELECT, INSERT, UPDATE, DELETE, … * SELECT, INSERT, UPDATE, DELETE, …
= Data Definition Language (DDL) === Data Definition Language (DDL)
* CREATE, ALTER, DROP,TRUNCATE,… * CREATE, ALTER, DROP,TRUNCATE,…
= Data Control Language (DCL) === Data Control Language (DCL)
* GRANT, REVOKE, … * GRANT, REVOKE, …

View File

@ -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;
-------------------------------------------------------

View File

@ -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… }
-------------------------------------------------------

View File

@ -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

View File

@ -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… }
-------------------------------------------------------

View File

@ -1,32 +1,13 @@
== Consequences of SQL Injection == What is SQL Injection?
= SQL injection attacks allow attackers to === A SQL injection attack consists of insertion or "injection" of an SQL query via the input data from the client to the application
* 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
= SQL Injection is more common in PHP, Classic ASP, Cold Fusion and older languages === A successful SQL injection exploit can:
* Languages do not provide parameterized query support * Read and modify sensitive data from the database
* Parameterized queries have been added to newer versions * Execute administration operations on the database
* Early adopters of web technology ** 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
* Attackers 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, …

View File

@ -1,17 +1,14 @@
== Example of SQL Injection == Consequences of SQL Injection
= Dynamic query in application === SQL injection attacks allow attackers to
* select * from users where name = ‘” + userName + “’”; * Spoof identity
* select * from users where employee_id = ” + userID; * 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 === SQL Injection is more common in PHP, Classic ASP, Cold Fusion and older languages
* userName = [red]Smith or 1=1[red] * Languages that do not provide parameterized query support
* userName =[red] or 1=1 --[red] * Parameterized queries have been added to newer versions
* userID = [red]1234567 or 1=1[red] * Early adopters of web technology (i.e. Old Code)
* 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*

View File

@ -1,19 +1,17 @@
== Special Characters & Statements == Severity of SQL Injection
/* */ are inline comments === The severity of SQL Injection attacks is limited by
-- , # are line comments * Attackers skill and imagination
'Select * from users where name = admin--and pass = pass' * Defense in depth countermeasures
** Input validation
** Least privilege
* Database technology
; allows query chaining === Not all databases support command chaining
'Select * from users; drop table users;' * Microsoft Access
* MySQL Connector/J and C
* Oracle
,+,|| allows string concatenation === Not all databases are equal (SQL Server)
Char() strings without quotes * Command shell: `master.dbo.xp_cmdshell 'cmd.exe dir c:'`
'Select * from users where name = +char(27) or 1=1' * Reqistry commands: `xp_regread`, `xp_regdeletekey`, …
Unions allows overlapping of database tables
'Select id, text from news
union all select name, pass from users'
Joins allows connecting to other tables

View File

@ -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*

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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
-------------------------------------------------------

View File

@ -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 … }
-------------------------------------------------------