From 129e9deba9eb739368de54009cae9f9d32ec0c63 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Sun, 21 May 2017 16:40:52 +0200 Subject: [PATCH] Added testcase for SQL injection lesson --- .../webgoat/assignments/AttackResult.java | 8 +- .../org/owasp/webgoat/plugins/LessonTest.java | 7 +- .../webgoat/plugin/SqlInjectionLesson5a.java | 230 ++++++------------ .../webgoat/plugin/SqlInjectionLesson5b.java | 205 +++------------- .../webgoat/plugin/SqlInjectionLesson6a.java | 202 +++------------ .../src/main/resources/html/SqlInjection.html | 93 ++----- .../resources/i18n/WebGoatLabels.properties | 5 +- .../plugin/SqlInjectionLesson5aTest.java | 81 ++++++ .../plugin/BlindSendFileAssignment.java | 3 +- 9 files changed, 257 insertions(+), 577 deletions(-) create mode 100644 webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/SqlInjectionLesson5aTest.java diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AttackResult.java b/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AttackResult.java index b10917d49..e78d46338 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AttackResult.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AttackResult.java @@ -25,11 +25,10 @@ package org.owasp.webgoat.assignments; -import lombok.AllArgsConstructor; import lombok.Getter; +import org.apache.commons.lang3.StringEscapeUtils; import org.owasp.webgoat.i18n.PluginMessages; -@AllArgsConstructor public class AttackResult { public static class AttackResultBuilder { @@ -89,6 +88,11 @@ public class AttackResult { @Getter private String output; + public AttackResult(boolean lessonCompleted, String feedback, String output) { + this.lessonCompleted = lessonCompleted; + this.feedback = StringEscapeUtils.escapeJson(feedback); + this.output = StringEscapeUtils.escapeJson(output); + } public static AttackResultBuilder builder(PluginMessages messages) { return new AttackResultBuilder(messages); diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java index 07a0d272d..4677b499c 100644 --- a/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java +++ b/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java @@ -2,7 +2,7 @@ package org.owasp.webgoat.plugins; import org.junit.Before; import org.owasp.webgoat.i18n.Language; -import org.owasp.webgoat.i18n.Messages; +import org.owasp.webgoat.i18n.PluginMessages; import org.owasp.webgoat.session.WebSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.embedded.LocalServerPort; @@ -30,7 +30,7 @@ public abstract class LessonTest { @Autowired protected WebApplicationContext wac; @Autowired - protected Messages messages; + protected PluginMessages messages; @MockBean protected WebSession webSession; @MockBean @@ -38,7 +38,8 @@ public abstract class LessonTest { @Before public void init() { - when(language.getLocale()).thenReturn(Locale.US); + when(webSession.getUserName()).thenReturn("unit-test"); + when(language.getLocale()).thenReturn(Locale.getDefault()); } } diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5a.java index c7dbb59b8..9eea9b173 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5a.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5a.java @@ -2,6 +2,7 @@ package org.owasp.webgoat.plugin; 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; @@ -10,211 +11,118 @@ 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/attack5a") +@AssignmentHints(value = {"SqlStringInjectionHint1", "SqlStringInjectionHint2", "SqlStringInjectionHint3", "SqlStringInjectionHint4"}) public class SqlInjectionLesson5a extends AssignmentEndpoint { - @RequestMapping(method = RequestMethod.POST) - public @ResponseBody AttackResult completed(@RequestParam String account, HttpServletRequest request) throws IOException { - return injectableQuery(account); - } + @RequestMapping(method = RequestMethod.POST) + public + @ResponseBody + AttackResult completed(@RequestParam String account) { + return injectableQuery(account); + } - protected AttackResult injectableQuery(String accountName) - { - try - { + protected AttackResult injectableQuery(String accountName) { + try { Connection connection = DatabaseUtilities.getConnection(getWebSession()); String query = "SELECT * FROM user_data WHERE last_name = '" + accountName + "'"; - try - { + try { Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_READ_ONLY); + ResultSet.CONCUR_READ_ONLY); ResultSet results = statement.executeQuery(query); - if ((results != null) && (results.first() == true)) - { + if ((results != null) && (results.first())) { ResultSetMetaData resultsMetaData = results.getMetaData(); - StringBuffer output = new StringBuffer(); + 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()); + 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 (SQLException sqle) { + + return trackProgress(failed().output(sqle.getMessage()).build()); } - } catch (Exception e) - { - e.printStackTrace(); - return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build()); + } catch (Exception e) { + return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build()); } } - - public 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()); + + 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()); } -// -// protected Element parameterizedQuery(WebSession s) -// { -// ElementContainer ec = new ElementContainer(); -// -// ec.addElement(getLabelManager().get("StringSqlInjectionSecondStage")); -// if (s.getParser().getRawParameter(ACCT_NAME, "YOUR_NAME").equals("restart")) -// { -// getLessonTracker(s).getLessonProperties().setProperty(STAGE, "1"); -// return (injectableQuery(s)); -// } -// -// ec.addElement(new BR()); -// -// try -// { -// Connection connection = DatabaseUtilities.getConnection(s); -// -// ec.addElement(makeAccountLine(s)); -// -// String query = "SELECT * FROM user_data WHERE last_name = ?"; -// ec.addElement(new PRE(query)); -// -// try -// { -// PreparedStatement statement = connection.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, -// ResultSet.CONCUR_READ_ONLY); -// statement.setString(1, accountName); -// ResultSet results = statement.executeQuery(); -// -// if ((results != null) && (results.first() == true)) -// { -// ResultSetMetaData resultsMetaData = results.getMetaData(); -// ec.addElement(DatabaseUtilities.writeTable(results, resultsMetaData)); -// results.last(); -// -// // If they get back more than one user they succeeded -// if (results.getRow() >= 6) -// { -// makeSuccess(s); -// } -// } -// else -// { -// ec.addElement(getLabelManager().get("NoResultsMatched")); -// } -// } catch (SQLException sqle) -// { -// ec.addElement(new P().addElement(sqle.getMessage())); -// } -// } catch (Exception e) -// { -// s.setMessage(getLabelManager().get("ErrorGenerating") + this.getClass().getName()); -// e.printStackTrace(); -// } -// -// return (ec); -// } -// -// protected Element makeAccountLine(WebSession s) -// { -// ElementContainer ec = new ElementContainer(); -// ec.addElement(new P().addElement(getLabelManager().get("EnterLastName"))); -// -// accountName = s.getParser().getRawParameter(ACCT_NAME, "Your Name"); -// Input input = new Input(Input.TEXT, ACCT_NAME, accountName.toString()); -// ec.addElement(input); -// -// Element b = ECSFactory.makeButton(getLabelManager().get("Go!")); -// ec.addElement(b); -// -// return ec; -// -// } - - - } diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5b.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5b.java index c21a9e3e6..595bb490d 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5b.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5b.java @@ -1,8 +1,8 @@ package org.owasp.webgoat.plugin; - 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; @@ -16,209 +16,84 @@ 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 = {"SqlStringInjectionHint1", "SqlStringInjectionHint2", "SqlStringInjectionHint3", "SqlStringInjectionHint4"}) public class SqlInjectionLesson5b extends AssignmentEndpoint { - @RequestMapping(method = RequestMethod.POST) - public @ResponseBody AttackResult completed(@RequestParam String userid, HttpServletRequest request) throws IOException { - return injectableQuery(userid); - - } + @RequestMapping(method = RequestMethod.POST) + public + @ResponseBody + AttackResult completed(@RequestParam String userid, HttpServletRequest request) throws IOException { + return injectableQuery(userid); - protected AttackResult injectableQuery(String accountName) - { - try - { + } + + protected AttackResult injectableQuery(String accountName) { + try { Connection connection = DatabaseUtilities.getConnection(getWebSession()); String query = "SELECT * FROM user_data WHERE userid = " + accountName; - try - { + try { Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_READ_ONLY); + ResultSet.CONCUR_READ_ONLY); ResultSet results = statement.executeQuery(query); - if ((results != null) && (results.first() == true)) - { + if ((results != null) && (results.first() == true)) { ResultSetMetaData resultsMetaData = results.getMetaData(); - StringBuffer output = new StringBuffer(); + StringBuffer output = new StringBuffer(); - output.append(writeTable(results, resultsMetaData)); + 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()); + 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 (SQLException sqle) { + + return trackProgress(failed().output(sqle.getMessage()).build()); } - } catch (Exception e) - { - e.printStackTrace(); - return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build()); + } catch (Exception e) { + e.printStackTrace(); + return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build()); } } - - public 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()); - } -// -// protected Element parameterizedQuery(WebSession s) -// { -// ElementContainer ec = new ElementContainer(); -// -// ec.addElement(getLabelManager().get("StringSqlInjectionSecondStage")); -// if (s.getParser().getRawParameter(ACCT_NAME, "YOUR_NAME").equals("restart")) -// { -// getLessonTracker(s).getLessonProperties().setProperty(STAGE, "1"); -// return (injectableQuery(s)); -// } -// -// ec.addElement(new BR()); -// -// try -// { -// Connection connection = DatabaseUtilities.getConnection(s); -// -// ec.addElement(makeAccountLine(s)); -// -// String query = "SELECT * FROM user_data WHERE last_name = ?"; -// ec.addElement(new PRE(query)); -// -// try -// { -// PreparedStatement statement = connection.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, -// ResultSet.CONCUR_READ_ONLY); -// statement.setString(1, accountName); -// ResultSet results = statement.executeQuery(); -// -// if ((results != null) && (results.first() == true)) -// { -// ResultSetMetaData resultsMetaData = results.getMetaData(); -// ec.addElement(DatabaseUtilities.writeTable(results, resultsMetaData)); -// results.last(); -// -// // If they get back more than one user they succeeded -// if (results.getRow() >= 6) -// { -// makeSuccess(s); -// } -// } -// else -// { -// ec.addElement(getLabelManager().get("NoResultsMatched")); -// } -// } catch (SQLException sqle) -// { -// ec.addElement(new P().addElement(sqle.getMessage())); -// } -// } catch (Exception e) -// { -// s.setMessage(getLabelManager().get("ErrorGenerating") + this.getClass().getName()); -// e.printStackTrace(); -// } -// -// return (ec); -// } -// -// protected Element makeAccountLine(WebSession s) -// { -// ElementContainer ec = new ElementContainer(); -// ec.addElement(new P().addElement(getLabelManager().get("EnterLastName"))); -// -// accountName = s.getParser().getRawParameter(ACCT_NAME, "Your Name"); -// Input input = new Input(Input.TEXT, ACCT_NAME, accountName.toString()); -// ec.addElement(input); -// -// Element b = ECSFactory.makeButton(getLabelManager().get("Go!")); -// ec.addElement(b); -// -// return ec; -// -// } - - - } diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6a.java index 9e0950c12..90774c0e3 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6a.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6a.java @@ -2,6 +2,7 @@ package org.owasp.webgoat.plugin; 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; @@ -10,214 +11,89 @@ 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.*; +import static org.owasp.webgoat.plugin.SqlInjectionLesson5a.writeTable; /*************************************************************************************************** - * - * + * + * * 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/attack6a") +@AssignmentHints(value = {"SqlStringInjectionHint5", "SqlStringInjectionHint6"}) public class SqlInjectionLesson6a extends AssignmentEndpoint { - @RequestMapping(method = RequestMethod.POST) - public @ResponseBody AttackResult completed(@RequestParam String userid_6a, HttpServletRequest request) throws IOException { - return injectableQuery(userid_6a); - // The answer: Smith' union select userid,user_name, password,cookie,cookie, cookie,userid from user_system_data -- + @RequestMapping(method = RequestMethod.POST) + public + @ResponseBody + AttackResult completed(@RequestParam String userid_6a) throws IOException { + return injectableQuery(userid_6a); + // The answer: Smith' union select userid,user_name, password,cookie,cookie, cookie,userid from user_system_data -- - } + } - protected AttackResult injectableQuery(String accountName) - { - try - { + protected AttackResult injectableQuery(String accountName) { + try { Connection connection = DatabaseUtilities.getConnection(getWebSession()); String query = "SELECT * FROM user_data WHERE last_name = '" + accountName + "'"; - try - { + try { Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_READ_ONLY); + ResultSet.CONCUR_READ_ONLY); ResultSet results = statement.executeQuery(query); - if ((results != null) && (results.first() == true)) - { + if ((results != null) && (results.first())) { ResultSetMetaData resultsMetaData = results.getMetaData(); - StringBuffer output = new StringBuffer(); + StringBuffer output = new StringBuffer(); output.append(writeTable(results, resultsMetaData)); results.last(); // If they get back more than one user they succeeded - if (results.getRow() >= 5) - { - return trackProgress(success().feedback("sql-injection.6a.success").feedbackArgs(output.toString()).build()); - } else { - return trackProgress(failed().output(output.toString()).build()); - } - - } - else - { - return trackProgress(failed().feedback("sql-injection.6a.no.results").build()); + if (results.getRow() >= 5) { + return trackProgress(success().feedback("sql-injection.6a.success").feedbackArgs(output.toString()).build()); + } else { + return trackProgress(failed().output(output.toString()).build()); + } + + } else { + return trackProgress(failed().feedback("sql-injection.6a.no.results").build()); } - } catch (SQLException sqle) - { - - return trackProgress(failed().output(sqle.getMessage()).build()); + } 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()); + } catch (Exception e) { + e.printStackTrace(); + return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build()); } } - - public 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()); - } -// -// protected Element parameterizedQuery(WebSession s) -// { -// ElementContainer ec = new ElementContainer(); -// -// ec.addElement(getLabelManager().get("StringSqlInjectionSecondStage")); -// if (s.getParser().getRawParameter(ACCT_NAME, "YOUR_NAME").equals("restart")) -// { -// getLessonTracker(s).getLessonProperties().setProperty(STAGE, "1"); -// return (injectableQuery(s)); -// } -// -// ec.addElement(new BR()); -// -// try -// { -// Connection connection = DatabaseUtilities.getConnection(s); -// -// ec.addElement(makeAccountLine(s)); -// -// String query = "SELECT * FROM user_data WHERE last_name = ?"; -// ec.addElement(new PRE(query)); -// -// try -// { -// PreparedStatement statement = connection.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, -// ResultSet.CONCUR_READ_ONLY); -// statement.setString(1, accountName); -// ResultSet results = statement.executeQuery(); -// -// if ((results != null) && (results.first() == true)) -// { -// ResultSetMetaData resultsMetaData = results.getMetaData(); -// ec.addElement(DatabaseUtilities.writeTable(results, resultsMetaData)); -// results.last(); -// -// // If they get back more than one user they succeeded -// if (results.getRow() >= 6) -// { -// makeSuccess(s); -// } -// } -// else -// { -// ec.addElement(getLabelManager().get("NoResultsMatched")); -// } -// } catch (SQLException sqle) -// { -// ec.addElement(new P().addElement(sqle.getMessage())); -// } -// } catch (Exception e) -// { -// s.setMessage(getLabelManager().get("ErrorGenerating") + this.getClass().getName()); -// e.printStackTrace(); -// } -// -// return (ec); -// } -// -// protected Element makeAccountLine(WebSession s) -// { -// ElementContainer ec = new ElementContainer(); -// ec.addElement(new P().addElement(getLabelManager().get("EnterLastName"))); -// -// accountName = s.getParser().getRawParameter(ACCT_NAME, "Your Name"); -// Input input = new Input(Input.TEXT, ACCT_NAME, accountName.toString()); -// ec.addElement(input); -// -// Element b = ECSFactory.makeButton(getLabelManager().get("Go!")); -// ec.addElement(b); -// -// return ec; -// -// } - - - } 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 85d55aadb..0cdcc1d49 100644 --- a/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjection.html +++ b/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjection.html @@ -3,54 +3,33 @@
- -
- -
+
- -
+
- -
+
- -
+
- -
+
- -
- - - - -
-
-
+
- -
- - - -
- -
-
+
- -
+
- -
- - - -
- -
-
- - - -
- -
-
- -
+
- -
+
- -
+
- -
+
- -
+
- -
+
- -
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 407f5367a..e63a9fb5c 100644 --- a/webgoat-lessons/sql-injection/src/main/resources/i18n/WebGoatLabels.properties +++ b/webgoat-lessons/sql-injection/src/main/resources/i18n/WebGoatLabels.properties @@ -1,12 +1,13 @@ #StringSqlInjection.java StringSqlInjectionSecondStage=Now that you have successfully performed an SQL injection, try the same type of attack on a parameterized query. Restart the lesson if you wish to return to the injectable query. EnterLastName=Enter your last name: -NoResultsMatched=No results matched. Try Again. +NoResultsMatched=No results matched. Try Again. SqlStringInjectionHint1=The application is taking your input and inserting it at the end of a pre-formed SQL command. SqlStringInjectionHint2=This is the code for the query being built and issued by WebGoat:

"SELECT * FROM user_data WHERE last_name = "accountName" SqlStringInjectionHint3=Compound SQL statements can be made by joining multiple tests with keywords like AND and OR. Try appending a SQL statement that always resolves to true SqlStringInjectionHint4=Try entering [ smith' OR '1' = '1 ]. - +SqlStringInjectionHint5=Try adding a union to the query, the number of columns should match. +SqlStringInjectionHint6=Try entering [ Smith' union select userid,user_name, password,cookie,cookie, cookie,userid from user_system_data -- ]. sql-injection.5a.success=You have succeed: {0} sql-injection.5a.no.results=No results matched. Try Again. diff --git a/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/SqlInjectionLesson5aTest.java b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/SqlInjectionLesson5aTest.java new file mode 100644 index 000000000..54c99b481 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/SqlInjectionLesson5aTest.java @@ -0,0 +1,81 @@ +package org.owasp.webgoat.plugin; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.owasp.webgoat.plugins.LessonTest; +import org.owasp.webgoat.session.WebgoatContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author nbaars + * @since 5/21/17. + */ +@RunWith(SpringJUnit4ClassRunner.class) +public class SqlInjectionLesson5aTest extends LessonTest { + + @Autowired + private WebgoatContext context; + + @Before + public void setup() throws Exception { + SqlInjection sql = new SqlInjection(); + when(webSession.getCurrentLesson()).thenReturn(sql); + when(webSession.getWebgoatContext()).thenReturn(context); + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void knownAccountShouldDisplayData() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a") + .param("account", "Smith")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("lessonCompleted", is(false))) + .andExpect(jsonPath("$.feedback", is(messages.getMessage("assignment.not.solved")))) + .andExpect(jsonPath("$.output", containsString("

USERID, FIRST_NAME"))); + } + + @Test + public void unknownAccount() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a") + .param("account", "Smithh")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("lessonCompleted", is(false))) + .andExpect(jsonPath("$.feedback", is(messages.getMessage("NoResultsMatched")))) + .andExpect(jsonPath("$.output").doesNotExist()); + } + + @Test + public void sqlInjection() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a") + .param("account", "smith' OR '1' = '1")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("lessonCompleted", is(true))) + .andExpect(jsonPath("$.feedback", containsString("You have succeed"))) + .andExpect(jsonPath("$.output").doesNotExist()); + } + + @Test + public void sqlInjectionWrongShouldDisplayError() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a") + .param("account", "smith' OR '1' = '1'")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("lessonCompleted", is(false))) + .andExpect(jsonPath("$.feedback", containsString(messages.getMessage("assignment.not.solved")))) + .andExpect(jsonPath("$.output", is("malformed string: '1''"))); + } +} \ No newline at end of file diff --git a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java index 3a3ddb74f..f8792b06c 100644 --- a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java +++ b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java @@ -3,7 +3,6 @@ package org.owasp.webgoat.plugin; import com.beust.jcommander.internal.Lists; import com.google.common.base.Joiner; import lombok.SneakyThrows; -import org.apache.commons.lang3.StringEscapeUtils; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AttackResult; @@ -83,7 +82,7 @@ public class BlindSendFileAssignment extends AssignmentEndpoint { Comment comment = comments.parseXml(commentStr); comments.addComment(comment, false); } catch (Exception e) { - error = StringEscapeUtils.escapeJson(e.toString()); + error = e.toString(); } File logFile = new File(webGoatHomeDirectory, "/XXE/log" + webSession.getUserName() + ".txt");