Initial cut on CSRF. More to come
This commit is contained in:
BIN
webgoat-lessons/csrf/src/main/.DS_Store
vendored
Normal file
BIN
webgoat-lessons/csrf/src/main/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
webgoat-lessons/csrf/src/main/java/.DS_Store
vendored
Normal file
BIN
webgoat-lessons/csrf/src/main/java/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
webgoat-lessons/csrf/src/main/java/org/.DS_Store
vendored
Normal file
BIN
webgoat-lessons/csrf/src/main/java/org/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
webgoat-lessons/csrf/src/main/java/org/owasp/.DS_Store
vendored
Normal file
BIN
webgoat-lessons/csrf/src/main/java/org/owasp/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/.DS_Store
vendored
Normal file
BIN
webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/.DS_Store
vendored
Normal file
Binary file not shown.
@ -0,0 +1,36 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* Created by jason on 9/29/17.
|
||||
*/
|
||||
public class CSRF extends NewLesson {
|
||||
@Override
|
||||
public Category getDefaultCategory() {
|
||||
return Category.REQUEST_FORGERIES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getHints() {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getDefaultRanking() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() { return "csrf.title"; }
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "CSRF";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package org.owasp.webgoat.plugin;
|
||||
|
||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
||||
import org.owasp.webgoat.assignments.AttackResult;
|
||||
import org.owasp.webgoat.session.UserSessionData;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Created by jason on 9/29/17.
|
||||
*/
|
||||
|
||||
@AssignmentPath("/csrf/confirm-flag-1")
|
||||
@AssignmentHints({""})
|
||||
public class CSRFConfirmFlag1 extends AssignmentEndpoint {
|
||||
|
||||
@Autowired
|
||||
UserSessionData userSessionData;
|
||||
|
||||
@PostMapping(produces = {"application/json"})
|
||||
public @ResponseBody AttackResult completed(String confirmFlagVal) {
|
||||
// String host = (req.getHeader("host") == null) ? "NULL" : req.getHeader("host");
|
||||
// String origin = (req.getHeader("origin") == null) ? "NULL" : req.getHeader("origin");
|
||||
// Integer serverPort = (req.getServerPort() < 1) ? 0 : req.getServerPort();
|
||||
// String serverName = (req.getServerName() == null) ? "NULL" : req.getServerName();
|
||||
// String referer = (req.getHeader("referer") == null) ? "NULL" : req.getHeader("referer");
|
||||
|
||||
if (confirmFlagVal.equals(userSessionData.getValue("csrf-get-success"))) {
|
||||
return success().feedback("csrf-get-success").output("Correct, the flag was " + userSessionData.getValue("csrf-get-success")).build();
|
||||
}
|
||||
return failed().feedback("").build();
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package org.owasp.webgoat.plugin;
|
||||
|
||||
import org.owasp.webgoat.assignments.Endpoint;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
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.ResponseBody;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by jason on 9/30/17.
|
||||
*/
|
||||
|
||||
public class CSRFGetFlag extends Endpoint {
|
||||
|
||||
@Autowired
|
||||
UserSessionData userSessionData;
|
||||
@Autowired
|
||||
private PluginMessages pluginMessages;
|
||||
|
||||
@RequestMapping(produces = {"application/json"}, method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public Map<String, Object> invoke(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
|
||||
Map<String,Object> response = new HashMap<>();
|
||||
|
||||
String host = (req.getHeader("host") == null) ? "NULL" : req.getHeader("host");
|
||||
String origin = (req.getHeader("origin") == null) ? "NULL" : req.getHeader("origin");
|
||||
Integer serverPort = (req.getServerPort() < 1) ? 0 : req.getServerPort();
|
||||
String serverName = (req.getServerName() == null) ? "NULL" : req.getServerName();
|
||||
String referer = (req.getHeader("referer") == null) ? "NULL" : req.getHeader("referer");
|
||||
String[] refererArr = referer.split("/");
|
||||
|
||||
if (referer.equals("NULL") && req.getParameter("csrf").equals("true")) {
|
||||
userSessionData.setValue("csrf-get-success", Math.floor(Math.random()*100000));
|
||||
response.put("success",true);
|
||||
response.put("message",pluginMessages.getMessage("csrf-get-null-referer.success"));
|
||||
response.put("flag",userSessionData.getValue("csrf-get-success"));
|
||||
} else if (refererArr[2].equals(host)) {
|
||||
response.put("success", false);
|
||||
response.put("message", "Appears the request came from the original host");
|
||||
response.put("flag", null);
|
||||
} else {
|
||||
response.put("success", false);
|
||||
response.put("message", "TBD");
|
||||
response.put("flag", null);
|
||||
}
|
||||
|
||||
return response;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return "/csrf/basic-get-flag";
|
||||
}
|
||||
}
|
BIN
webgoat-lessons/csrf/src/main/resources/.DS_Store
vendored
Normal file
BIN
webgoat-lessons/csrf/src/main/resources/.DS_Store
vendored
Normal file
Binary file not shown.
57
webgoat-lessons/csrf/src/main/resources/html/CSRF.html
Normal file
57
webgoat-lessons/csrf/src/main/resources/html/CSRF.html
Normal file
@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:CSRF_intro.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:CSRF_GET.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:CSRF_Get_Flag.adoc"></div>
|
||||
|
||||
<form accept-charset="UNKNOWN" id="basic-csrf-get"
|
||||
method="GET" name="form1"
|
||||
successCallback=""
|
||||
action="/WebGoat/csrf/basic-get-flag"
|
||||
enctype="application/json;charset=UTF-8">
|
||||
<input name="csrf" type="hidden" value="false" />
|
||||
<input type="submit" name="ubmit=" />
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
|
||||
<div class="adoc-content" th:replace="doc:CSRF_Basic_Get-1.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" id="confirm-flag-1"
|
||||
method="POST" name="form2"
|
||||
successCallback=""
|
||||
action="/WebGoat/csrf/basic-confirm-flag"
|
||||
enctype="application/json;charset=UTF-8">
|
||||
|
||||
Confirm Flag Value:
|
||||
<input type="text" length="6" name="confirmFlagVal" value="false" />
|
||||
|
||||
<input name="submit" value="Submit" type="submit"/>
|
||||
|
||||
</form>
|
||||
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!--</div>-->
|
||||
|
||||
</html>
|
@ -0,0 +1,4 @@
|
||||
csrf.title=Cross-Site Request Forgeries
|
||||
csrf-get-null-referer.success=Congratulations! Appears you made the request from your local machine.
|
||||
csrf-get-other-referer.successfeedback=Congratulations! Appears you made the request from\
|
||||
|
BIN
webgoat-lessons/csrf/src/main/resources/lessonPlans/.DS_Store
vendored
Normal file
BIN
webgoat-lessons/csrf/src/main/resources/lessonPlans/.DS_Store
vendored
Normal file
Binary file not shown.
@ -0,0 +1,3 @@
|
||||
== Confirm Flag
|
||||
|
||||
Confirm the flag you should have gotten on the previous page below.
|
@ -0,0 +1,9 @@
|
||||
== The Base Form
|
||||
|
||||
The form below has hidden elements and submits to an action of TBD. You can try it out and watch what it does, but it won't get you the flag. Once you can
|
||||
|
||||
Every attack in this lesson will need to be done through another page or site. To see your progress, you will need to reload the
|
||||
pages or re-navigate back through the lesson to see your progress.
|
||||
|
||||
Just to get your feet wet, issue a request to _SERVER_/WebGoat/csrf/basic-get-flag with a parameter named 'csrf' equal to 'true'. Your request needs to
|
||||
come from a local file or be hosted on a different website.
|
@ -1,6 +1,6 @@
|
||||
== CSRF with a GET request
|
||||
|
||||
This is the most easiest CSRF attack to perform. For example you receive an e-mail with the following content:
|
||||
This is the most simple CSRF attack to perform. For example you receive an e-mail with the following content:
|
||||
|
||||
`<a href="http://bank.com/transfer?account_number_from=123456789&account_number_to=987654321&amount=100000">View my Pictures!</a>`
|
||||
|
@ -0,0 +1,4 @@
|
||||
== Basic Get CSRF Exercise
|
||||
|
||||
place holder ...
|
||||
|
@ -1,11 +1,11 @@
|
||||
=== What is a Crosse-site request forgery?
|
||||
=== What is a Cross-site request forgery?
|
||||
|
||||
Cross-site request forgery, also known as one-click attack or session riding and abbreviated as CSRF
|
||||
(sometimes pronounced sea-surf) or XSRF, is a type of malicious exploit of a website where unauthorized commands are transmitted
|
||||
from a user that the website trusts. Unlike cross-site scripting (XSS), which exploits the trust a user has for a particular site, CSRF
|
||||
exploits the trust that a site has in a user's browser.
|
||||
|
||||
A cross-site request forgery is a confused deputy attack against a web browser. CSRF commonly has the following characteristics:
|
||||
A cross-site request forgery is a 'confused deputy' attack against a web browser. CSRF commonly has the following characteristics:
|
||||
|
||||
* It involves sites that rely on a user's identity.
|
||||
* It exploits the site's trust in that identity.
|
||||
@ -16,7 +16,7 @@ At risk are web applications that perform actions based on input from trusted an
|
||||
the specific action. A user who is authenticated by a cookie saved in the user's web browser could unknowingly send an HTTP request to a site
|
||||
that trusts the user and thereby causes an unwanted action.
|
||||
|
||||
CSRF attacks target functionality that causes a state change on the server, such as changing the victim's email address or password, or purchasing
|
||||
A CSRF attack targets/abuses basic web functionality. If the site allows that causes a state change on the server, such as changing the victim's email address or password, or purchasing
|
||||
something. Forcing the victim to retrieve data doesn't benefit an attacker because the attacker doesn't receive the response, the victim does.
|
||||
As such, CSRF attacks target state-changing requests.
|
||||
|
@ -1,181 +0,0 @@
|
||||
<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, 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:XXE_plan.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, 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:XXE_intro.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this block for each 'page' of content -->
|
||||
<!-- sample ascii doc content for second page -->
|
||||
<div class="adoc-content" th:replace="doc:XXE_simple.adoc"></div>
|
||||
<!-- if including attack, reuse this section, leave classes in place -->
|
||||
<div class="attack-container">
|
||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||
<!-- using attack-form class on your form will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
||||
<!-- 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 -->
|
||||
<form class="attack-form" accept-charset="UNKNOWN" prepareData="register" method="POST" name="form"
|
||||
action="/WebGoat/XXE/simple" contentType="application/xml">
|
||||
<script th:src="@{/plugin_lessons/plugin/XXE/js/xxe.js}"
|
||||
language="JavaScript"></script>
|
||||
<div id="lessonContent">
|
||||
<strong>Registration form</strong>
|
||||
<form prepareData="register" accept-charset="UNKNOWN" method="POST" name="form" action="#attack/307/100">
|
||||
<table>
|
||||
<tr>
|
||||
<td>Username</td>
|
||||
<td><input name="username" value="" type="TEXT"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>E-mail</td>
|
||||
<td><input name="email" value="" type="TEXT"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password</td>
|
||||
<td><input name="email" value="" type="TEXT"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td align="right"><input type="submit" id="registerButton" value="Sign up"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
<br/>
|
||||
</form>
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
</div>
|
||||
</form>
|
||||
<div id='registration_success'></div>
|
||||
</div>
|
||||
<!-- 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 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:XXE_changing_content_type.adoc"></div>
|
||||
<div class="attack-container">
|
||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||
<!-- using attack-form class on your form will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
||||
<!-- 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 -->
|
||||
<form class="attack-form" accept-charset="UNKNOWN" prepareData="registerJson" method="POST" name="form"
|
||||
action="/WebGoat/XXE/content-type" contentType="application/json">
|
||||
<script th:src="@{/plugin_lessons/plugin/XXE/js/xxe.js}"
|
||||
language="JavaScript"></script>
|
||||
<div id="lessonContent">
|
||||
<strong>Registration form</strong>
|
||||
<form prepareData="registerJson" accept-charset="UNKNOWN" method="POST" name="form" action="#attack/307/100">
|
||||
<table>
|
||||
<tr>
|
||||
<td>Username</td>
|
||||
<td><input name="username" value="" type="TEXT"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>E-mail</td>
|
||||
<td><input name="email" value="" type="TEXT"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password</td>
|
||||
<td><input name="email" value="" type="TEXT"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td align="right"><input type="submit" value="Sign up"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
<br/>
|
||||
</form>
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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:XXE_overflow.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, 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:XXE_blind.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, 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:XXE_blind_assignment.adoc"></div>
|
||||
<div class="attack-container">
|
||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||
<!-- using attack-form class on your form will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
||||
<!-- 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 -->
|
||||
<form class="attack-form" accept-charset="UNKNOWN" prepareData="registerJson" method="POST" name="form"
|
||||
action="/WebGoat/XXE/content-type" contentType="application/json">
|
||||
<script th:src="@{/plugin_lessons/plugin/XXE/js/xxe.js}"
|
||||
language="JavaScript"></script>
|
||||
<div id="lessonContent">
|
||||
<strong>Registration form</strong>
|
||||
<form prepareData="registerJson" accept-charset="UNKNOWN" method="POST" name="form" action="#attack/307/100">
|
||||
<table>
|
||||
<tr>
|
||||
<td>Username</td>
|
||||
<td><input name="username" value="" type="TEXT"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>E-mail</td>
|
||||
<td><input name="email" value="" type="TEXT"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password</td>
|
||||
<td><input name="email" value="" type="TEXT"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td align="right"><input type="submit" value="Sign up"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
<br/>
|
||||
</form>
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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:XXE_mitigation.adoc"></div>
|
||||
</div>
|
||||
|
||||
|
||||
</html>
|
@ -1,15 +0,0 @@
|
||||
webgoat.customjs.register = function () {
|
||||
var xml = '<?xml version="1.0"?>' +
|
||||
'<user>' +
|
||||
' <username>' + 'test' + '</username>' +
|
||||
' <password>' + 'test' + '</password>' +
|
||||
'</user>';
|
||||
return xml;
|
||||
}
|
||||
webgoat.customjs.registerJson = function () {
|
||||
var json = '{' +
|
||||
' "user":' + '"test"' +
|
||||
' "password":' + '"test"' +
|
||||
'}';
|
||||
return json;
|
||||
}
|
@ -1 +0,0 @@
|
||||
WebGoat 8 rocks...
|
Reference in New Issue
Block a user