diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionChallenge.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionChallenge.java
index 9890947de..ee6dab42a 100644
--- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionChallenge.java
+++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionChallenge.java
@@ -26,6 +26,7 @@ import static org.springframework.web.bind.annotation.RequestMethod.POST;
@AssignmentPath("SqlInjection/challenge")
@AssignmentHints(value = {"SqlInjectionChallenge1", "SqlInjectionChallenge2", "SqlInjectionChallenge3"})
@Slf4j
+@AssignmentHints(value ={"SqlInjectionChallengeHint1", "SqlInjectionChallengeHint2", "SqlInjectionChallengeHint3", "SqlInjectionChallengeHint4"})
public class SqlInjectionChallenge extends AssignmentEndpoint {
private static final String PASSWORD_TOM = "thisisasecretfortomonly";
diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java
index 5231895c7..8ed18fa7d 100644
--- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java
+++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java
@@ -1,11 +1,10 @@
-
package org.owasp.webgoat.plugin.advanced;
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.plugin.introduction.SqlInjectionLesson8;
+import org.owasp.webgoat.plugin.introduction.SqlInjectionLesson5a;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@@ -47,7 +46,7 @@ import java.sql.*;
* @created October 28, 2003
*/
@AssignmentPath("/SqlInjection/attack6a")
-@AssignmentHints(value = {"SqlStringInjectionHint6", "SqlStringInjectionHint7", "SqlStringInjectionHint8"})
+@AssignmentHints(value = {"SqlStringInjectionHint6a1", "SqlStringInjectionHint6a2", "SqlStringInjectionHint6a3", "SqlStringInjectionHint6a4"})
public class SqlInjectionLesson6a extends AssignmentEndpoint {
@RequestMapping(method = RequestMethod.POST)
@@ -60,9 +59,13 @@ public class SqlInjectionLesson6a extends AssignmentEndpoint {
protected AttackResult injectableQuery(String accountName) {
try {
+ boolean usedUnion = true;
Connection connection = DatabaseUtilities.getConnection(getWebSession());
String query = "SELECT * FROM user_data WHERE last_name = '" + accountName + "'";
-
+ //Check if Union is used
+ if(!accountName.matches("(?i)(^[^-/*;)]*)(\\s*)UNION(.*$)")) {
+ usedUnion = false;
+ }
try {
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
@@ -72,18 +75,19 @@ public class SqlInjectionLesson6a extends AssignmentEndpoint {
ResultSetMetaData resultsMetaData = results.getMetaData();
StringBuffer output = new StringBuffer();
- output.append(SqlInjectionLesson8.generateTable(results));
- if(! (query.toLowerCase().contains("union") || query.toLowerCase().contains("join")) )
- output.append("There is also a way to retrieve the Data by using a UNION or JOIN. Can you figure out, how this is done?");
+ output.append(SqlInjectionLesson5a.writeTable(results, resultsMetaData));
+ if(! usedUnion)
+ output.append("To succesfully complete this Assignement you have to use a UNION");
results.last();
// If they get back more than one user they succeeded
- if (results.getRow() >= 5) {
+ if (results.getRow() >= 5 && usedUnion) {
return trackProgress(success().feedback("sql-injection.6a.success").feedbackArgs(output.toString()).build());
+ } else if((output.toString().contains("dave") && output.toString().contains("passW0rD")) && !usedUnion) {
+ return trackProgress(failed().output("To succesfully complete this Assignement you have to use a UNION").build());
} else {
return trackProgress(failed().output(output.toString()).build());
}
-
} else {
return trackProgress(failed().feedback("sql-injection.6a.no.results").build());
@@ -96,4 +100,4 @@ public class SqlInjectionLesson6a extends AssignmentEndpoint {
return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build());
}
}
-}
+}
\ No newline at end of file
diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5a.java
new file mode 100644
index 000000000..68a11f38a
--- /dev/null
+++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5a.java
@@ -0,0 +1,126 @@
+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.io.IOException;
+import java.sql.*;
+
+
+/***************************************************************************************************
+ *
+ *
+ * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
+ * please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 20014 Bruce Mayhew
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Getting Source ==============
+ *
+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
+ * projects.
+ *
+ * For details, please see http://webgoat.github.io
+ *
+ * @author Bruce Mayhew WebGoat
+ * @created October 28, 2003
+ */
+@AssignmentPath("/SqlInjection/attack5a")
+public class SqlInjectionLesson5a extends AssignmentEndpoint {
+
+ @RequestMapping(method = RequestMethod.POST)
+ public
+ @ResponseBody
+ AttackResult completed(@RequestParam String account, @RequestParam String operator, @RequestParam String injection) {
+ return injectableQuery(account + " " + operator + " " + injection);
+ }
+
+ protected AttackResult injectableQuery(String accountName) {
+ try {
+ Connection connection = DatabaseUtilities.getConnection(getWebSession());
+ System.out.println(accountName);
+ String query = "SELECT * FROM user_data WHERE first_name = 'John' and last_name = '" + accountName + "'";
+ 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(writeTable(results, resultsMetaData));
+ results.last();
+
+ // If they get back more than one user they succeeded
+ if (results.getRow() >= 6) {
+ return trackProgress(success().feedback("sql-injection.5a.success").feedbackArgs(output.toString()).build());
+ } else {
+ return trackProgress(failed().output(output.toString()).build());
+ }
+ } else {
+ return trackProgress(failed().feedback("sql-injection.5a.no.results").build());
+
+ }
+ } catch (SQLException sqle) {
+
+ return trackProgress(failed().output(sqle.getMessage()).build());
+ }
+ } catch (Exception e) {
+ return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build());
+ }
+ }
+
+ public static String writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws IOException,
+ SQLException {
+ int numColumns = resultsMetaData.getColumnCount();
+ results.beforeFirst();
+ StringBuffer t = new StringBuffer();
+ t.append("
");
+
+ if (results.next()) {
+ for (int i = 1; i < (numColumns + 1); i++) {
+ t.append(resultsMetaData.getColumnName(i));
+ t.append(", ");
+ }
+
+ t.append("
");
+ results.beforeFirst();
+
+ while (results.next()) {
+
+ for (int i = 1; i < (numColumns + 1); i++) {
+ t.append(results.getString(i));
+ t.append(", ");
+ }
+
+ t.append("
");
+ }
+
+ } else {
+ t.append("Query Successful; however no data was returned from this query.");
+ }
+
+ t.append("
");
+ return (t.toString());
+ }
+}
\ No newline at end of file
diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5b.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5b.java
new file mode 100644
index 000000000..b0bececef
--- /dev/null
+++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5b.java
@@ -0,0 +1,109 @@
+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 javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.sql.*;
+
+
+/***************************************************************************************************
+ *
+ *
+ * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
+ * please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 20014 Bruce Mayhew
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Getting Source ==============
+ *
+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
+ * projects.
+ *
+ * For details, please see http://webgoat.github.io
+ *
+ * @author Bruce Mayhew WebGoat
+ * @created October 28, 2003
+ */
+@AssignmentPath("/SqlInjection/attack5b")
+@AssignmentHints(value = {"SqlStringInjectionHint5b1", "SqlStringInjectionHint5b2", "SqlStringInjectionHint5b3", "SqlStringInjectionHint5b4"})
+public class SqlInjectionLesson5b extends AssignmentEndpoint {
+
+ @RequestMapping(method = RequestMethod.POST)
+ public
+ @ResponseBody
+ AttackResult completed(@RequestParam String userid, @RequestParam String login_count, HttpServletRequest request) throws IOException {
+ return injectableQuery(login_count, userid);
+ }
+
+ protected AttackResult injectableQuery(String login_count, String accountName) {
+ try {
+ Connection connection = DatabaseUtilities.getConnection(getWebSession());
+ PreparedStatement query = connection.prepareStatement("SELECT * From user_data WHERE Login_Count = ? and userid= " + accountName, ResultSet.TYPE_SCROLL_INSENSITIVE,
+ ResultSet.CONCUR_READ_ONLY);
+
+ int count = 0;
+ try {
+ count = Integer.parseInt(login_count);
+ } catch(Exception e) {
+ return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build());
+ }
+
+ query.setInt(1, count);
+ //String query = "SELECT * FROM user_data WHERE Login_Count = " + login_count + " and userid = " + accountName, ;
+ System.err.println("Querry: " + query);
+ try {
+ Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
+ ResultSet.CONCUR_READ_ONLY);
+ ResultSet results = query.executeQuery();
+
+ if ((results != null) && (results.first() == true)) {
+ ResultSetMetaData resultsMetaData = results.getMetaData();
+ StringBuffer output = new StringBuffer();
+
+ output.append(SqlInjectionLesson5a.writeTable(results, resultsMetaData));
+ results.last();
+
+ // If they get back more than one user they succeeded
+ if (results.getRow() >= 6) {
+ return trackProgress(success().feedback("sql-injection.5b.success").feedbackArgs(output.toString()).build());
+ } else {
+ return trackProgress(failed().output(output.toString()).build());
+ }
+
+ } else {
+ return trackProgress(failed().feedback("sql-injection.5b.no.results").build());
+
+// output.append(getLabelManager().get("NoResultsMatched"));
+ }
+ } catch (SQLException sqle) {
+
+ return trackProgress(failed().output(sqle.getMessage()).build());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build());
+ }
+ }
+}
\ No newline at end of file
diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12a.java
index 896eec53c..1394cfd53 100644
--- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12a.java
+++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12a.java
@@ -33,8 +33,9 @@ public class SqlInjectionLesson12a extends AssignmentEndpoint {
@SneakyThrows
public AttackResult completed(@RequestParam String ip) {
Connection connection = DatabaseUtilities.getConnection(webSession);
- PreparedStatement preparedStatement = connection.prepareStatement("select ip from servers where hostname = 'webgoat-prd' and ip = ?");
+ PreparedStatement preparedStatement = connection.prepareStatement("select ip from servers where ip = ? and hostname = ?");
preparedStatement.setString(1, ip);
+ preparedStatement.setString(2, "webgoat-prd");
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
return trackProgress(success().build());
diff --git a/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjection.html b/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjection.html
index 39f8594e4..146625452 100644
--- a/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjection.html
+++ b/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjection.html
@@ -52,6 +52,79 @@
+
+
+
+
diff --git a/webgoat-lessons/sql-injection/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/sql-injection/src/main/resources/i18n/WebGoatLabels.properties
index 3472a053d..45825e4c1 100644
--- a/webgoat-lessons/sql-injection/src/main/resources/i18n/WebGoatLabels.properties
+++ b/webgoat-lessons/sql-injection/src/main/resources/i18n/WebGoatLabels.properties
@@ -12,9 +12,18 @@ SqlInjectionChallenge3=Use tooling to automate this attack
sql-injection.error=Sorry, this solution is not correct. Try again!
NoResultsMatched=No results matched. Try Again.
-SqlStringInjectionHint6=Try Appending a new SQL Statement to the Query.
-SqlStringInjectionHint7=The new SQL Statement can be really simple like: SELECT ... FROM ...
-SqlStringInjectionHint8=Your new SQL Query should start, with a " ; " and end with " -- "
+SqlInjectionChallengeHint1=The Table Name is randomized at each start of Webgoat, try to figure out the name first.
+SqlInjectionChallengeHint2=Find the Field which is vulnerable to SQL Injection use that to change the password.
+SqlInjectionChallengeHint3=Change the password through an Update Statement.
+SqlInjectionChallengeHint4=The Vulnerable Field is the Username Field of the Register form.
+SqlStringInjectionHint5b1=Try to check which of the input fields is susceptible to an injection attack.
+SqlStringInjectionHint5b2=Insert 0 or 1 = 1 into the first input field. Th Output should tell you if this field is injectable.
+SqlStringInjectionHint5b3=The first Input field is not susceptible to sql injection.
+SqlStringInjectionHint5b4=You don't need to insert any quotations into your injection-string.
+SqlStringInjectionHint6a1=Try Appending stuff like ",1" to your query, to figure out how many columns there are.
+SqlStringInjectionHint6a2=When using a UNION the number of columns, from both tables should match.
+SqlStringInjectionHint6a3=The UNION should contain 7 columns.
+SqlStringInjectionHint6a4=Try using these columns in your union: userid, user_name, password, cookie, cookie, cookie, userid.
SqlStringInjectionHint9=Try sorting and look at the request
SqlStringInjectionHint10=Intercept the request and try to specify a different order by
SqlStringInjectionHint10a1=First establish a connection, after that you can create a statement.
diff --git a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content6a.adoc b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content6a.adoc
index 7dc74e14c..8256ad1ff 100644
--- a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content6a.adoc
+++ b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content6a.adoc
@@ -1,6 +1,8 @@
== Try It! Pulling data from other tables
-Lets try to exploit the fact that you can append your own SQL Statement. One of the tables in the WebGoat database is:
+Lets try to exploit the fact that you can use a union to get the contents of another table.
+
+One of the tables in the WebGoat database is:
-------------------------------------------------------
CREATE TABLE user_system_data (userid int not null primary key,
@@ -9,7 +11,5 @@ CREATE TABLE user_system_data (userid int not null primary key,
cookie varchar(30));
-------------------------------------------------------
-*6.a)* Inject your own Query into the SQL Statement to retrieve all Data from the Table. +
-*6.b)* When you have figured it out.... What is Dave's password?
-
-
+*6.a)* Retrieve all data from the table by using a UNION (You have to use a union to complete this assignment.) +
+*6.b)* When you have figured it out.... What is Dave's password?
\ No newline at end of file
diff --git a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content11.adoc b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content11.adoc
new file mode 100644
index 000000000..a73fdc660
--- /dev/null
+++ b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content11.adoc
@@ -0,0 +1,9 @@
+== 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 builds a dynamic query by concatenating strings making it susceptible to String SQL injection:
+
+------------------------------------------------------------
+"select * from users where LOGIN_COUNT > 0 and FIRST_NAME = ‘" + userName + "'";
+------------------------------------------------------------
+
+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.
diff --git a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content12.adoc b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content12.adoc
new file mode 100644
index 000000000..7dbbc5ae4
--- /dev/null
+++ b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content12.adoc
@@ -0,0 +1,11 @@
+== 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 builds a dynamic query by concatenating a number making it susceptible to Numeric SQL injection:
+
+--------------------------------------------------
+"select * from users where Login_Count = " + Login_Count + " and USERID = " + UserID;
+--------------------------------------------------
+
+Using the two Input Fields below, try to retrieve all the date from the users table.
+
+Warning: Only one of these fields is susceptible to SQL Injection. You need to find out which, to successfully retrieve all the data.
\ No newline at end of file
diff --git a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_order_by.adoc b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_order_by.adoc
index 6e8ff54e0..d4806d1ed 100644
--- a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_order_by.adoc
+++ b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_order_by.adoc
@@ -2,4 +2,6 @@ In this assignment try to perform an SQL injection through the ORDER BY field.
Try to find the ip address of the `webgoat-prd` server, guessing the complete
ip address might take too long so we give you the last part: `xxx.130.219.202`
+Tip: To complete this assignment a tool such as OWASP ZAP is required.
+
Note: The submit field of this assignment is *NOT* vulnerable for an SQL injection.
\ No newline at end of file