diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/BlindNumericSqlInjection.java b/main/project/JavaSource/org/owasp/webgoat/lessons/BlindNumericSqlInjection.java
new file mode 100644
index 000000000..f67bb653f
--- /dev/null
+++ b/main/project/JavaSource/org/owasp/webgoat/lessons/BlindNumericSqlInjection.java
@@ -0,0 +1,273 @@
+package org.owasp.webgoat.lessons;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.html.A;
+import org.apache.ecs.html.IMG;
+import org.apache.ecs.html.Input;
+import org.apache.ecs.html.P;
+import org.owasp.webgoat.session.DatabaseUtilities;
+import org.owasp.webgoat.session.ECSFactory;
+import org.owasp.webgoat.session.WebSession;
+
+/*******************************************************************************
+ *
+ *
+ * This file is part of WebGoat, an Open Web Application Security Project
+ * utility. For details, please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 2007 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 code.google.com, a repository
+ * for free software projects.
+ *
+ * For details, please see http://code.google.com/p/webgoat/
+ *
+ * @author Chuck Willis Chuck's web
+ * site (this lesson is heavily based on Bruce Mayhews' SQL
+ * Injection lesson
+ * @created January 14, 2005
+ */
+public class BlindNumericSqlInjection extends LessonAdapter
+{
+
+ public final static A MANDIANT_LOGO = new A().setHref("http://www.mandiant.com").addElement(new IMG("images/logos/mandiant.png").setAlt("MANDIANT").setBorder(0).setHspace(0).setVspace(0));
+
+ private final static String ACCT_NUM = "account_number";
+
+ private final static String TARGET_CC_NUM = "1111222233334444";
+
+ /**
+ * Description of the Method
+ *
+ * @param s
+ * Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent(WebSession s)
+ {
+ ElementContainer ec = new ElementContainer();
+
+ try
+ {
+ Connection connection = DatabaseUtilities.getConnection(s);
+
+ ec.addElement(new P().addElement("Enter your Account Number: "));
+
+ String accountNumber = s.getParser().getRawParameter(ACCT_NUM, "101");
+ Input input = new Input(Input.TEXT, ACCT_NUM, accountNumber.toString());
+ ec.addElement(input);
+
+ Element b = ECSFactory.makeButton("Go!");
+ ec.addElement(b);
+
+ String query = "SELECT * FROM user_data WHERE userid = " + accountNumber;
+ String answer_query;
+// if (runningOnWindows())
+// {
+// answer_query = "SELECT TOP 1 first_name FROM user_data WHERE userid = "
+// + TARGET_CC_NUM;
+// } else
+// {
+ answer_query = "SELECT pin FROM pins WHERE cc_number = '" + TARGET_CC_NUM + "'";
+// }
+
+ try
+ {
+ Statement answer_statement = connection.createStatement(
+ ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
+ ResultSet answer_results = answer_statement.executeQuery(answer_query);
+ answer_results.first();
+ System.out.println("Account: " + accountNumber );
+ System.out.println("Answer : " + answer_results.getString(1));
+ if (accountNumber.toString().equals(answer_results.getString(1)))
+ {
+ makeSuccess(s);
+ } else
+ {
+
+ Statement statement = connection.createStatement(
+ ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
+ ResultSet results = statement.executeQuery(query);
+
+ if ((results != null) && (results.first() == true))
+ {
+ ec.addElement(new P().addElement("Account number is valid."));
+ } else
+ {
+ ec.addElement(new P().addElement("Invalid account number."));
+ }
+ }
+ }
+ catch (SQLException sqle)
+ {
+ ec.addElement(new P().addElement("An error occurred, please try again."));
+ }
+ }
+ catch (Exception e)
+ {
+ s.setMessage("Error generating " + this.getClass().getName());
+ e.printStackTrace();
+ }
+
+ return (ec);
+ }
+
+ /**
+ * Gets the category attribute of the SqlInjection object
+ *
+ * @return The category value
+ */
+ protected Category getDefaultCategory()
+ {
+ return Category.INJECTION;
+ }
+
+ /**
+ * Gets the credits attribute of the AbstractLesson object
+ *
+ * @return The credits value
+ */
+ public Element getCredits()
+ {
+ return super.getCustomCredits("Created by Chuck Willis ", MANDIANT_LOGO);
+ }
+
+ /**
+ * Gets the hints attribute of the DatabaseFieldScreen object
+ *
+ * @return The hints value
+ */
+ protected List getHints(WebSession s)
+ {
+ List hints = new ArrayList();
+// if (runningOnWindows())
+// {
+ hints
+ .add("Compound SQL statements can be made by joining multiple tests with keywords like AND and OR. "
+ + "Create a SQL statement that you can use as a true/false test and then "
+ + "start narrowing down the number using > and <"
+ + "
The backend database is HSQLDB, but this shouldn't make any difference because "
+ + "you can solve this lesson with standard SQL syntax.");
+
+ hints
+ .add("The application is taking your input and inserting it at the end of a pre-formed SQL command. "
+ + "You will need to make use of the following SQL functions: "
+ + "
AND - combine the logic of the normal query with a boolean result"
+ + "
( and ) - group subexpressions so they evaluate properly"
+ + "
SELECT - make a subquery for your target data and get a number"
+ + "
> and = and < - once you have the number, compare it to a choosen one");
+
+ hints.add("This is the code for the query being built and issued by WebGoat:
"
+ + "\"SELECT * FROM user_data WHERE userid = \" + accountNumber ");
+ hints
+ .add("Here is an example for another table:"
+ + "
In the table user_data, is the userid for the record with a cc_number of "
+ + "333498703333"
+ + " greater than 100? "
+ + "
101 AND ((SELECT userid FROM user_data WHERE cc_number='"
+ + "333498703333"
+ + "') > 100 ); "
+ + "
If you get back that account number is valid, then yes. If get back that the number is "
+ + "invalid then answer is no.");
+ hints
+ .add("Partial Solution:"
+ + "
Is the pin of the record with a cc_number of "
+ + TARGET_CC_NUM
+ + " greater than 1000? "
+ + "
101 AND ((SELECT pin FROM pins WHERE cc_number='"
+ + TARGET_CC_NUM
+ + "') > 1000 ); "
+ + "
If you get back that account number is valid, then yes. If get back that the number is "
+ + "invalid then answer is no.");
+ hints
+ .add("Another Part of Solution:"
+ + "
Is the pin of the record with a cc_number of "
+ + TARGET_CC_NUM
+ + " greater than 10000? "
+ + "
101 AND ((SELECT pin FROM pins WHERE cc_number='"
+ + TARGET_CC_NUM
+ + "') > 10000 ); "
+ + "
If you get back that account number is valid, then yes. If get back that the number is "
+ + "invalid then answer is no.");
+
+ return hints;
+ }
+
+ /**
+ * Gets the instructions attribute of the SqlInjection object
+ *
+ * @return The instructions value
+ */
+ public String getInstructions(WebSession s)
+ {
+ String instructions = "The form below allows a user to enter an account number and determine if "
+ + "it is valid or not. Use this form to develop a true / false test check other entries in the database. "
+ + "
The goal is to find the value of "
+ + "the field pin in table pins for the row with the cc_number of "
+ + TARGET_CC_NUM
+ + ". The field is of type int, which is an integer."
+ + "
Put the discovered pin value in the form to pass the lesson.";
+
+ return (instructions);
+ }
+
+ private final static Integer DEFAULT_RANKING = new Integer(90);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ /**
+ * Gets the title attribute of the DatabaseFieldScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ("Blind Numeric SQL Injection");
+ }
+
+ /**
+ * Constructor for the DatabaseFieldScreen object
+ *
+ * @param s
+ * Description of the Parameter
+ */
+ public void handleRequest(WebSession s)
+ {
+ try
+ {
+ super.handleRequest(s);
+ }
+ catch (Exception e)
+ {
+ System.out.println("Exception caught: " + e);
+ e.printStackTrace(System.out);
+ }
+ }
+}
diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/BlindSqlInjection.java b/main/project/JavaSource/org/owasp/webgoat/lessons/BlindSqlInjection.java
deleted file mode 100644
index 974abb709..000000000
--- a/main/project/JavaSource/org/owasp/webgoat/lessons/BlindSqlInjection.java
+++ /dev/null
@@ -1,237 +0,0 @@
-
-package org.owasp.webgoat.lessons;
-
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.ecs.Element;
-import org.apache.ecs.ElementContainer;
-import org.apache.ecs.StringElement;
-import org.apache.ecs.html.Input;
-import org.apache.ecs.html.P;
-import org.owasp.webgoat.session.DatabaseUtilities;
-import org.owasp.webgoat.session.ECSFactory;
-import org.owasp.webgoat.session.WebSession;
-
-
-/***************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 2007 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 code.google.com, a repository for free software
- * projects.
- *
- * For details, please see http://code.google.com/p/webgoat/
- *
- * @author Chuck Willis Chuck's web site (this lesson
- * is heavily based on Bruce Mayhews' SQL Injection lesson
- * @created January 14, 2005
- */
-public class BlindSqlInjection extends LessonAdapter
-{
-
- private final static String ACCT_NUM = "account_number";
-
- private final static int TARGET_ACCT_NUM = 15613;
-
- /**
- * Description of the Method
- *
- * @param s
- * Description of the Parameter
- * @return Description of the Return Value
- */
- protected Element createContent(WebSession s)
- {
- ElementContainer ec = new ElementContainer();
-
- try
- {
- Connection connection = DatabaseUtilities.getConnection(s);
-
- ec.addElement(new P().addElement("Enter your Account Number: "));
-
- String accountNumber = s.getParser().getRawParameter(ACCT_NUM, "101");
- Input input = new Input(Input.TEXT, ACCT_NUM, accountNumber.toString());
- ec.addElement(input);
-
- Element b = ECSFactory.makeButton("Go!");
- ec.addElement(b);
-
- String query = "SELECT * FROM user_data WHERE userid = " + accountNumber;
- String answer_query;
- answer_query = "SELECT TOP 1 first_name FROM user_data WHERE userid = " + TARGET_ACCT_NUM;
-
- try
- {
- Statement answer_statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
- ResultSet.CONCUR_READ_ONLY);
- ResultSet answer_results = answer_statement.executeQuery(answer_query);
- answer_results.first();
- // System.out.println("Account: " + accountNumber);
- // System.out.println("Answer : " + answer_results.getString(1));
- if (accountNumber.toString().equals(answer_results.getString(1)))
- {
- makeSuccess(s);
- }
- else
- {
-
- Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
- ResultSet.CONCUR_READ_ONLY);
- ResultSet results = statement.executeQuery(query);
-
- if ((results != null) && (results.first() == true))
- {
- ec.addElement(new P().addElement("Account number is valid"));
- }
- else
- {
- ec.addElement(new P().addElement("Invalid account number"));
- }
- }
- } catch (SQLException sqle)
- {
- ec.addElement(new P().addElement("An error occurred, please try again."));
- }
- } catch (Exception e)
- {
- s.setMessage("Error generating " + this.getClass().getName());
- e.printStackTrace();
- }
-
- return (ec);
- }
-
- /**
- * Gets the category attribute of the SqlInjection object
- *
- * @return The category value
- */
- protected Category getDefaultCategory()
- {
- return Category.INJECTION;
- }
-
- /**
- * Gets the credits attribute of the AbstractLesson object
- *
- * @return The credits value
- */
- public Element getCredits()
- {
- return new StringElement("By Chuck Willis");
- }
-
- /**
- * Gets the hints attribute of the DatabaseFieldScreen object
- *
- * @return The hints value
- */
- protected List getHints(WebSession s)
- {
- List hints = new ArrayList();
- hints.add("Compound SQL statements can be made by joining multiple tests with keywords like AND and OR. "
- + "Create a SQL statement that you can use as a true/false test and then "
- + "select the first character of the target element and do a start narrowing "
- + "down the character using > and <"
- + "
The backend database is HSQLDB. Keep that in mind if you research SQL functions "
- + "on the Internet since different databases use some different functions and syntax.");
- hints.add("This is the code for the query being built and issued by WebGoat:
"
- + "\"SELECT * FROM user_data WHERE userid = \" + accountNumber ");
- hints.add("The application is taking your input and inserting it at the end of a pre-formed SQL command. "
- + "You will need to make use of the following SQL functions: "
- + "
SELECT - query for your target data and get a string "
- + "
substr(string, start, length) - returns a "
- + "substring of string starting at the start character and going for length characters "
- + "
ascii(string) will return the ascii value of the first character in string "
- + "
> and < - once you have a character's value, compare it to a choosen one");
- hints.add("Example: is the first character of the first_name of userid " + TARGET_ACCT_NUM
- + " less than 'M' (ascii 77)? "
- + "
101 AND (ascii( substr((SELECT first_name FROM user_data WHERE userid=" + TARGET_ACCT_NUM
- + ") , 1 , 1) ) < 77 ); "
- + "
If you get back that account number is valid, then yes. If get back that the number is"
- + "invalid then answer is no.");
- hints.add("Another example: is the second character of the first_name of userid " + TARGET_ACCT_NUM
- + " greater than 'm' (ascii 109)? "
- + "
101 AND (ascii( substr((SELECT first_name FROM user_data WHERE userid=" + TARGET_ACCT_NUM
- + ") , 2 , 1) ) > 109 ); "
- + "
If you get back that account number is valid, then yes. If get back that the number is "
- + "invalid then answer is no.");
- return hints;
- }
-
- /**
- * Gets the instructions attribute of the SqlInjection object
- *
- * @return The instructions value
- */
- public String getInstructions(WebSession s)
- {
- String instructions = "The form below allows a user to enter an account number and determine if "
- + "it is valid or not. Use this form to develop a true / false test check other entries in the database. "
- + "
Reference Ascii Values: 'A' = 65 'Z' = 90 'a' = 97 'z' = 122 "
- + "
The goal is to find the value of " + "the first_name in table user_data for userid "
- + TARGET_ACCT_NUM
- + ". Put the discovered name in the form to pass the lesson. Only the discovered name "
- + "should be put into the form field, paying close attention to the spelling and capitalization.";
-
- return (instructions);
- }
-
- private final static Integer DEFAULT_RANKING = new Integer(70);
-
- protected Integer getDefaultRanking()
- {
- return DEFAULT_RANKING;
- }
-
- /**
- * Gets the title attribute of the DatabaseFieldScreen object
- *
- * @return The title value
- */
- public String getTitle()
- {
- return ("Blind SQL Injection");
- }
-
- /**
- * Constructor for the DatabaseFieldScreen object
- *
- * @param s
- * Description of the Parameter
- */
- public void handleRequest(WebSession s)
- {
- try
- {
- super.handleRequest(s);
- } catch (Exception e)
- {
- // System.out.println("Exception caught: " + e);
- e.printStackTrace(System.out);
- }
- }
-}
diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/BlindStringSqlInjection.java b/main/project/JavaSource/org/owasp/webgoat/lessons/BlindStringSqlInjection.java
new file mode 100644
index 000000000..1d58f840a
--- /dev/null
+++ b/main/project/JavaSource/org/owasp/webgoat/lessons/BlindStringSqlInjection.java
@@ -0,0 +1,322 @@
+package org.owasp.webgoat.lessons;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.html.Input;
+import org.apache.ecs.html.P;
+import org.apache.ecs.html.A;
+import org.apache.ecs.html.IMG;
+import org.owasp.webgoat.session.DatabaseUtilities;
+import org.owasp.webgoat.session.ECSFactory;
+import org.owasp.webgoat.session.WebSession;
+
+/*******************************************************************************
+ *
+ *
+ * This file is part of WebGoat, an Open Web Application Security Project
+ * utility. For details, please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 2007 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 code.google.com, a repository
+ * for free software projects.
+ *
+ * For details, please see http://code.google.com/p/webgoat/
+ *
+ * @author Chuck Willis Chuck's web
+ * site (this lesson is heavily based on Bruce Mayhews' SQL
+ * Injection lesson
+ * @created January 14, 2005
+ */
+public class BlindStringSqlInjection extends LessonAdapter
+{
+
+ public final static A MANDIANT_LOGO = new A().setHref("http://www.mandiant.com").addElement(new IMG("images/logos/mandiant.png").setAlt("MANDIANT").setBorder(0).setHspace(0).setVspace(0));
+
+ private final static String ACCT_NUM = "account_number";
+
+ private final static String TARGET_CC_NUM = "4321432143214321";
+
+ /**
+ * Description of the Method
+ *
+ * @param s
+ * Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent(WebSession s)
+ {
+ ElementContainer ec = new ElementContainer();
+
+ try
+ {
+ Connection connection = DatabaseUtilities.getConnection(s);
+
+ ec.addElement(new P().addElement("Enter your Account Number: "));
+
+ String accountNumber = s.getParser().getRawParameter(ACCT_NUM, "101");
+ Input input = new Input(Input.TEXT, ACCT_NUM, accountNumber.toString());
+ ec.addElement(input);
+
+ Element b = ECSFactory.makeButton("Go!");
+ ec.addElement(b);
+
+ String query = "SELECT * FROM user_data WHERE userid = " + accountNumber;
+ String answer_query;
+// if (runningOnWindows())
+// {
+// answer_query = "SELECT TOP 1 first_name FROM user_data WHERE userid = "
+// + TARGET_CC_NUM;
+// } else
+// {
+ answer_query = "SELECT name FROM pins WHERE cc_number = '" + TARGET_CC_NUM +"'";
+// }
+
+ try
+ {
+ Statement answer_statement = connection.createStatement(
+ ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
+ ResultSet answer_results = answer_statement.executeQuery(answer_query);
+ answer_results.first();
+ System.out.println("Account: " + accountNumber );
+ System.out.println("Answer : " + answer_results.getString(1));
+ if (accountNumber.toString().equals(answer_results.getString(1)))
+ {
+ makeSuccess(s);
+ } else
+ {
+
+ Statement statement = connection.createStatement(
+ ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
+ ResultSet results = statement.executeQuery(query);
+
+ if ((results != null) && (results.first() == true))
+ {
+ ec.addElement(new P().addElement("Account number is valid"));
+ } else
+ {
+ ec.addElement(new P().addElement("Invalid account number"));
+ }
+ }
+ }
+ catch (SQLException sqle)
+ {
+ ec.addElement(new P().addElement("An error occurred, please try again."));
+
+ // comment out two lines below
+ ec.addElement(new P().addElement(sqle.getMessage()));
+ sqle.printStackTrace();
+
+ }
+ }
+ catch (Exception e)
+ {
+ s.setMessage("Error generating " + this.getClass().getName());
+ e.printStackTrace();
+ }
+
+ return (ec);
+ }
+
+ /**
+ * Gets the category attribute of the SqlInjection object
+ *
+ * @return The category value
+ */
+ protected Category getDefaultCategory()
+ {
+ return Category.INJECTION;
+ }
+
+ /**
+ * Gets the credits attribute of the AbstractLesson object
+ *
+ * @return The credits value
+ */
+ public Element getCredits()
+ {
+ return super.getCustomCredits("Created by Chuck Willis ", MANDIANT_LOGO);
+ }
+
+ /**
+ *
+ * Determines the OS that WebGoat is running on. Needed because different DB
+ * backends are used on the different OSes (Access on Windows, InstantDB on
+ * others)
+ *
+ * @return true if running on Windows, false otherwise
+ */
+// private boolean runningOnWindows()
+// {
+// String os = System.getProperty("os.name", "Windows");
+// if (os.toLowerCase().indexOf("window") != -1)
+// {
+// return true;
+// } else
+// {
+// return false;
+// }
+// }
+
+ /**
+ * Gets the hints attribute of the DatabaseFieldScreen object
+ *
+ * @return The hints value
+ */
+ protected List getHints(WebSession s)
+ {
+ List hints = new ArrayList();
+// if (runningOnWindows())
+// {
+ hints
+ .add("Compound SQL statements can be made by joining multiple tests with keywords like AND and OR. "
+ + "Create a SQL statement that you can use as a true/false test and then "
+ + "select the first character of the target element and do a start narrowing "
+ + "down the character using > and <"
+ + "
The backend database is HSQLDB. Keep that in mind if you research SQL functions "
+ + "on the Internet since different databases use some different functions and syntax."
+
+ + "
You can find more about HSQLDB's SQL Syntax at "
+ + "http://hsqldb.org/doc/guide/ch09.html. "
+ + "Pay attention to the section titled \"String built-in Functions / Stored Procedures\".");
+
+ hints
+ .add("The application is taking your input and inserting it at the end of a pre-formed SQL command. "
+ + "You will need to make use of the following SQL contstructs: "
+
+ + "
AND - combine the logic of the normal query with a boolean result"
+ + "
( and ) - group subexpressions so they evaluate properly"
+ + "
SELECT - make a subquery for your target data and get a string "
+ + "
SUBSTRING(string, start, length) - returns a "
+ + "substring of string starting at the start character and going for length characters "
+ + "
> and = and < - once you have a character's value, compare it to a choosen one"
+ + "
You can find more about HSQLDB's SQL Syntax at "
+ + "http://hsqldb.org/doc/guide/ch09.html");
+
+ hints.add("This is the code for the query being built and issued by WebGoat:
"
+ + "\"SELECT * FROM user_data WHERE userid = \" + accountNumber ");
+
+ hints
+ .add("Here is an example for another table:"
+ + "
In the table user_data, is the first character of the first_name for the record with a cc_number of "
+ + "333498703333"
+ + " greater than 'M'? "
+ + "
101 AND (SUBSTRING((SELECT first_name FROM user_data WHERE cc_number='"
+ + "333498703333"
+ + "'), 1, 1) > 'M' ); "
+ + "
If you get back that account number is valid, then yes. If get back that the number is "
+ + "invalid then answer is no.");
+ hints
+ .add("Partial Solution for First Character:"
+ + "
Is the first character of the name of the record with a cc_number of "
+ + TARGET_CC_NUM
+ + " less than 'M'? "
+ + "
101 AND (SUBSTRING((SELECT name FROM pins WHERE cc_number='"
+ + TARGET_CC_NUM
+ + "'), 1, 1) < 'M' ); "
+ + "
If you get back that account number is valid, then yes. If get back that the number is "
+ + "invalid then answer is no.");
+ hints
+ .add("Another Part of Solution for First Character:"
+ + "
Is the first character of the name of the record with a cc_number of "
+ + TARGET_CC_NUM
+ + " less than 'H'? "
+ + "
101 AND (SUBSTRING((SELECT name FROM pins WHERE cc_number='"
+ + TARGET_CC_NUM
+ + "'), 1, 1) < 'H' ); "
+ + "
If you get back that account number is valid, then yes. If get back that the number is "
+ + "invalid then answer is no.");
+ hints
+ .add("Partial Solution for Second Character:"
+ + "
Is the second character of the name of the record with a cc_number of "
+ + TARGET_CC_NUM
+ + " greater than 'k'? "
+ + "
101 AND (SUBSTRING((SELECT name FROM pins WHERE cc_number='"
+ + TARGET_CC_NUM
+ + "'), 2, 1) > 'k' ); "
+ + "
If you get back that account number is valid, then yes. If get back that the number is "
+ + "invalid then answer is no.");
+
+
+ return hints;
+ }
+
+ /**
+ * Gets the instructions attribute of the SqlInjection object
+ *
+ * @return The instructions value
+ */
+ public String getInstructions(WebSession s)
+ {
+ String instructions = "The form below allows a user to enter an account number and determine if "
+ + "it is valid or not. Use this form to develop a true / false test check other entries in the database. "
+ + "
Reference Ascii Values: 'A' = 65 'Z' = 90 'a' = 97 'z' = 122 "
+ + "
The goal is to find the value of "
+ + "the field name in table pins for the row with the cc_number of "
+ + TARGET_CC_NUM
+ + ". The field is of type varchar, which is a string."
+ + "
Put the discovered name in the form to pass the lesson. Only the discovered name "
+ + "should be put into the form field, paying close attention to the spelling and capitalization.";
+
+ return (instructions);
+ }
+
+ private final static Integer DEFAULT_RANKING = new Integer(95);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ /**
+ * Gets the title attribute of the DatabaseFieldScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ("Blind String SQL Injection");
+ }
+
+ /**
+ * Constructor for the DatabaseFieldScreen object
+ *
+ * @param s
+ * Description of the Parameter
+ */
+ public void handleRequest(WebSession s)
+ {
+ try
+ {
+ super.handleRequest(s);
+ }
+ catch (Exception e)
+ {
+ System.out.println("Exception caught: " + e);
+ e.printStackTrace(System.out);
+ }
+ }
+}
diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/Category.java b/main/project/JavaSource/org/owasp/webgoat/lessons/Category.java
index 87a14c8a6..90b24335b 100644
--- a/main/project/JavaSource/org/owasp/webgoat/lessons/Category.java
+++ b/main/project/JavaSource/org/owasp/webgoat/lessons/Category.java
@@ -69,13 +69,15 @@ public class Category implements Comparable
public final static Category INSECURE_STORAGE = new Category("Insecure Storage", new Integer(1500));
- public final static Category PARAMETER_TAMPERING = new Category("Parameter Tampering", new Integer(1600));
+ public final static Category MALICIOUS_EXECUTION = new Category("Malicious Execution", new Integer(1600));
+
+ public final static Category PARAMETER_TAMPERING = new Category("Parameter Tampering", new Integer(1700));
- public final static Category SESSION_MANAGEMENT = new Category("Session Management Flaws", new Integer(1700));
+ public final static Category SESSION_MANAGEMENT = new Category("Session Management Flaws", new Integer(1800));
- public final static Category WEB_SERVICES = new Category("Web Services", new Integer(1800));
+ public final static Category WEB_SERVICES = new Category("Web Services", new Integer(1900));
- public final static Category ADMIN_FUNCTIONS = new Category("Admin Functions", new Integer(1900));
+ public final static Category ADMIN_FUNCTIONS = new Category("Admin Functions", new Integer(2000));
public final static Category CHALLENGE = new Category("Challenge", new Integer(3000));
@@ -95,6 +97,7 @@ public class Category implements Comparable
categories.add(XSS);
categories.add(BUFFER_OVERFLOW);
categories.add(INJECTION);
+ categories.add(MALICIOUS_EXECUTION);
categories.add(ERROR_HANDLING);
categories.add(INSECURE_STORAGE);
categories.add(DOS);
diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/MaliciousFileExecution.java b/main/project/JavaSource/org/owasp/webgoat/lessons/MaliciousFileExecution.java
new file mode 100644
index 000000000..299386c91
--- /dev/null
+++ b/main/project/JavaSource/org/owasp/webgoat/lessons/MaliciousFileExecution.java
@@ -0,0 +1,501 @@
+package org.owasp.webgoat.lessons;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+import java.io.File;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.html.Form;
+import org.apache.ecs.html.H1;
+import org.apache.ecs.html.Input;
+import org.apache.ecs.html.P;
+import org.apache.ecs.html.A;
+import org.apache.ecs.html.IMG;
+import org.owasp.webgoat.session.DatabaseUtilities;
+import org.owasp.webgoat.session.ECSFactory;
+import org.owasp.webgoat.session.WebSession;
+
+import org.apache.commons.fileupload.*;
+import org.apache.commons.fileupload.disk.*;
+import org.apache.commons.fileupload.servlet.*;
+
+/*******************************************************************************
+ *
+ *
+ * This file is part of WebGoat, an Open Web Application Security Project
+ * utility. For details, please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 2007 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 code.google.com, a repository
+ * for free software projects.
+ *
+ * For details, please see http://code.google.com/p/webgoat/
+ *
+ * @author Chuck Willis of MANDIANT
+ * @created July 11, 2008
+ */
+public class MaliciousFileExecution extends LessonAdapter
+{
+
+ private final static A MANDIANT_LOGO = new A().setHref("http://www.mandiant.com").addElement(new IMG("images/logos/mandiant.png").setAlt("MANDIANT").setBorder(0).setHspace(0).setVspace(0));
+
+ // the UPLOADS_DIRECTORY is where uploads are stored such that they can be references
+ // in image tags as "uploads/filename.ext". This directory string should not contain any path separators (/ or \)
+ private String uploads_and_target_parent_directory = null;
+
+ private final static String UPLOADS_RELATIVE_PATH = "uploads";
+
+ // this is the target directory that the user must put a file in to pass the lessson. The file must be named
+ // username.txt. This directory string should not contain any path separators (/ or \)
+
+ private final static String TARGET_RELATIVE_PATH = "mfe_target";
+
+ // this should probably go in a constructor, but we need the session object...
+ // may be able to do something like:
+ // String directory = this.getServletContext().getRealPath("/");
+ private void fill_uploads_and_target_parent_directory(WebSession s) {
+ //uploads_and_target_parent_directory = s.getWebgoatContext().getServlet().getServletContext().getRealPath("/");
+ uploads_and_target_parent_directory = s.getContext().getRealPath("/");
+ // make sure it ends with a / or \
+ if(!uploads_and_target_parent_directory.endsWith(File.separator)) {
+ uploads_and_target_parent_directory = uploads_and_target_parent_directory +
+ File.separator;
+ }
+ System.out.println("uploads_and_target_parent_directory set to = "
+ + uploads_and_target_parent_directory);
+
+ // make sure the directories exist
+ File uploads_dir = new File(uploads_and_target_parent_directory
+ + UPLOADS_RELATIVE_PATH);
+ uploads_dir.mkdir();
+
+ File target_dir = new File(uploads_and_target_parent_directory
+ + TARGET_RELATIVE_PATH);
+ target_dir.mkdir();
+
+ // delete the user's target file if it is already there since we must
+ // have restarted webgoat
+ File userfile = new File(uploads_and_target_parent_directory
+ + TARGET_RELATIVE_PATH + java.io.File.separator
+ + s.getUserName() + ".txt");
+
+ userfile.delete();
+
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @param s
+ * Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent(WebSession s)
+ {
+
+ if(uploads_and_target_parent_directory == null) {
+ fill_uploads_and_target_parent_directory(s);
+ }
+
+
+ ElementContainer ec = new ElementContainer();
+
+ try
+ {
+
+ // check for success - see if the target file exists yet
+
+ File userfile = new File(uploads_and_target_parent_directory
+ + TARGET_RELATIVE_PATH + java.io.File.separator
+ + s.getUserName() + ".txt");
+
+ if(userfile.exists()) {
+ makeSuccess(s);
+ }
+
+ Connection connection = DatabaseUtilities.getConnection(s);
+
+ ec.addElement(new H1().addElement("WebGoat Image Storage"));
+
+ // show the current image
+ ec.addElement(new P().addElement("Your current image:"));
+
+ String image_query = "SELECT image_relative_url FROM mfe_images WHERE user_name = '"
+ + s.getUserName() + "'";
+
+ Statement image_statement = connection.createStatement(
+ ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
+ ResultSet image_results = image_statement.executeQuery(image_query);
+
+ if(image_results.next() == false) {
+ // result set was empty
+ ec.addElement(new P().addElement("No image uploaded"));
+ System.out.println("No image uploaded");
+ } else {
+
+ String image_url = image_results.getString(1);
+
+ ec.addElement(new IMG(image_url).setBorder(0).setHspace(0).setVspace(0));
+
+ System.out.println("Found image named: " + image_url);
+
+ }
+
+ ec.addElement(new P().addElement("Upload a new image:"));
+
+ Input input = new Input(Input.FILE, "myfile", "");
+ ec.addElement(input);
+
+ Element b = ECSFactory.makeButton("Start Upload");
+ ec.addElement(b);
+
+ }
+ catch (Exception e)
+ {
+ s.setMessage("Error generating " + this.getClass().getName());
+ e.printStackTrace();
+ }
+
+ return (ec);
+ }
+
+ /**
+ * Gets the category attribute of the SqlInjection object
+ *
+ * @return The category value
+ */
+ protected Category getDefaultCategory()
+ {
+ return Category.MALICIOUS_EXECUTION;
+ }
+
+ /**
+ * Gets the credits attribute of the AbstractLesson object
+ *
+ * @return The credits value
+ */
+ public Element getCredits()
+ {
+ return super.getCustomCredits("Created by Chuck Willis ", MANDIANT_LOGO);
+ }
+
+ /**
+ * Gets the hints attribute of the DatabaseFieldScreen object
+ *
+ * @return The hints value
+ */
+ protected List getHints(WebSession s)
+ {
+ if(uploads_and_target_parent_directory == null) {
+ fill_uploads_and_target_parent_directory(s);
+ }
+
+ String target_filename = uploads_and_target_parent_directory
+ + TARGET_RELATIVE_PATH
+ + java.io.File.separator
+ + s.getUserName() + ".txt";
+
+ List hints = new ArrayList();
+
+ hints.add("Where are uploaded images stored? Can you browse to them directly?");
+
+ hints.add("What type of file can you upload to a J2EE server that will be executed when you browse to it?");
+
+ hints.add("You want to upload a .jsp file that creates an instance of the class java.io.File " +
+ " and calls the createNewFile() method of that instance.");
+
+ hints.add("Below are some helpful links..." +
+ "
Here is a page with an example of a simple .jsp file using a Scriptlet:" +
+ "
" +
+ "http://www.jsptut.com/Scriptlets.jsp" +
+ "
Here is an page with an example of using createNewFile():" +
+ "
" +
+ "http://www.roseindia.net/java/example/java/io/CreateFile.shtml" +
+ "
Here is the API specification for java.io.File:" +
+ "
" +
+ "http://java.sun.com/j2se/1.5.0/docs/api/java/io/File.html"
+ );
+
+ hints
+ .add("Here is an example .jsp file, modify it to use java.io.File and its createNewFile() method:"
+ + "
<HTML>"
+ + "
<%"
+ + "
java.lang.String hello = new java.lang.String(\"Hello World!\");"
+ + "
System.out.println(hello);"
+ + "
%>"
+ + "
</HTML>"
+ + "
NOTE: executing this file will print \"Hello World!\" to the Tomcat Console, not to your client browser"
+ );
+
+
+ hints
+ .add("SOLUTION:
Upload a file with a .jsp extension and this content:"
+ + "
<HTML>"
+ + "
<%"
+ + "
java.io.File file = new java.io.File(\""
+ + target_filename.replaceAll("\\\\", "\\\\\\\\") // if we are on windows, we need to
+ // make sure path separators are doubled / escaped
+ + "\");"
+ + "
file.createNewFile();"
+ + "
%>"
+ + "
</HTML>"
+ + "
After you have uploaded your jsp file, you can get the system to execute it by opening it in your browser at the URL below (or by just refreshing this page):"
+ + "
http://webgoat_ip:port/WebGoat/" + UPLOADS_RELATIVE_PATH + "/yourfilename.jsp"
+ );
+
+ return hints;
+ }
+
+ // this is a custom method for this lesson to restart. It is called in WebSession.restartLesson
+ // in a currently somewhat "hacked up" manner that is specific to this lesson. There probably
+ // should be an abstract type for lessons that need custom "restarting" code.
+ public void restartLesson(WebSession s)
+ {
+
+ if(uploads_and_target_parent_directory == null) {
+ fill_uploads_and_target_parent_directory(s);
+ }
+
+ System.out.println("Restarting Malicious File Execution lesson for user " + s.getUserName());
+
+ // delete the user's target file
+ File userfile = new File(uploads_and_target_parent_directory
+ + TARGET_RELATIVE_PATH
+ + java.io.File.separator
+ + s.getUserName() + ".txt");
+
+ userfile.delete();
+
+ // remove the row from the mfe table
+ // add url to database table
+
+ try {
+ Connection connection = DatabaseUtilities.getConnection(s);
+
+ Statement statement = connection.createStatement();
+
+ String deleteuserrow = "DELETE from mfe_images WHERE user_name = '"
+ + s.getUserName() + "';";
+
+ statement.executeUpdate(deleteuserrow);
+
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+
+ // cleanup code has been disabled for now. I'm not sure where it can be called cleanly
+ // where it will know what directory to use since that is pulled from the session object
+
+ // this method will delete files in the target directory and the uploads directory
+ // it should be called when WebGoat starts
+// public static void cleanDirectories() {
+// // delete files in TARGET_DIRECTORY
+// File target_dir = new File(TARGET_RELATIVE_PATH);
+// deleteFilesInDir(target_dir);
+//
+// // delete files in uploads directory
+// File uploads_dir = new File(uploads_and_target_parent_directory + UPLOADS_RELATIVE_PATH);
+// deleteFilesInDir(uploads_dir);
+//
+// }
+
+// private static void deleteFilesInDir(File dir) {
+// File[] dir_files = dir.listFiles();
+// for(int i = 0; i < dir_files.length; i++) {
+// // we won't recurse and we don't want to delete every file just in
+// // case TARGET_DIRECTORY or uploads directory is pointed
+// // somewhere stupid, like c:\ or /
+// if(dir_files[i].isFile()) {
+// String lower_file_name = dir_files[i].getName().toLowerCase();
+//
+// if(lower_file_name.endsWith(".jpg") ||
+// lower_file_name.endsWith(".gif") ||
+// lower_file_name.endsWith(".png") ||
+// lower_file_name.endsWith(".jsp") ||
+// lower_file_name.endsWith(".txt") ||
+// lower_file_name.endsWith(".asp") || // in case they think this is a IIS server :-)
+// lower_file_name.endsWith(".aspx")) {
+// dir_files[i].delete();
+// }
+// }
+// }
+// }
+
+
+ /**
+ * Gets the instructions attribute of the object
+ *
+ * @return The instructions value
+ */
+ public String getInstructions(WebSession s)
+ {
+ if(uploads_and_target_parent_directory == null) {
+ fill_uploads_and_target_parent_directory(s);
+ }
+
+ String instructions = "The form below allows you to upload an image which will be displayed on this page. "
+ + "Features like this are often found on web based discussion boards and social networking sites. "
+ + "This feature is vulnerable to Malicious File Execution."
+ + "
In order to pass this lession, upload and run a malicious file. In order to prove that your file can execute,"
+ + " it should create another file named:
"
+ + uploads_and_target_parent_directory
+ + TARGET_RELATIVE_PATH
+ + java.io.File.separator
+ + s.getUserName() + ".txt"
+ + "
Once you have created this file, you will pass the lesson.";
+
+ return (instructions);
+ }
+
+ private final static Integer DEFAULT_RANKING = new Integer(75);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ /**
+ * Gets the title attribute of the DatabaseFieldScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ("Malicious File Execution");
+ }
+
+ /**
+ * Constructor for the DatabaseFieldScreen object
+ *
+ * @param s
+ * Description of the Parameter
+ */
+ public void handleRequest(WebSession s)
+ {
+
+ if(uploads_and_target_parent_directory == null) {
+ fill_uploads_and_target_parent_directory(s);
+ }
+
+
+
+ try
+ {
+ if(ServletFileUpload.isMultipartContent(s.getRequest())) {
+ // multipart request - we have the file upload
+
+// Create a factory for disk-based file items
+ DiskFileItemFactory factory = new DiskFileItemFactory();
+ factory.setSizeThreshold(500000); // files over 500k will be written to disk temporarily.
+ // files under that size will be stored in memory until written to disk by the request handler code below
+
+// Create a new file upload handler
+ ServletFileUpload upload = new ServletFileUpload(factory);
+
+// Parse the request
+ List /* FileItem */ items = upload.parseRequest(s.getRequest());
+
+// Process the uploaded items
+ java.util.Iterator iter = items.iterator();
+ while (iter.hasNext()) {
+ FileItem item = (FileItem) iter.next();
+
+ if (item.isFormField()) {
+
+ // ignore regular form fields
+
+ } else {
+
+ // not a form field, must be a file upload
+ if(item.getName().contains("/") || item.getName().contains("\\")) {
+ System.out.println("Uploaded file contains a / or \\ (i.e. attempted directory traversal). Not storing file.");
+ // TODO - is there a way to show an error to the user here?
+
+ s.setMessage("Directory traversal not allowed. Nice try though.");
+
+ } else {
+
+ // write file to disk with original name in uploads directory
+ String uploaded_file_path = uploads_and_target_parent_directory
+ + UPLOADS_RELATIVE_PATH
+ + java.io.File.separator
+ + item.getName();
+ File uploadedFile = new File(uploaded_file_path);
+ item.write(uploadedFile);
+ System.out.println("Stored file:\n" + uploaded_file_path );
+
+ // add url to database table
+ Connection connection = DatabaseUtilities.getConnection(s);
+
+ Statement statement = connection.createStatement();
+
+ // attempt an update
+ String updateData1 = "UPDATE mfe_images SET image_relative_url='" + UPLOADS_RELATIVE_PATH + "/"
+ + item.getName() + "' WHERE user_name = '"
+ + s.getUserName() + "';";
+
+ System.out.println("Updating row:\n" + updateData1 );
+ if(statement.executeUpdate(updateData1) == 0) {
+
+ // update failed, we need to add a row
+ String insertData1 = "INSERT INTO mfe_images VALUES ('" +
+ s.getUserName() + "','" + UPLOADS_RELATIVE_PATH + "/" +
+ item.getName() + "')";
+
+ System.out.println("Inserting row:\n" + insertData1 );
+ statement.executeUpdate(insertData1);
+
+ }
+ }
+
+ }
+ }
+
+ }
+ // now handle normally (if it was a multipart request or now)
+
+ //super.handleRequest(s);
+
+ // needed to cut and paste and edit rather than calling super
+ // here so that we could set the encoding type to multipart form data
+ // call createContent first so messages will go somewhere
+
+ Form form = new Form(getFormAction(), Form.POST).setName("form")
+ .setEncType("multipart/form-data");
+
+ form.addElement(createContent(s));
+
+ setContent(form);
+ }
+ catch (Exception e)
+ {
+ System.out.println("Exception caught: " + e);
+ e.printStackTrace(System.out);
+ }
+ }
+}
diff --git a/main/project/JavaSource/org/owasp/webgoat/session/CreateDB.java b/main/project/JavaSource/org/owasp/webgoat/session/CreateDB.java
index 349829970..cef4f69ae 100644
--- a/main/project/JavaSource/org/owasp/webgoat/session/CreateDB.java
+++ b/main/project/JavaSource/org/owasp/webgoat/session/CreateDB.java
@@ -76,6 +76,45 @@ public class CreateDB
}
}
+ /**
+ * Description of the Method
+ *
+ * @param connection Description of the Parameter
+ *
+ * @exception SQLException Description of the Exception
+ */
+ private void createMFEImagesTable(Connection connection) throws SQLException
+ {
+ Statement statement = connection.createStatement();
+
+ // Drop mfe_images table
+ try
+ {
+ String dropTable = "DROP TABLE mfe_images";
+ statement.executeUpdate(dropTable);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error dropping mfe_images table from database");
+ }
+
+ // Create the new mfe_images table
+ try
+ {
+ String createTableStatement = "CREATE TABLE mfe_images ("
+ + "user_name varchar(50) not null, "
+ + "image_relative_url varchar(50) not null"
+ + ")";
+ statement.executeUpdate(createTableStatement);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error creating mfe_images table in database");
+ e.printStackTrace();
+ }
+
+ }
+
/**
* Description of the Method
*
@@ -267,6 +306,53 @@ public class CreateDB
}
+ // creates the table pins which is used in the blind sql injection lesson
+ private void createBlindSQLLessonTable(Connection connection) throws SQLException
+ {
+ Statement statement = connection.createStatement();
+
+ // Delete table if there is one
+ try
+ {
+ String dropTable = "DROP TABLE pins";
+ statement.executeUpdate(dropTable);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error dropping pins table");
+ }
+
+ // Create the new table
+ try
+ {
+ String createTableStatement = "CREATE TABLE pins ("
+ + "cc_number varchar(30),"
+ + "pin int,"
+ + "name varchar(20)"
+ + ")";
+ statement.executeUpdate(createTableStatement);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error creating pins table");
+ e.printStackTrace();
+ }
+
+ // Populate it
+ String insertData1 = "INSERT INTO pins VALUES ('987654321098765', 1234, 'Joe')";
+ String insertData2 = "INSERT INTO pins VALUES ('1234567890123456', 4567, 'Jack')";
+ String insertData3 = "INSERT INTO pins VALUES ('4321432143214321', 4321, 'Jill')";
+ String insertData4 = "INSERT INTO pins VALUES ('1111111111111111', 7777, 'Jim')";
+ String insertData5 = "INSERT INTO pins VALUES ('1111222233334444', 2364, 'John')";
+
+ statement.executeUpdate(insertData1);
+ statement.executeUpdate(insertData2);
+ statement.executeUpdate(insertData3);
+ statement.executeUpdate(insertData4);
+ statement.executeUpdate(insertData5);
+
+ }
+
/**
* Description of the Method
*
@@ -897,6 +983,7 @@ public class CreateDB
System.out.println("Successful connection to database");
createUserDataTable(connection);
createLoginTable(connection);
+ createBlindSQLLessonTable(connection);
createUserAdminTable(connection);
createProductTable(connection);
createMessageTable(connection);
@@ -908,6 +995,7 @@ public class CreateDB
createTransactionTable(connection);
createTanUserDataTable(connection);
createTanTable(connection);
+ createMFEImagesTable(connection);
System.out.println("Success: creating tables.");
}
}
diff --git a/main/project/JavaSource/org/owasp/webgoat/session/WebSession.java b/main/project/JavaSource/org/owasp/webgoat/session/WebSession.java
index 6aa22647f..ca479eaa6 100644
--- a/main/project/JavaSource/org/owasp/webgoat/session/WebSession.java
+++ b/main/project/JavaSource/org/owasp/webgoat/session/WebSession.java
@@ -991,7 +991,10 @@ public class WebSession
{
RandomLessonAdapter rla = (RandomLessonAdapter) al;
rla.setStage(this, rla.getStages()[0]);
- }
+ }
+ else if(al instanceof org.owasp.webgoat.lessons.MaliciousFileExecution) {
+ ((org.owasp.webgoat.lessons.MaliciousFileExecution) al).restartLesson(this);
+ }
}
/**
diff --git a/main/project/WebContent/WEB-INF/lib/commons-fileupload-1.2.1.jar b/main/project/WebContent/WEB-INF/lib/commons-fileupload-1.2.1.jar
new file mode 100644
index 000000000..aa209b388
Binary files /dev/null and b/main/project/WebContent/WEB-INF/lib/commons-fileupload-1.2.1.jar differ
diff --git a/main/project/WebContent/WEB-INF/lib/commons-io-1.4.jar b/main/project/WebContent/WEB-INF/lib/commons-io-1.4.jar
new file mode 100644
index 000000000..133dc6cb3
Binary files /dev/null and b/main/project/WebContent/WEB-INF/lib/commons-io-1.4.jar differ
diff --git a/main/project/WebContent/images/logos/mandiant.png b/main/project/WebContent/images/logos/mandiant.png
new file mode 100644
index 000000000..7ae27d43d
Binary files /dev/null and b/main/project/WebContent/images/logos/mandiant.png differ