From 7f532f0ffc2c2a3631a7ca964380d2779ccd46ee Mon Sep 17 00:00:00 2001 From: Jason White Date: Fri, 17 Feb 2017 13:05:54 -0500 Subject: [PATCH] XSS lesson updates --- .../webgoat/session/UserSessionData.java | 4 + .../static/js/goatApp/view/GoatRouter.js | 7 +- .../js/goatApp/view/LessonContentView.js | 4 +- webgoat-lessons/command-injection/pom.xml | 34 ++++ .../webgoat/plugin/CommandInjection.java | 63 ++++++ .../plugin/CommandInjectionExecute.java | 58 ++++++ .../html/CommandInjection.html | 51 +++++ .../lessonPlans/en/CommandInjection1.adoc | 20 ++ .../plugin/i18n/WebGoatLabels.properties | 4 + .../plugin/CrossSiteScriptingLesson5a.java | 33 ++- .../plugin/CrossSiteScriptingLesson5b.java | 192 +++--------------- .../plugin/CrossSiteScriptingLesson6a.java | 185 ++--------------- .../plugin/CrossSiteScriptingLesson6b.java | 95 --------- .../webgoat/plugin/DOMCrossSiteScripting.java | 8 +- .../html/CrossSiteScripting.html | 37 ++-- .../en/CrossSiteScripting_content1.adoc | 20 +- .../en/CrossSiteScripting_content3.adoc | 2 +- .../en/CrossSiteScripting_content4.adoc | 7 +- .../en/CrossSiteScripting_content5a.adoc | 4 +- .../en/CrossSiteScripting_content5b.adoc | 3 +- .../en/CrossSiteScripting_content5c.adoc | 9 + .../en/CrossSiteScripting_content6.adoc | 12 +- .../en/CrossSiteScripting_content6a.adoc | 11 +- .../plugin/i18n/WebGoatLabels.properties | 18 +- 24 files changed, 402 insertions(+), 479 deletions(-) create mode 100644 webgoat-lessons/command-injection/pom.xml create mode 100644 webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjection.java create mode 100644 webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjectionExecute.java create mode 100644 webgoat-lessons/command-injection/src/main/resources/plugin/CommandInjection/html/CommandInjection.html create mode 100644 webgoat-lessons/command-injection/src/main/resources/plugin/CommandInjection/lessonPlans/en/CommandInjection1.adoc create mode 100644 webgoat-lessons/command-injection/src/main/resources/plugin/i18n/WebGoatLabels.properties delete mode 100644 webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6b.java create mode 100644 webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content5c.adoc diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/UserSessionData.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/UserSessionData.java index e5546c2ba..1e1229e40 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/session/UserSessionData.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/UserSessionData.java @@ -18,6 +18,10 @@ public class UserSessionData { //GETTERS & SETTERS public Object getValue(String key) { + if (!userSessionData.containsKey(key)) { + return null; + } + // else return userSessionData.get(key); } diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/GoatRouter.js b/webgoat-container/src/main/resources/static/js/goatApp/view/GoatRouter.js index dd278c7cc..ec1667826 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/view/GoatRouter.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/view/GoatRouter.js @@ -54,7 +54,7 @@ define(['jquery', webgoat.customjs.jquery = $; //passing jquery into custom js scope ... still klunky, but works for now webgoat.customjs.jqueryVuln = $vuln; - // temporary shim to support dom-xss lesson + // temporary shim to support dom-xss assignment webgoat.customjs.phoneHome = function (e) { console.log('phoneHome invoked'); console.log(arguments.callee); @@ -97,6 +97,11 @@ define(['jquery', this.menuController.updateMenu(name); }, + testRoute: function (param) { + this.lessonController.testHandler(param); + //this.menuController.updateMenu(name); + }, + welcomeRoute: function () { render(); this.lessonController.loadWelcome(); diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js index 07e9eb177..7f478dab2 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js @@ -114,7 +114,9 @@ define(['jquery', this.renderFeedback(data.feedback); this.renderOutput(data.output || ""); - if (data.assignmentCompleted) { + //TODO: refactor back assignmentCompleted in Java + if (data.lessonCompleted || data.assignmentCompleted) { + this.markAssignmentComplete(); this.trigger('assignment:complete'); } else { diff --git a/webgoat-lessons/command-injection/pom.xml b/webgoat-lessons/command-injection/pom.xml new file mode 100644 index 000000000..313061c5d --- /dev/null +++ b/webgoat-lessons/command-injection/pom.xml @@ -0,0 +1,34 @@ + + 4.0.0 + http-proxies + jar + + org.owasp.webgoat.lesson + webgoat-lessons-parent + 8.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + 4.1.3.RELEASE + test + + + junit + junit + ${junit.version} + jar + test + + + + + diff --git a/webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjection.java b/webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjection.java new file mode 100644 index 000000000..ad87c7c20 --- /dev/null +++ b/webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjection.java @@ -0,0 +1,63 @@ +package org.owasp.webgoat.plugin; + +import com.beust.jcommander.internal.Lists; +import org.owasp.webgoat.lessons.Category; +import org.owasp.webgoat.lessons.NewLesson; + +import java.util.List; + +/** + * ************************************************************************************************ + * 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. + *

+ * + * @author WebGoat + * @version $Id: $Id + * @since October 12, 2016 + */ +public class HttpProxies extends NewLesson { + @Override + public Category getDefaultCategory() { + return Category.GENERAL; + } + + @Override + public List getHints() { + return Lists.newArrayList(); + } + + @Override + public Integer getDefaultRanking() { + return 2; + } + + @Override + public String getTitle() { + return "http-proxies.title"; + } + + @Override + public String getId() { + return "HttpProxies"; + } +} diff --git a/webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjectionExecute.java b/webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjectionExecute.java new file mode 100644 index 000000000..ee8f9ef64 --- /dev/null +++ b/webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjectionExecute.java @@ -0,0 +1,58 @@ +package org.owasp.webgoat.plugin; + +import org.owasp.webgoat.assignments.AssignmentEndpoint; +import org.owasp.webgoat.assignments.AssignmentPath; +import org.owasp.webgoat.assignments.AttackResult; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * ************************************************************************************************* + * + * + * 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("/HttpProxies/intercept-request") +public class HttpBasicsInterceptRequest extends AssignmentEndpoint { + + @RequestMapping(method = RequestMethod.GET) + public @ResponseBody + AttackResult completed(HttpServletRequest request) throws IOException { + if (request.getHeader("x-request-intercepted").toLowerCase().equals("true") && request.getParameter("changeMe").equals("Requests are tampered easily")) { + return trackProgress(success().feedback("http-proxies.intercept.success").build()); + } else { + return trackProgress(failed().feedback("http-proxies.intercept.failure").build()); + } + } +} \ No newline at end of file diff --git a/webgoat-lessons/command-injection/src/main/resources/plugin/CommandInjection/html/CommandInjection.html b/webgoat-lessons/command-injection/src/main/resources/plugin/CommandInjection/html/CommandInjection.html new file mode 100644 index 000000000..59113e121 --- /dev/null +++ b/webgoat-lessons/command-injection/src/main/resources/plugin/CommandInjection/html/CommandInjection.html @@ -0,0 +1,51 @@ + + + + +

+ + +
+
+ +
+ + +
+
+ +
+ + +
+
+ +
+ + +
+
+ +
+ +
+
+
+
+ + + + +
+
+
+
+
+ \ No newline at end of file diff --git a/webgoat-lessons/command-injection/src/main/resources/plugin/CommandInjection/lessonPlans/en/CommandInjection1.adoc b/webgoat-lessons/command-injection/src/main/resources/plugin/CommandInjection/lessonPlans/en/CommandInjection1.adoc new file mode 100644 index 000000000..6344750d7 --- /dev/null +++ b/webgoat-lessons/command-injection/src/main/resources/plugin/CommandInjection/lessonPlans/en/CommandInjection1.adoc @@ -0,0 +1,20 @@ + +== HTTP Proxy Overview + +Many times proxies are used as a way of accessing otehrwise blocked content. A user might connect to server A, which relays content from server B + ... Because Server B is blocked wihtin the user's network. That's not the use case we will be dealing with here, but the concept is the same. +HTTP Proxies receive requesets from a client and relay them. They also typically record them. They act as a man-in-the-middle (keep that in mind if you decide to +use a proxy server to connect to some other system that is otherwise blocked). We won't get into HTTP vs HTTPS just yet, but that's an important topic in +relationship to proxies. + +=== Proxy Capabilities + +Proxies sit between your client and the server the client is talking to. You can record and analyze the requests & responses. You can also use the proxy to +modify (tamper) the requests and responses. Proxies also have automated or semi-automated functions that allow you to gain efficiency in testing and +analyzing the security of a website. + +=== Other Uses for Proxies + +ZAP specifically can also be used in the development process in a CI/CD, DevOps or otherwise automated build/test environment. This lesson does +not currently have any details on that, but it is worth mentioning. There are a number of examples on the internet of it being integrated into a +CI/CD with Jenkins, maven or other build processes. \ No newline at end of file diff --git a/webgoat-lessons/command-injection/src/main/resources/plugin/i18n/WebGoatLabels.properties b/webgoat-lessons/command-injection/src/main/resources/plugin/i18n/WebGoatLabels.properties new file mode 100644 index 000000000..2140e3ed4 --- /dev/null +++ b/webgoat-lessons/command-injection/src/main/resources/plugin/i18n/WebGoatLabels.properties @@ -0,0 +1,4 @@ +http-proxies.title=HTTP Proxies + +http-proxies.intercept.success=Well done, you tampered the request as expected +http-proxies.intercept.failure=Please try again. Make sure to make all the changes. And case sensitivity may matter ... or not, you never know! \ No newline at end of file diff --git a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5a.java b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5a.java index 857939090..6b87d7475 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5a.java +++ b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5a.java @@ -4,6 +4,8 @@ package org.owasp.webgoat.plugin; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AttackResult; +import org.owasp.webgoat.session.UserSessionData; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @@ -47,21 +49,44 @@ import java.io.IOException; @AssignmentPath("/CrossSiteScripting/attack5a") public class CrossSiteScriptingLesson5a extends AssignmentEndpoint { - @RequestMapping(method = RequestMethod.POST) + @Autowired + UserSessionData userSessionData; + + @RequestMapping(method = RequestMethod.GET) public @ResponseBody AttackResult completed(@RequestParam Integer QTY1, @RequestParam Integer QTY2, @RequestParam Integer QTY3, @RequestParam Integer QTY4, @RequestParam String field1, @RequestParam Integer field2, HttpServletRequest request) throws IOException { - System.out.println("foo"); + // System.out.println("foo"); // Should add some QTY validation here. Someone could have fun and enter a negative quantity and get merchanidise and a refund :) double totalSale = QTY1.intValue() * 69.99 + QTY2.intValue() * 27.99 + QTY3.intValue() * 1599.99 + QTY4.intValue() * 299.99; - + + userSessionData.setValue("xss-reflected1-complete",(Object)"false"); StringBuffer cart = new StringBuffer(); cart.append("Thank you for shopping at WebGoat.
You're support is appreciated
"); cart.append("

We have chaged credit card:" + field1 + "
"); cart.append( " -------------------
"); cart.append( " $" + totalSale); - return trackProgress(failed().output(cart.toString()).build()); + + //init state + if (userSessionData.getValue("xss-reflected1-complete") == null) { + userSessionData.setValue("xss-reflected1-complete",(Object)"false"); + } + + if (field1.toLowerCase().contains("")) { + //return trackProgress() + userSessionData.setValue("xss-reflected-5a-complete","true"); + return trackProgress(success() + .feedback("xss-reflected-5a-success") + .output(cart.toString()) + .build()); + } else { + userSessionData.setValue("xss-reflected1-complete","false"); + return trackProgress(success() + .feedback("xss-reflected-5a-failure") + .output(cart.toString()) + .build()); + } } } \ No newline at end of file diff --git a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5b.java b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5b.java index d09d0daf2..eb609039f 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5b.java +++ b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5b.java @@ -4,7 +4,16 @@ package org.owasp.webgoat.plugin; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentPath; +import org.owasp.webgoat.assignments.AttackResult; +import org.owasp.webgoat.session.UserSessionData; +import org.springframework.beans.factory.annotation.Autowired; +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; /*************************************************************************************************** @@ -39,176 +48,27 @@ import org.owasp.webgoat.assignments.AssignmentPath; */ @AssignmentPath("/CrossSiteScripting/attack5b") public class CrossSiteScriptingLesson5b extends AssignmentEndpoint { -/* - @RequestMapping(method = RequestMethod.POST) - public @ResponseBody AttackResult completed(@RequestParam String userid, HttpServletRequest request) throws IOException { - return injectableQuery(userid); - - } - protected AttackResult injectableQuery(String accountName) - { - try - { - Connection connection = DatabaseUtilities.getConnection(getWebSession()); - String query = "SELECT * FROM user_data WHERE userid = " + accountName; + @Autowired + UserSessionData userSessionData; - try - { - Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_READ_ONLY); - ResultSet results = statement.executeQuery(query); + @RequestMapping(method = RequestMethod.POST) + public @ResponseBody + AttackResult completed(@RequestParam String isReflectedXSS) throws IOException { + // init + System.out.println(userSessionData.getValue("xss-reflected5a-complete")); - if ((results != null) && (results.first() == true)) - { - ResultSetMetaData resultsMetaData = results.getMetaData(); - StringBuffer output = new StringBuffer(); + //TODO +// if (null == userSessionData.getValue("xss-reflected5a-complete") || userSessionData.getValue("xss-reflected-5a-complete").equals("false")) { +// //userSessionData.setValue("xss-reflected1-complete",(Object)"false"); +// return trackProgress(success().feedback("xss-reflected-5b-do5a-first").build()); +// } - output.append(writeTable(results, resultsMetaData)); - results.last(); - - // If they get back more than one user they succeeded - if (results.getRow() >= 6) - { - return trackProgress(AttackResult.success("You have succeed: " + output.toString())); - } else { - return trackProgress(AttackResult.failed("You are close, try again. " + output.toString())); - } - - } - else - { - return trackProgress(AttackResult.failed("No Results Matched. Try Again. ")); - -// output.append(getLabelManager().get("NoResultsMatched")); - } - } catch (SQLException sqle) - { - - return trackProgress(AttackResult.failed(sqle.getMessage())); - } - } catch (Exception e) - { - e.printStackTrace(); - return trackProgress(AttackResult.failed( "ErrorGenerating" + this.getClass().getName() + " : " + e.getMessage())); + if (isReflectedXSS.toLowerCase().equals("no") || isReflectedXSS.toLowerCase().equals("n")) { + //return trackProgress() + return trackProgress(success().feedback("xss-reflected-5b-success").build()); + } else { + return trackProgress(success().feedback("xss-reflected-5b-failure").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/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6a.java b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6a.java index 67b2ab912..4e9e2a372 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6a.java +++ b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6a.java @@ -3,7 +3,15 @@ package org.owasp.webgoat.plugin; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentPath; +import org.owasp.webgoat.assignments.AttackResult; +import org.owasp.webgoat.session.UserSessionData; +import org.springframework.beans.factory.annotation.Autowired; +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; /*************************************************************************************************** @@ -38,176 +46,19 @@ import org.owasp.webgoat.assignments.AssignmentPath; */ @AssignmentPath("/CrossSiteScripting/attack6a") public class CrossSiteScriptingLesson6a 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 -- + @Autowired + UserSessionData userSessionData; - } + @RequestMapping(method = RequestMethod.POST) + public @ResponseBody + AttackResult completed(@RequestParam String DOMTestRoute) throws IOException { - protected AttackResult injectableQuery(String accountName) - { - try - { - Connection connection = DatabaseUtilities.getConnection(getWebSession()); - String query = "SELECT * FROM user_data WHERE 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() == true)) - { - 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(AttackResult.success("You have succeed: " + output.toString())); - } else { - return trackProgress(AttackResult.failed("You are close, try again. " + output.toString())); - } - - } - else - { - return trackProgress(AttackResult.failed("No Results Matched. Try Again. ")); - - } - } catch (SQLException sqle) - { - - return trackProgress(AttackResult.failed(sqle.getMessage())); - } - } catch (Exception e) - { - e.printStackTrace(); - return trackProgress(AttackResult.failed( "ErrorGenerating" + this.getClass().getName() + " : " + e.getMessage())); + if (DOMTestRoute.equals("start.mvc#test/")) { + //return trackProgress() + return trackProgress(success().feedback("xss-reflected-6a-success").build()); + } else { + return trackProgress(failed().feedback("xss-reflected-6a-failure").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/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6b.java b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6b.java deleted file mode 100644 index d58cbe90a..000000000 --- a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6b.java +++ /dev/null @@ -1,95 +0,0 @@ - -package org.owasp.webgoat.plugin; - -import org.owasp.webgoat.assignments.AssignmentEndpoint; -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.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - - - -/*************************************************************************************************** - * - * - * 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("/CrossSiteScripting/attack6b") -public class CrossSiteScriptingLesson6b extends AssignmentEndpoint { - - @RequestMapping(method = RequestMethod.POST) - public @ResponseBody AttackResult completed(@RequestParam String userid_6b, HttpServletRequest request) throws IOException { - if (userid_6b.toString().equals(getPassword())) { - return trackProgress(success().build()); - } else { - return trackProgress(failed().build()); - } - } - - protected String getPassword() - { - - String password="dave"; - try - { - Connection connection = DatabaseUtilities.getConnection(getWebSession()); - String query = "SELECT password FROM user_system_data WHERE user_name = 'dave'"; - - try - { - Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_READ_ONLY); - ResultSet results = statement.executeQuery(query); - - if ((results != null) && (results.first() == true)) - { - password = results.getString("password"); - } - } catch (SQLException sqle) - { - sqle.printStackTrace(); - // do nothing - } - } catch (Exception e) - { - e.printStackTrace(); - // do nothing - } - return (password); - } -} diff --git a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/DOMCrossSiteScripting.java b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/DOMCrossSiteScripting.java index 0acb4e38b..c4ceea5b4 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/DOMCrossSiteScripting.java +++ b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/DOMCrossSiteScripting.java @@ -19,17 +19,17 @@ public class DOMCrossSiteScripting extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) public @ResponseBody AttackResult completed(@RequestParam Integer param1, - @RequestParam Integer param2, HttpServletRequest request) - throws IOException { - + @RequestParam Integer param2, HttpServletRequest request) throws IOException { if (param1 == 42 && param2 == 24 && request.getHeader("webgoat-requested-by").equals("dom-xss-vuln")) { + System.out.println("DOM-XSS successful"); return trackProgress(success().build()); } else { return trackProgress(failed().build()); } } } - +// something like ... http://localhost:8080/WebGoat/start.mvc#test/testParam=foobar&_someVar=234902384lotslsfjdOf9889080GarbageHere%3Cscript%3Ewebgoat.customjs.phoneHome();%3C%2Fscript%3E +// or http://localhost:8080/WebGoat/start.mvc#test/testParam=foobar&_someVar=234902384lotslsfjdOf9889080GarbageHere". \ No newline at end of file diff --git a/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content5b.adoc b/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content5b.adoc index f4e3b0570..477752127 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content5b.adoc +++ b/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content5b.adoc @@ -1,4 +1,5 @@ == Was it Really Reflected XSS? -Now, was the last attack truly reflected XSS? +You should have been able to execute script with the last example. Was it truly reflected XSS? + diff --git a/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content5c.adoc b/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content5c.adoc new file mode 100644 index 000000000..ffc47194a --- /dev/null +++ b/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content5c.adoc @@ -0,0 +1,9 @@ +== Was it Really Reflected XSS? + +The last example was not truly reflected XSS ... Why you say? +# Can you execute it by changing the URL? (No) +# If you do follow the actual payload in a new tab, does it execute the script? (No ... go ahead and give it a try) + +The reason for #2 is that the response type + + diff --git a/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content6.adoc b/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content6.adoc index eaa6c8884..1445c3baf 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content6.adoc +++ b/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content6.adoc @@ -1,10 +1,12 @@ == DOM-Based XSS Scenario +DOM-based XSS is similar to reflected. The difference is that the payload will never go to the server, but will only ever be processed by the client. + * Attacker sends a malicious URL to victim -* Victim clicks on the link that loads malicious web page -* The malicious web page's JavaScript opens a local web page on the victims machine that contains an attack -* The local page executes attack in the computer’s local zone +* Victim clicks on the link +* That link may load a malicious web page or a web page they use (are logged into?) that has a vulnerable route/handler +* If it's a malicious web page, it may use it's own JavaScript to attack another page/url with a vulnerable route/handler +* The vulnerable page renders the payload and executes attack in the user's context on that page/site * Attacker’s malicious script may run commands with the privileges of local account -*Victim does not realize attack occurred* - +*Victim does not realize attack occurred* ... Malicious attackers don't use <script>alert('xss')</ script> \ No newline at end of file diff --git a/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content6a.adoc b/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content6a.adoc index 1726ff547..9d4ce0689 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content6a.adoc +++ b/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/CrossSiteScripting/lessonPlans/en/CrossSiteScripting_content6a.adoc @@ -1,3 +1,12 @@ == Try It! DOM-Based XSS -Need A Lesson +For this, you'll want to look for some 'test' code in the route handlers (javascript/backbone). Sometimes, test code gets left in. +(Often times test code is very simple and lacks security or any quality controls!). + +Your objective is to find the route and exploit it. First though ... what is the base route? As an example, look at the URL for this lesson ... +it should look something like /WebGoat/start.mvc#lesson/CrossSiteScripting.lesson/5 (although maybe slightly different). The 'base route' in this case is: +*start.mvc#lesson/* + +The *CrossSiteScripting.lesson/5* after that are parameters that are processed by javascript route handler. + +So, what is test route for this test code? diff --git a/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/i18n/WebGoatLabels.properties b/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/i18n/WebGoatLabels.properties index 2b0bc8c70..af10c440a 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/i18n/WebGoatLabels.properties +++ b/webgoat-lessons/cross-site-scripting/src/main/resources/plugin/i18n/WebGoatLabels.properties @@ -1,10 +1,10 @@ -#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. -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 ]. +# XSS success, failure messages and hints +xss-reflected-5a-success=well done, but alerts aren't very impressive are they? Please continue. +xss-reflected-5a-failure=Try again. We do want to see this specific javascript (in case you are trying to do something more fancy) +xss-reflected-5b-success=Correct ... because +xss-reflected-5b-failure=Nope, pretty easy to guess now though. +xss-reflected-6a-success=Correct! Now, see if you can send in an exploit to that route in the next assignment. +xss-reflected-6a-failure=No, look at the example. Check the GoatRouter.js file. It should be pretty easy to determine. +xss.lesson1.failure=Are you sure? Try using a tab from a different site. -xss.lesson1.failure=Are you sure? Try using a tab from a different site. \ No newline at end of file +#xss-reflected-5b-do5a-first=Do the reflected xss attack prior to this, then come back and answer this. \ No newline at end of file