XSS lesson updates
This commit is contained in:
parent
af8f8c27a6
commit
7f532f0ffc
@ -18,6 +18,10 @@ public class UserSessionData {
|
|||||||
|
|
||||||
//GETTERS & SETTERS
|
//GETTERS & SETTERS
|
||||||
public Object getValue(String key) {
|
public Object getValue(String key) {
|
||||||
|
if (!userSessionData.containsKey(key)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// else
|
||||||
return userSessionData.get(key);
|
return userSessionData.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ define(['jquery',
|
|||||||
webgoat.customjs.jquery = $; //passing jquery into custom js scope ... still klunky, but works for now
|
webgoat.customjs.jquery = $; //passing jquery into custom js scope ... still klunky, but works for now
|
||||||
webgoat.customjs.jqueryVuln = $vuln;
|
webgoat.customjs.jqueryVuln = $vuln;
|
||||||
|
|
||||||
// temporary shim to support dom-xss lesson
|
// temporary shim to support dom-xss assignment
|
||||||
webgoat.customjs.phoneHome = function (e) {
|
webgoat.customjs.phoneHome = function (e) {
|
||||||
console.log('phoneHome invoked');
|
console.log('phoneHome invoked');
|
||||||
console.log(arguments.callee);
|
console.log(arguments.callee);
|
||||||
@ -97,6 +97,11 @@ define(['jquery',
|
|||||||
this.menuController.updateMenu(name);
|
this.menuController.updateMenu(name);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
testRoute: function (param) {
|
||||||
|
this.lessonController.testHandler(param);
|
||||||
|
//this.menuController.updateMenu(name);
|
||||||
|
},
|
||||||
|
|
||||||
welcomeRoute: function () {
|
welcomeRoute: function () {
|
||||||
render();
|
render();
|
||||||
this.lessonController.loadWelcome();
|
this.lessonController.loadWelcome();
|
||||||
|
@ -114,7 +114,9 @@ define(['jquery',
|
|||||||
this.renderFeedback(data.feedback);
|
this.renderFeedback(data.feedback);
|
||||||
|
|
||||||
this.renderOutput(data.output || "");
|
this.renderOutput(data.output || "");
|
||||||
if (data.assignmentCompleted) {
|
//TODO: refactor back assignmentCompleted in Java
|
||||||
|
if (data.lessonCompleted || data.assignmentCompleted) {
|
||||||
|
|
||||||
this.markAssignmentComplete();
|
this.markAssignmentComplete();
|
||||||
this.trigger('assignment:complete');
|
this.trigger('assignment:complete');
|
||||||
} else {
|
} else {
|
||||||
|
34
webgoat-lessons/command-injection/pom.xml
Normal file
34
webgoat-lessons/command-injection/pom.xml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>http-proxies</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.owasp.webgoat.lesson</groupId>
|
||||||
|
<artifactId>webgoat-lessons-parent</artifactId>
|
||||||
|
<version>8.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-test</artifactId>
|
||||||
|
<version>4.1.3.RELEASE</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>${junit.version}</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -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/
|
||||||
|
* <p>
|
||||||
|
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||||
|
* <p>
|
||||||
|
* 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.
|
||||||
|
* <p>
|
||||||
|
* 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.
|
||||||
|
* <p>
|
||||||
|
* 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.
|
||||||
|
* <p>
|
||||||
|
* Getting Source ==============
|
||||||
|
* <p>
|
||||||
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||||
|
* projects.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @author WebGoat
|
||||||
|
* @version $Id: $Id
|
||||||
|
* @since October 12, 2016
|
||||||
|
*/
|
||||||
|
public class HttpProxies extends NewLesson {
|
||||||
|
@Override
|
||||||
|
public Category getDefaultCategory() {
|
||||||
|
return Category.GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getHints() {
|
||||||
|
return Lists.newArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getDefaultRanking() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTitle() {
|
||||||
|
return "http-proxies.title";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "HttpProxies";
|
||||||
|
}
|
||||||
|
}
|
@ -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 <a href="http://code.google.com/p/webgoat">WebGoat</a>
|
||||||
|
* @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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
|
||||||
|
<div class="lesson-page-wrapper">
|
||||||
|
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||||
|
<!-- include content here. Content will be presented via asciidocs files,
|
||||||
|
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||||
|
<div class="adoc-content" th:replace="doc:HttpBasics_ProxyIntro0.adoc"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="lesson-page-wrapper">
|
||||||
|
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||||
|
<!-- include content here. Content will be presented via asciidocs files,
|
||||||
|
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||||
|
<div class="adoc-content" th:replace="doc:HttpBasics_ProxyIntro1.adoc"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="lesson-page-wrapper">
|
||||||
|
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||||
|
<!-- include content here. Content will be presented via asciidocs files,
|
||||||
|
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||||
|
<div class="adoc-content" th:replace="doc:HttpBasics_ProxyIntro2.adoc"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="lesson-page-wrapper">
|
||||||
|
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||||
|
<!-- include content here. Content will be presented via asciidocs files,
|
||||||
|
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||||
|
<div class="adoc-content" th:replace="doc:HttpBasics_ProxyIntro3.adoc"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="lesson-page-wrapper">
|
||||||
|
<!-- stripped down without extra comments -->
|
||||||
|
<div class="adoc-content" th:replace="doc:HttpBasics_ProxyIntercept.adoc"></div>
|
||||||
|
<div class="attack-container">
|
||||||
|
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||||
|
<form class="attack-form" accept-charset="UNKNOWN" name="intercept-request"
|
||||||
|
method="POST"
|
||||||
|
action="/WebGoat/HttpBasics/intercept-request"
|
||||||
|
enctype="application/json;charset=UTF-8">
|
||||||
|
|
||||||
|
<input type="text" value="doesn't matter really" name="changeMe" />
|
||||||
|
<input type="submit" value="Submit" />
|
||||||
|
|
||||||
|
</form>
|
||||||
|
<div class="attack-feedback"></div>
|
||||||
|
<div class="attack-output"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</html>
|
@ -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.
|
@ -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!
|
@ -4,6 +4,8 @@ package org.owasp.webgoat.plugin;
|
|||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
import org.owasp.webgoat.assignments.AssignmentPath;
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
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.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
@ -47,21 +49,44 @@ import java.io.IOException;
|
|||||||
@AssignmentPath("/CrossSiteScripting/attack5a")
|
@AssignmentPath("/CrossSiteScripting/attack5a")
|
||||||
public class CrossSiteScriptingLesson5a extends AssignmentEndpoint {
|
public class CrossSiteScriptingLesson5a extends AssignmentEndpoint {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.POST)
|
@Autowired
|
||||||
|
UserSessionData userSessionData;
|
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET)
|
||||||
public @ResponseBody AttackResult completed(@RequestParam Integer QTY1,
|
public @ResponseBody AttackResult completed(@RequestParam Integer QTY1,
|
||||||
@RequestParam Integer QTY2, @RequestParam Integer QTY3,
|
@RequestParam Integer QTY2, @RequestParam Integer QTY3,
|
||||||
@RequestParam Integer QTY4, @RequestParam String field1,
|
@RequestParam Integer QTY4, @RequestParam String field1,
|
||||||
@RequestParam Integer field2, HttpServletRequest request)
|
@RequestParam Integer field2, HttpServletRequest request)
|
||||||
throws IOException {
|
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 :)
|
// 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;
|
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();
|
StringBuffer cart = new StringBuffer();
|
||||||
cart.append("Thank you for shopping at WebGoat. <br />You're support is appreciated<hr />");
|
cart.append("Thank you for shopping at WebGoat. <br />You're support is appreciated<hr />");
|
||||||
cart.append("<p>We have chaged credit card:" + field1 + "<br />");
|
cart.append("<p>We have chaged credit card:" + field1 + "<br />");
|
||||||
cart.append( " ------------------- <br />");
|
cart.append( " ------------------- <br />");
|
||||||
cart.append( " $" + totalSale);
|
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("<script>alert('my javascript here')</script>")) {
|
||||||
|
//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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,7 +4,16 @@ package org.owasp.webgoat.plugin;
|
|||||||
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
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")
|
@AssignmentPath("/CrossSiteScripting/attack5b")
|
||||||
public class CrossSiteScriptingLesson5b extends AssignmentEndpoint {
|
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)
|
@Autowired
|
||||||
{
|
UserSessionData userSessionData;
|
||||||
try
|
|
||||||
{
|
|
||||||
Connection connection = DatabaseUtilities.getConnection(getWebSession());
|
|
||||||
String query = "SELECT * FROM user_data WHERE userid = " + accountName;
|
|
||||||
|
|
||||||
try
|
@RequestMapping(method = RequestMethod.POST)
|
||||||
{
|
public @ResponseBody
|
||||||
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
|
AttackResult completed(@RequestParam String isReflectedXSS) throws IOException {
|
||||||
ResultSet.CONCUR_READ_ONLY);
|
// init
|
||||||
ResultSet results = statement.executeQuery(query);
|
System.out.println(userSessionData.getValue("xss-reflected5a-complete"));
|
||||||
|
|
||||||
if ((results != null) && (results.first() == true))
|
//TODO
|
||||||
{
|
// if (null == userSessionData.getValue("xss-reflected5a-complete") || userSessionData.getValue("xss-reflected-5a-complete").equals("false")) {
|
||||||
ResultSetMetaData resultsMetaData = results.getMetaData();
|
// //userSessionData.setValue("xss-reflected1-complete",(Object)"false");
|
||||||
StringBuffer output = new StringBuffer();
|
// return trackProgress(success().feedback("xss-reflected-5b-do5a-first").build());
|
||||||
|
// }
|
||||||
|
|
||||||
output.append(writeTable(results, resultsMetaData));
|
if (isReflectedXSS.toLowerCase().equals("no") || isReflectedXSS.toLowerCase().equals("n")) {
|
||||||
results.last();
|
//return trackProgress()
|
||||||
|
return trackProgress(success().feedback("xss-reflected-5b-success").build());
|
||||||
// If they get back more than one user they succeeded
|
} else {
|
||||||
if (results.getRow() >= 6)
|
return trackProgress(success().feedback("xss-reflected-5b-failure").build());
|
||||||
{
|
|
||||||
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()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws IOException,
|
|
||||||
SQLException
|
|
||||||
{
|
|
||||||
int numColumns = resultsMetaData.getColumnCount();
|
|
||||||
results.beforeFirst();
|
|
||||||
StringBuffer t = new StringBuffer();
|
|
||||||
t.append("<p>");
|
|
||||||
|
|
||||||
if (results.next())
|
|
||||||
{
|
|
||||||
for (int i = 1; i < (numColumns + 1); i++)
|
|
||||||
{
|
|
||||||
t.append(resultsMetaData.getColumnName(i));
|
|
||||||
t.append(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
t.append("<br />");
|
|
||||||
results.beforeFirst();
|
|
||||||
|
|
||||||
while (results.next())
|
|
||||||
{
|
|
||||||
|
|
||||||
for (int i = 1; i < (numColumns + 1); i++)
|
|
||||||
{
|
|
||||||
t.append(results.getString(i));
|
|
||||||
t.append(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
t.append("<br />");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
t.append ("Query Successful; however no data was returned from this query.");
|
|
||||||
}
|
|
||||||
|
|
||||||
t.append("</p>");
|
|
||||||
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;
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,15 @@ package org.owasp.webgoat.plugin;
|
|||||||
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
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")
|
@AssignmentPath("/CrossSiteScripting/attack6a")
|
||||||
public class CrossSiteScriptingLesson6a extends AssignmentEndpoint {
|
public class CrossSiteScriptingLesson6a extends AssignmentEndpoint {
|
||||||
/*
|
@Autowired
|
||||||
@RequestMapping(method = RequestMethod.POST)
|
UserSessionData userSessionData;
|
||||||
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 DOMTestRoute) throws IOException {
|
||||||
|
|
||||||
protected AttackResult injectableQuery(String accountName)
|
if (DOMTestRoute.equals("start.mvc#test/")) {
|
||||||
{
|
//return trackProgress()
|
||||||
try
|
return trackProgress(success().feedback("xss-reflected-6a-success").build());
|
||||||
{
|
} else {
|
||||||
Connection connection = DatabaseUtilities.getConnection(getWebSession());
|
return trackProgress(failed().feedback("xss-reflected-6a-failure").build());
|
||||||
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()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws IOException,
|
|
||||||
SQLException
|
|
||||||
{
|
|
||||||
int numColumns = resultsMetaData.getColumnCount();
|
|
||||||
results.beforeFirst();
|
|
||||||
StringBuffer t = new StringBuffer();
|
|
||||||
t.append("<p>");
|
|
||||||
|
|
||||||
if (results.next())
|
|
||||||
{
|
|
||||||
for (int i = 1; i < (numColumns + 1); i++)
|
|
||||||
{
|
|
||||||
t.append(resultsMetaData.getColumnName(i));
|
|
||||||
t.append(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
t.append("<br />");
|
|
||||||
results.beforeFirst();
|
|
||||||
|
|
||||||
while (results.next())
|
|
||||||
{
|
|
||||||
|
|
||||||
for (int i = 1; i < (numColumns + 1); i++)
|
|
||||||
{
|
|
||||||
t.append(results.getString(i));
|
|
||||||
t.append(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
t.append("<br />");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
t.append ("Query Successful; however no data was returned from this query.");
|
|
||||||
}
|
|
||||||
|
|
||||||
t.append("</p>");
|
|
||||||
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;
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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 <a href="http://code.google.com/p/webgoat">WebGoat</a>
|
|
||||||
* @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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,17 +19,17 @@ public class DOMCrossSiteScripting extends AssignmentEndpoint {
|
|||||||
@RequestMapping(method = RequestMethod.POST)
|
@RequestMapping(method = RequestMethod.POST)
|
||||||
public @ResponseBody
|
public @ResponseBody
|
||||||
AttackResult completed(@RequestParam Integer param1,
|
AttackResult completed(@RequestParam Integer param1,
|
||||||
@RequestParam Integer param2, HttpServletRequest request)
|
@RequestParam Integer param2, HttpServletRequest request) throws IOException {
|
||||||
throws IOException {
|
|
||||||
|
|
||||||
if (param1 == 42 && param2 == 24 && request.getHeader("webgoat-requested-by").equals("dom-xss-vuln")) {
|
if (param1 == 42 && param2 == 24 && request.getHeader("webgoat-requested-by").equals("dom-xss-vuln")) {
|
||||||
|
System.out.println("DOM-XSS successful");
|
||||||
return trackProgress(success().build());
|
return trackProgress(success().build());
|
||||||
} else {
|
} else {
|
||||||
return trackProgress(failed().build());
|
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<script>webgoat.customjs.phoneHome();<%2Fscript>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@
|
|||||||
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
|
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
|
||||||
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
|
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
|
||||||
<form class="attack-form" accept-charset="UNKNOWN"
|
<form class="attack-form" accept-charset="UNKNOWN"
|
||||||
method="POST" name="form"
|
method="GET" name="xss-5a"
|
||||||
action="/WebGoat/CrossSiteScripting/attack5a"
|
action="/WebGoat/CrossSiteScripting/attack5a"
|
||||||
enctype="application/json;charset=UTF-8">
|
enctype="application/json;charset=UTF-8">
|
||||||
<hr width="90%" />
|
<hr width="90%" />
|
||||||
@ -161,11 +161,27 @@
|
|||||||
<div class="attack-output"></div>
|
<div class="attack-output"></div>
|
||||||
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
|
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="lesson-page-wrapper">
|
||||||
|
<div class="adoc-content" th:replace="doc:CrossSiteScripting_content5b.adoc"></div>
|
||||||
|
<div class="attack-container">
|
||||||
|
<form class="attack-form" accept-charset="UNKNOWN"
|
||||||
|
method="POST" name="xss-5b"
|
||||||
|
action="/WebGoat/CrossSiteScripting/attack5b"
|
||||||
|
enctype="application/json;charset=UTF-8">
|
||||||
|
<input size="4" value="" name="isReflectedXSS" type="text" />
|
||||||
|
<input type="submit" name="reflectedXssSubmit" value="Submit"/>
|
||||||
|
</form>
|
||||||
|
<!-- do not remove the two following div's, this is where your feedback/output will land -->
|
||||||
|
<div class="attack-feedback"></div>
|
||||||
|
<div class="attack-output"></div>
|
||||||
|
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:CrossSiteScripting_content6.adoc"></div>
|
<div class="adoc-content" th:replace="doc:CrossSiteScripting_content6.adoc"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
@ -180,18 +196,11 @@
|
|||||||
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
|
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
|
||||||
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
|
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
|
||||||
<form class="attack-form" accept-charset="UNKNOWN"
|
<form class="attack-form" accept-charset="UNKNOWN"
|
||||||
method="POST" name="form"
|
method="POST" name="DOMTestRoute"
|
||||||
action="/WebGoat/CrossSiteScripting/attack6a"
|
action="/WebGoat/CrossSiteScripting/attack6a"
|
||||||
enctype="application/json;charset=UTF-8">
|
enctype="application/json;charset=UTF-8">
|
||||||
<table>
|
<input name="DOMTestRoute" value="" type="TEXT" />
|
||||||
<tr>
|
<input name="SubmitTestRoute" value="Submit" type="SUBMIT"/>
|
||||||
<td>Name:</td>
|
|
||||||
<td><input name="userid_6a" value="" type="TEXT" /></td>
|
|
||||||
<td><input
|
|
||||||
name="Get Account Info" value="Get Account Info" type="SUBMIT"/></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</form>
|
</form>
|
||||||
<!-- do not remove the two following div's, this is where your feedback/output will land -->
|
<!-- do not remove the two following div's, this is where your feedback/output will land -->
|
||||||
<div class="attack-feedback"></div>
|
<div class="attack-feedback"></div>
|
||||||
|
@ -1,14 +1,21 @@
|
|||||||
== What is XSS
|
== What is XSS
|
||||||
|
|
||||||
NEED DEFINITION.
|
Cross-site script (also commonly known as XSS) is a vulnerability/flaw that combines ...
|
||||||
|
# the allowance of html/script tags as input that are ...
|
||||||
|
# rendred into a browser without encoding or sanitization
|
||||||
|
|
||||||
==== Cross site scripting (XSS) is the most prevalent and pernicious web application security issue
|
=== Cross site scripting (XSS) is the most prevalent and pernicious web application security issue
|
||||||
|
|
||||||
==== XSS flaws occur whenever an application takes user originated data and sends it to a web browser without validation or encoding
|
While there is a simple well-known defense for this attack, there are still many instances of it on the web. In terms of fixing it,
|
||||||
|
coverage of fixes also tends to be a problem. We'll talk more about the defense in a little bit.
|
||||||
|
|
||||||
=== XSS allows attackers to execute script in the victim’s browser and take over the user’s browser using scripting malware
|
=== XSS has a significant impact
|
||||||
|
|
||||||
==== Examples:
|
Especially as 'Rich Internet Applications' are more and more common place, privileged function calls linked to via javascript may be compromised.
|
||||||
|
And if not properly protected, sensitive data (such as your authentication cookies) can be stolen and used for someone else's purpose.
|
||||||
|
|
||||||
|
|
||||||
|
==== Quick examples:
|
||||||
* From the browser address bar (chrome, Firefox)
|
* From the browser address bar (chrome, Firefox)
|
||||||
+
|
+
|
||||||
----
|
----
|
||||||
@ -22,4 +29,5 @@ javascript:alert(document.cookie);
|
|||||||
----
|
----
|
||||||
|
|
||||||
== Try It! Using Chrome or Firefox
|
== Try It! Using Chrome or Firefox
|
||||||
Type in `javascript:alert(document.cookie);` in the URL bar. If you /cut/paste you'll need to add the `javascript:` back in. Try it on a different tab.
|
Type in `javascript:alert(document.cookie);` in the URL bar. *NOTE:* If you /cut/paste you'll need to add the `javascript:` back in.
|
||||||
|
Try it on a different tab (with WebGoat open in that tab).
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* Insertion of hostile and inappropriate content
|
* Insertion of hostile and inappropriate content
|
||||||
+
|
+
|
||||||
----
|
----
|
||||||
<img src=“http://pornsite.com/image.jpg/>
|
<img src=“http://malicious.site.com/image.jpg/>
|
||||||
“>GoodYear recommends buying BridgeStone tires…
|
“>GoodYear recommends buying BridgeStone tires…
|
||||||
----
|
----
|
||||||
|
|
||||||
|
@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
=== Reflected
|
=== Reflected
|
||||||
* Malicious content from a user request is displayed to the user in a web browser
|
* Malicious content from a user request is displayed to the user in a web browser
|
||||||
* Malicious content is written into the page via server code
|
* Malicious content is written into the page after from server response
|
||||||
* Social engineering is required
|
* Social engineering is required
|
||||||
|
* Runs with browser privileges inherited from user in browser
|
||||||
|
|
||||||
=== Local: DOM-based
|
=== DOM-based (also technically reflected)
|
||||||
* Malicious content from a user request is used by client-side scripts to write HTML to it own page
|
* Malicious content from a user request is used by client-side scripts to write HTML to it own page
|
||||||
* Similar to reflected XSS
|
* Similar to reflected XSS
|
||||||
* Runs with browser privileges
|
* Runs with browser privileges inherited from user in browser
|
||||||
|
|
||||||
=== Stored or Persistent
|
=== Stored or Persistent
|
||||||
* Malicious content is stored on the server ( in a database, file system, or other object ) and later displayed to users in a web browser
|
* Malicious content is stored on the server ( in a database, file system, or other object ) and later displayed to users in a web browser
|
||||||
|
@ -2,5 +2,7 @@
|
|||||||
|
|
||||||
Identify which field is susceptible to XSS
|
Identify which field is susceptible to XSS
|
||||||
|
|
||||||
It is always a good practice to validate all input on the server side. XSS can occur when unvalidated user input is used in an HTTP response. In a reflected XSS attack, an attacker can craft a URL with the attack script and post it to another website, email it, or otherwise get a victim to click on it.
|
It is always a good practice to validate all input on the server side. XSS can occur when unvalidated user input is used in an HTTP response.
|
||||||
|
In a reflected XSS attack, an attacker can craft a URL with the attack script and post it to another website, email it, or otherwise get a victim to click on it.
|
||||||
|
|
||||||
|
Make sure to include in your attack payload "<script>alert('my javascript here')</script>".
|
@ -1,4 +1,5 @@
|
|||||||
== Was it Really Reflected XSS?
|
== 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?
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
|||||||
== DOM-Based XSS Scenario
|
== 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
|
* Attacker sends a malicious URL to victim
|
||||||
* Victim clicks on the link that loads malicious web page
|
* Victim clicks on the link
|
||||||
* The malicious web page's JavaScript opens a local web page on the victims machine that contains an attack
|
* That link may load a malicious web page or a web page they use (are logged into?) that has a vulnerable route/handler
|
||||||
* The local page executes attack in the computer’s local zone
|
* 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
|
* 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>
|
||||||
|
|
@ -1,3 +1,12 @@
|
|||||||
== Try It! DOM-Based XSS
|
== 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?
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
#StringSqlInjection.java
|
# XSS success, failure messages and hints
|
||||||
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.
|
xss-reflected-5a-success=well done, but alerts aren't very impressive are they? Please continue.
|
||||||
EnterLastName=Enter your last name:
|
xss-reflected-5a-failure=Try again. We do want to see this specific javascript (in case you are trying to do something more fancy)
|
||||||
NoResultsMatched=No results matched. Try Again.
|
xss-reflected-5b-success=Correct ... because <ul><li>The script was not triggered by the URL/QueryString</li><li>Even if you use the attack URL in a new tab, it won't execute (becuase of response type). Try it if you like.</li></ul>
|
||||||
SqlStringInjectionHint1=The application is taking your input and inserting it at the end of a pre-formed SQL command.
|
xss-reflected-5b-failure=Nope, pretty easy to guess now though.
|
||||||
SqlStringInjectionHint2=This is the code for the query being built and issued by WebGoat:<br><br> "SELECT * FROM user_data WHERE last_name = "accountName"
|
xss-reflected-6a-success=Correct! Now, see if you can send in an exploit to that route in the next assignment.
|
||||||
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
|
xss-reflected-6a-failure=No, look at the example. Check the GoatRouter.js file. It should be pretty easy to determine.
|
||||||
SqlStringInjectionHint4=Try entering [ smith' OR '1' = '1 ].
|
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.
|
#xss-reflected-5b-do5a-first=Do the reflected xss attack prior to this, then come back and answer this.
|
Loading…
x
Reference in New Issue
Block a user