Added a new lessons for sql injections on "Compromising confidentiality with String SQL Injection"
This commit is contained in:
parent
083eb1b567
commit
75b1895122
@ -982,6 +982,48 @@ public class CreateDB {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the table used in SQL-Injections (introduction)
|
||||
*/
|
||||
private void createEmployeesTable(Connection connection) throws SQLException {
|
||||
Statement statement = connection.createStatement();
|
||||
|
||||
// Drop employees table
|
||||
try {
|
||||
String dropTable = "DROP TABLE employees";
|
||||
statement.executeUpdate(dropTable);
|
||||
} catch (SQLException e) {
|
||||
System.out.println("Info - Could not drop employees table");
|
||||
}
|
||||
|
||||
// Create the new table
|
||||
try {
|
||||
String createTableStatement = "CREATE TABLE employees ("
|
||||
+ "userid varchar(6) not null primary key,"
|
||||
+ "first_name varchar(20),"
|
||||
+ "last_name varchar(20),"
|
||||
+ "department varchar(20),"
|
||||
+ "salary varchar(10),"
|
||||
+ "auth_tan varchar(6)"
|
||||
+ ")";
|
||||
statement.executeUpdate(createTableStatement);
|
||||
} catch (SQLException e) {
|
||||
System.out.println("Error creating employees table " + e.getLocalizedMessage());
|
||||
}
|
||||
|
||||
// Populate
|
||||
String insertData1 = "INSERT INTO employees VALUES ('32147','Paulina', 'Travers', 'Accounting', '$46.000', 'P45JSI')";
|
||||
String insertData2 = "INSERT INTO employees VALUES ('89762','Tobi', 'Barnett', 'Development', '$77.000', 'TA9LL1')";
|
||||
String insertData3 = "INSERT INTO employees VALUES ('96134','Bob', 'Franco', 'Marketing', '$83.700', 'LO9S2V')";
|
||||
String insertData4 = "INSERT INTO employees VALUES ('34477','Abraham ', 'Holman', 'Development', '$50.000', 'UU2ALK')";
|
||||
String insertData5 = "INSERT INTO employees VALUES ('37648','John', 'Smith', 'Marketing', '$64.350', '3SL99A')";
|
||||
statement.executeUpdate(insertData1);
|
||||
statement.executeUpdate(insertData2);
|
||||
statement.executeUpdate(insertData3);
|
||||
statement.executeUpdate(insertData4);
|
||||
statement.executeUpdate(insertData5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Description of the Method
|
||||
*
|
||||
@ -1009,6 +1051,7 @@ public class CreateDB {
|
||||
createMFEImagesTable(connection);
|
||||
createModifyWithSQLLessonTable(connection);
|
||||
createJWTKeys(connection);
|
||||
createEmployeesTable(connection);
|
||||
System.out.println("Success: creating tables.");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,92 @@
|
||||
|
||||
package org.owasp.webgoat.plugin.introduction;
|
||||
|
||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
||||
import org.owasp.webgoat.assignments.AttackResult;
|
||||
import org.owasp.webgoat.session.DatabaseUtilities;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.sql.*;
|
||||
|
||||
@AssignmentPath("/SqlInjection/attack8")
|
||||
@AssignmentHints(value = {"SqlStringInjectionHint8-1", "SqlStringInjectionHint8-2", "SqlStringInjectionHint8-3", "SqlStringInjectionHint8-4", "SqlStringInjectionHint8-5"})
|
||||
public class SqlInjectionLesson8 extends AssignmentEndpoint {
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
public
|
||||
@ResponseBody
|
||||
AttackResult completed(@RequestParam String name, @RequestParam String auth_tan) {
|
||||
return injectableQueryConfidentiality(name, auth_tan);
|
||||
}
|
||||
|
||||
protected AttackResult injectableQueryConfidentiality(String name, String auth_tan) {
|
||||
try {
|
||||
Connection connection = DatabaseUtilities.getConnection(getWebSession());
|
||||
String query = "SELECT * FROM employees WHERE last_name = '" + name + "' AND auth_tan = '" + auth_tan + "'";
|
||||
|
||||
try {
|
||||
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
|
||||
ResultSet results = statement.executeQuery(query);
|
||||
|
||||
if ((results != null) && (results.first())) {
|
||||
ResultSetMetaData resultsMetaData = results.getMetaData();
|
||||
StringBuffer output = new StringBuffer();
|
||||
|
||||
output.append(generateTable(results, resultsMetaData));
|
||||
results.last();
|
||||
|
||||
// If they get back more than one user they succeeded
|
||||
if (results.getRow() > 1) {
|
||||
return trackProgress(success().feedback("sql-injection.8.success").feedbackArgs(output.toString()).build());
|
||||
} else {
|
||||
return trackProgress(failed().output(output.toString()).build());
|
||||
}
|
||||
} else {
|
||||
return trackProgress(failed().feedback("sql-injection.8.no.results").build());
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
return trackProgress(failed().output(e.getMessage()).build());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build());
|
||||
}
|
||||
}
|
||||
|
||||
public static String generateTable(ResultSet results, ResultSetMetaData resultsMetaData) throws SQLException {
|
||||
int numColumns = resultsMetaData.getColumnCount();
|
||||
results.beforeFirst();
|
||||
StringBuffer t = new StringBuffer();
|
||||
t.append("<table>");
|
||||
|
||||
if (results.next()) {
|
||||
t.append("<tr>");
|
||||
for (int i = 1; i < (numColumns + 1); i++) {
|
||||
t.append("<th>" + resultsMetaData.getColumnName(i) + "</th>");
|
||||
}
|
||||
t.append("</tr>");
|
||||
|
||||
results.beforeFirst();
|
||||
while (results.next()) {
|
||||
t.append("<tr>");
|
||||
for (int i = 1; i < (numColumns + 1); i++) {
|
||||
t.append("<td>" + results.getString(i) + "</td>");
|
||||
}
|
||||
t.append("</tr>");
|
||||
}
|
||||
|
||||
} else {
|
||||
t.append("Query Successful; however no data was returned from this query.");
|
||||
}
|
||||
|
||||
t.append("</table>");
|
||||
return (t.toString());
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -57,14 +57,20 @@
|
||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||
<form class="attack-form" accept-charset="UNKNOWN"
|
||||
method="POST" name="form"
|
||||
action="/WebGoat/SqlInjection/attack5a"
|
||||
enctype="application/json;charset=UTF-8">
|
||||
action="/WebGoat/SqlInjection/attack8"
|
||||
enctype="application/json;charset=UTF-8"
|
||||
autocomplete="off">
|
||||
<table>
|
||||
<tr>
|
||||
<td>Account Name:</td>
|
||||
<td><input name="account" value="" type="TEXT"/></td>
|
||||
<td><input
|
||||
name="Get Account Info" value="Get Account Info" type="SUBMIT"/></td>
|
||||
<td><label for="name">Employee Name:</label></td>
|
||||
<td><input id="name" name="name" value="" type="TEXT" placeholder="Lastname"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="auth_tan">Authentication TAN:</label></td>
|
||||
<td><input id="auth_tan" name="auth_tan" value="" type="TEXT" placeholder="TAN"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><button type="SUBMIT">Get department</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
@ -104,6 +110,26 @@
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_introduction_content10.adoc"></div>
|
||||
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_introduction_content8.adoc"></div>
|
||||
<div class="attack-container">
|
||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||
<form class="attack-form" accept-charset="UNKNOWN"
|
||||
method="POST" name="form"
|
||||
action="/WebGoat/SqlInjection/attack5a"
|
||||
enctype="application/json;charset=UTF-8">
|
||||
<table>
|
||||
<tr>
|
||||
<td>Account Name:</td>
|
||||
<td><input name="account" value="" type="TEXT"/></td>
|
||||
<td><input
|
||||
name="Get Account Info" value="Get Account Info" type="SUBMIT"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</html>
|
||||
|
@ -44,3 +44,12 @@ sql-injection.6a.no.results=No results matched. Try Again.
|
||||
|
||||
sql-injection.6b.success=You have succeeded: {0}
|
||||
sql-injection.6b.no.results=No results matched. Try Again.
|
||||
|
||||
sql-injection.8.success=You have succeed: {0}
|
||||
sql-injection.8.no.results=No employee found with matching lastname. Or maybe your authentication TAN is incorrect?
|
||||
|
||||
SqlStringInjectionHint8-1=The application is taking your input and inserting the values into the variables 'name' and 'auth_tan' of the pre-formed SQL command.
|
||||
SqlStringInjectionHint8-2=Compound SQL statements can be made by expanding the WHERE clause of the statement with keywords like AND and OR.
|
||||
SqlStringInjectionHint8-3=Try appending a SQL statement that always resolves to true.
|
||||
SqlStringInjectionHint8-4=Make sure all quotes (" ' ") are opened and closed properly so the resulting SQL query is syntactically correct.
|
||||
SqlStringInjectionHint8-5=Try extending the WHERE clause of the statement by adding something like: ' OR '1' = '1.
|
||||
|
@ -1,12 +1,23 @@
|
||||
Confidentiality
|
||||
== Compromising confidentiality with String SQL Injection
|
||||
If a system is vulnerable to SQL-Injections it is also easy to compromise aspects of the CIA-Triad.
|
||||
In the following three lessons, you will learn how to use simple SQL-Injection attacks to compromise each of the three by using SQL String and Numeric Injections, as well as query chaining.
|
||||
|
||||
== Try It! String SQL Injection
|
||||
This lesson, we will take a look at confidentiality.
|
||||
|
||||
The query in the code builds a dynamic query as seen in the previous example. The query in the code builds a dynamic query by concatenating strings making it susceptible to String SQL injection:
|
||||
=== What's String SQL Injection
|
||||
If queries are build dynamically in the application by concatenating strings to it, this makes it very susceptible to String SQL injection. +
|
||||
If the input takes a string, then you can easily manipulate the build query by using quotation marks to form the string to your specific needs. You could per example end the string parameter with it and input your own SQL after.
|
||||
|
||||
=== It's your turn!
|
||||
You are an employee named 'John Smith' working for a big company. The company has an internal system that allows all employees to see their own internal data like the department they work in and their salary.
|
||||
|
||||
The system requires the employees to use a unique authentication TAN to view their data. +
|
||||
Your current TAN is '3SL99A'.
|
||||
|
||||
Since you always have the urge to be the most earning employee you want to exploit the system and instead of viewing your own internal data take a look at the data of all your colleagues to check their current salaries.
|
||||
|
||||
Use the form below and try to retrieve all the employee data from the employees table. You shouldn't need to know any specific names or TANs to get the information you need. +
|
||||
You already found out that the query performing your request looks like that:
|
||||
------------------------------------------------------------
|
||||
"select USERID, FIRST_NAME, LAST_NAME, CC_NUMBER, CC_TYPE, COOKIE, LOGIN_COUNT from users where LOGIN_COUNT > 0 and FIRST_NAME = ‘" + userName + "'";
|
||||
"SELECT * FROM employees WHERE last_name = '" + name + "' AND auth_tan = '" + auth_tan + "';
|
||||
------------------------------------------------------------
|
||||
|
||||
Using the form below try to retrieve all the users from the users table. You shouldn't need to know any specific user name to get the complete list.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user