Refactoring (#1201)
* Some initial refactoring * Make it one application * Got it working * Fix problem on Windows * Move WebWolf * Move first lesson * Moved all lessons * Fix pom.xml * Fix tests * Add option to initialize a lesson This way we can create content for each user inside a lesson. The initialize method will be called when a new user is created or when a lesson reset happens * Clean up pom.xml files * Remove fetching labels based on language. We only support English at the moment, all the lesson explanations are written in English which makes it very difficult to translate. If we only had labels it would make sense to support multiple languages * Fix SonarLint issues * And move it all to the main project * Fix for documentation paths * Fix pom warnings * Remove PMD as it does not work * Update release notes about refactoring Update release notes about refactoring Update release notes about refactoring * Fix lesson template * Update release notes * Keep it in the same repo in Dockerhub * Update documentation to show how the connection is obtained. Resolves: #1180 * Rename all integration tests * Remove command from Dockerfile * Simplify GitHub actions Currently, we use a separate actions for pull-requests and branch build. This is now consolidated in one action. The PR action triggers always, it now only trigger when the PR is opened and not in draft. Running all platforms on a branch build is a bit too much, it is better to only run all platforms when someone opens a PR. * Remove duplicate entry from release notes * Add explicit registry for base image * Lesson scanner not working when fat jar When running the fat jar we have to take into account we are reading from the jar file and not the filesystem. In this case you cannot use `getFile` for example. * added info in README and fixed release docker * changed base image and added ignore file Co-authored-by: Zubcevic.com <rene@zubcevic.com>
This commit is contained in:
75
src/main/resources/lessons/csrf/css/reviews.css
Normal file
75
src/main/resources/lessons/csrf/css/reviews.css
Normal file
@ -0,0 +1,75 @@
|
||||
/* Component: Posts */
|
||||
.post .post-heading {
|
||||
height: 95px;
|
||||
padding: 20px 15px;
|
||||
}
|
||||
.post .post-heading .avatar {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
display: block;
|
||||
margin-right: 15px;
|
||||
}
|
||||
.post .post-heading .meta .title {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.post .post-heading .meta .title a {
|
||||
color: black;
|
||||
}
|
||||
.post .post-heading .meta .title a:hover {
|
||||
color: #aaaaaa;
|
||||
}
|
||||
.post .post-heading .meta .time {
|
||||
margin-top: 8px;
|
||||
color: #999;
|
||||
}
|
||||
.post .post-image .image {
|
||||
width:20%;
|
||||
height: 40%;
|
||||
}
|
||||
.post .post-description {
|
||||
padding: 5px;
|
||||
}
|
||||
.post .post-footer {
|
||||
border-top: 1px solid #ddd;
|
||||
padding: 15px;
|
||||
}
|
||||
.post .post-footer .input-group-addon a {
|
||||
color: #454545;
|
||||
}
|
||||
.post .post-footer .comments-list {
|
||||
padding: 0;
|
||||
margin-top: 20px;
|
||||
list-style-type: none;
|
||||
}
|
||||
.post .post-footer .comments-list .comment {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.post .post-footer .comments-list .comment .avatar {
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
}
|
||||
.post .post-footer .comments-list .comment .comment-heading {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
.post .post-footer .comments-list .comment .comment-heading .user {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
display: inline;
|
||||
margin-top: 0;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.post .post-footer .comments-list .comment .comment-heading .time {
|
||||
font-size: 12px;
|
||||
color: #aaa;
|
||||
margin-top: 0;
|
||||
display: inline;
|
||||
}
|
||||
.post .post-footer .comments-list .comment .comment-body {
|
||||
margin-left: 50px;
|
||||
}
|
||||
.post .post-footer .comments-list .comment > .comments-list {
|
||||
margin-left: 50px;
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
== Confirm Flag
|
||||
|
||||
Confirm the flag you should have gotten on the previous page below.
|
@ -0,0 +1,23 @@
|
||||
== CSRF and content-type
|
||||
|
||||
In the previous section we saw how relying on the content-type is not a protection against
|
||||
CSRF. In this section we will look into another way we can perform a CSRF attack against
|
||||
a APIs which are not protected against CSRF.
|
||||
|
||||
In this assignment you need to achieve to POST the following JSON message to our endpoints:
|
||||
|
||||
[source]
|
||||
----
|
||||
POST /csrf/feedback/message HTTP/1.1
|
||||
|
||||
{
|
||||
"name" : "WebGoat",
|
||||
"email" : "webgoat@webgoat.org",
|
||||
"content" : "WebGoat is the best!!"
|
||||
}
|
||||
----
|
||||
|
||||
More information can be found http://pentestmonkey.net/blog/csrf-xml-post-request[here]
|
||||
|
||||
Remember you need to make the call from another origin (WebWolf can help here) and you need to be logged in into
|
||||
WebGoat.
|
@ -0,0 +1,27 @@
|
||||
=== Automatic support from frameworks
|
||||
|
||||
Most frameworks now have default support for preventing CSRF. For example with Angular an interceptor reads a token
|
||||
from a cookie by default XSRF-TOKEN and sets it as an HTTP header, X-XSRF-TOKEN. Since only code that runs on your domain
|
||||
could read the cookie, the backend can be certain that the HTTP request came from your client application and not an attacker.
|
||||
|
||||
In order for this to work the backend server sets the token in a cookie. As the value of the cookie should be read
|
||||
by Angular (JavaScript) this cookie should not be marked with the http-only flag. On every request towards the server
|
||||
Angular will put the token in the X-XSRF-TOKEN as a HTTP header. The server can validate whether those two tokens
|
||||
match and this will ensure the server the request is running on the same domain.
|
||||
|
||||
*Important: DEFINE A SEPARATE COOKIE, DO NOT REUSE THE SESSION COOKIE*
|
||||
|
||||
Remember the session cookie should always be defined with http-only flag.
|
||||
|
||||
== Custom headers not safe
|
||||
|
||||
Another defense can be to add a custom request header to each call. This will work if all the interactions
|
||||
with the server are performed with JavaScript. On the server side you only need to check the presence of this header
|
||||
if this header is not present deny the request.
|
||||
Some frameworks offer this implementation by default however researcer Alex Infuhr found out that this can be bypassed
|
||||
as well. You can read about: https://insert-script.blogspot.com/2018/05/adobe-reader-pdf-client-side-request.html[Adobe Reader PDF - Client Side Request Injection]
|
||||
|
||||
|
||||
|
||||
|
||||
|
10
src/main/resources/lessons/csrf/documentation/CSRF_GET.adoc
Normal file
10
src/main/resources/lessons/csrf/documentation/CSRF_GET.adoc
Normal file
@ -0,0 +1,10 @@
|
||||
== CSRF with a GET request
|
||||
|
||||
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>`
|
||||
|
||||
If the user is still logged in to the website of bank.com this simple GET request will transfer money from one account to another.
|
||||
Of course in most cases the website might have multiple controls to approve the request.
|
||||
|
||||
|
@ -0,0 +1,4 @@
|
||||
== Basic Get CSRF Exercise
|
||||
|
||||
Trigger the form below from an external source while logged in. The response will include a 'flag' (a numeric value).
|
||||
|
@ -0,0 +1,33 @@
|
||||
== CSRF Impact
|
||||
|
||||
The impact is limited only by what the logged in user can do (if the site/function/action is not protected properly).
|
||||
The areas that are really prone to CSRF attacks are IoT devices and 'smart' appliances. Sadly, many consumer-grade routers
|
||||
have also proven vulnerable to CSRF.
|
||||
|
||||
== CSRF solutions
|
||||
|
||||
=== Same site cookie attribute
|
||||
|
||||
This is a new extension which modern browsers support which limits the scope of the cookie such that it will only be
|
||||
attached to requests if those requests are 'same-site'
|
||||
For example requests for `http://webgoat.org/something` will attach same-site cookies if the request is initiated from
|
||||
`webgoat.org`.
|
||||
There are two modes, strict and lax. The first one does not allow cross site request, this means when you are on
|
||||
github.com and you want to like it through Facebook (and Facebook specifies same-site as strict) you will be
|
||||
redirected to the login page, because the browser does not attach the cookie for Facebook.
|
||||
More information can be found here: https://www.sjoerdlangkemper.nl/2016/04/14/preventing-csrf-with-samesite-cookie-attribute/
|
||||
|
||||
=== Other protections
|
||||
|
||||
Fortunately, many (web) application frameworks now come with built in support to handle CSRF attacks. For example, Spring and
|
||||
Tomcat have this on by default. As long as you don't turn it off (like it is in WebGoat), you should be safe from CSRF attacks.
|
||||
|
||||
See the following for more information on CSRF protections:
|
||||
|
||||
https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html (Prevention/Defense)
|
||||
|
||||
https://owasp.org/www-community/attacks/csrf (Attack)
|
||||
|
||||
https://tomcat.apache.org/tomcat-7.0-doc/config/filter.html#CSRF_Prevention_Filter / https://tomcat.apache.org/tomcat-8.0-doc/config/filter.html#CSRF_Prevention_Filter (Tomcat)
|
||||
|
||||
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#csrf
|
46
src/main/resources/lessons/csrf/documentation/CSRF_JSON.adoc
Normal file
46
src/main/resources/lessons/csrf/documentation/CSRF_JSON.adoc
Normal file
@ -0,0 +1,46 @@
|
||||
**But I only have JSON APIs and no CORS enabled, how can those be susceptible to CSRF?**
|
||||
|
||||
A lot of web applications implement no protection against CSRF they are somehow protected by the fact that
|
||||
they only work with `application/json` as content type. The only way to make a request with this content-type from the
|
||||
browser is with a XHR request. Before the browser can make such a request a preflight request will be made towards
|
||||
the server (remember the CSRF request will be cross origin). If the pre-flight response does not allow the cross origin
|
||||
request the browser will not make the call.
|
||||
|
||||
To make a long answer short: this is *not* a valid protection against CSRF.
|
||||
|
||||
One example why this protection is not enough can be found https://bugs.chromium.org/p/chromium/issues/detail?id=490015[here].
|
||||
Turns out `Navigator.sendBeacon()` was allowed to send POST request with an arbitrary content-type.
|
||||
|
||||
[quote, 'developer.mozilla.org']
|
||||
____
|
||||
The navigator.sendBeacon() method can be used to asynchronously transfer a small amount of
|
||||
data over HTTP to a web server. This method addresses the needs of analytics and diagnostics
|
||||
code that typically attempts to send data to a web server prior to the unloading of the
|
||||
document. Sending the data any sooner may result in a missed opportunity to gather data...
|
||||
____
|
||||
|
||||
{nbsp} +
|
||||
For example:
|
||||
|
||||
[source]
|
||||
--
|
||||
function postBeacon() {
|
||||
var data= new Blob([JSON.stringify({"author" :"WebGoat"})], {type : 'application/json'});
|
||||
navigator.sendBeacon("http://localhost:8083", data)
|
||||
}
|
||||
--
|
||||
|
||||
[quote, 'Eduardo Vela']
|
||||
____
|
||||
I think Content-Type restrictions are useful for websites that are accidentally safe against CSRF. They are not meant to be, but they are because they happen to only accept XML or JSON payloads.
|
||||
|
||||
That said, it's somewhat obvious the websites depending on this behavior should be fixed, and any reputable pentesters will point that out. The issue is whether it's the browser responsibility to act as a nanny to weak websites, or we should leave weak websites as sacrifice for great justice. Survival of the fittest.
|
||||
|
||||
IMHO, the answer is somewhere in between, and a good first step would be to document all these Same Origin Policy gotchas that websites might depend upon for security.
|
||||
|
||||
But wrt to this bug in specific, if it never got fixed, I don't think it would be the end of the world. But then again, on this day and age, maybe there's a way to launch nuclear missiles with a XML RPC interface, so maybe it would be the end of the world.
|
||||
____
|
||||
|
||||
{nbsp} +
|
||||
Both Firefox and Chrome fixed this issue, but it shows why you should implement a CSRF protection instead
|
||||
of relying on the content-type of your APIs.
|
@ -0,0 +1,26 @@
|
||||
:blank: pass:[ +]
|
||||
|
||||
== Login CSRF attack
|
||||
|
||||
In a login CSRF attack, the attacker forges a login request to an honest site using the attacker’s username
|
||||
and password at that site. If the forgery succeeds, the honest server responds with a `Set-Cookie` header
|
||||
that instructs the browser to mutate its state by storing a session cookie, logging the user into
|
||||
the honest site as the attacker. This session cookie is used to bind subsequent requests to the user's session and hence
|
||||
to the attacker's authentication credentials. Login CSRF attacks can have serious consequences, for example
|
||||
see the picture below where an attacker created an account at google.com the victim visits the malicious
|
||||
website and the user is logged in as the attacker. The attacker could then later on gather information about
|
||||
the activities of the user.
|
||||
|
||||
{blank}
|
||||
|
||||
image::images/login-csrf.png[caption="Figure: ", title="Login CSRF from Robust Defenses for Cross-Site Request Forgery", width="800", height="500", style="lesson-image" link="http://seclab.stanford.edu/websec/csrf/csrf.pdf"]
|
||||
|
||||
{blank}
|
||||
For more information read the following http://seclab.stanford.edu/websec/csrf/csrf.pdf[paper].
|
||||
|
||||
In this assignment try to see if WebGoat is also vulnerable for a login CSRF attack.
|
||||
Leave this tab open and in another tab create a user based on your own username prefixed with `csrf-`.
|
||||
So if your username is `tom` you must create a new user called `csrf-tom`.
|
||||
|
||||
Login as the new user. This is what an attacker would do using CSRF. Then click the button in the original tab.
|
||||
Because you are logged in as a different user, the attacker learns that you clicked the button.
|
@ -0,0 +1,9 @@
|
||||
== Post a review on someone else's behalf
|
||||
|
||||
The page below simulates a comment/review page. The difference here is that you have to initiate the submission elsewhere as you might
|
||||
with a CSRF attack and like the previous exercise. It's easier than you think. In most cases, the trickier part is
|
||||
finding somewhere that you want to execute the CSRF attack. The classic example is account/wire transfers in someone's bank account.
|
||||
|
||||
But we're keeping it simple here. In this case, you just need to trigger a review submission on behalf of the currently
|
||||
logged in user.
|
||||
|
@ -0,0 +1,27 @@
|
||||
=== 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:
|
||||
|
||||
* It involves sites that rely on a user's identity.
|
||||
* It exploits the site's trust in that identity.
|
||||
* It tricks the user's browser into sending HTTP requests to a target site.
|
||||
* It involves HTTP requests that have side effects.
|
||||
|
||||
At risk are web applications that perform actions based on input from trusted and authenticated users without requiring the user to authorize
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
Let's continue with some exercises to address way to perform a CSRF request.
|
||||
|
||||
|
||||
|
||||
|
260
src/main/resources/lessons/csrf/html/CSRF.html
Normal file
260
src/main/resources/lessons/csrf/html/CSRF.html
Normal file
@ -0,0 +1,260 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lessons/csrf/documentation/CSRF_intro.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lessons/csrf/documentation/CSRF_GET.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lessons/csrf/documentation/CSRF_Get_Flag.adoc"></div>
|
||||
|
||||
<form accept-charset="UNKNOWN" id="basic-csrf-get"
|
||||
method="POST" name="form1"
|
||||
target="_blank"
|
||||
successCallback=""
|
||||
action="/WebGoat/csrf/basic-get-flag">
|
||||
<input name="csrf" type="hidden" value="false"/>
|
||||
<input type="submit" name="submit"/>
|
||||
|
||||
</form>
|
||||
|
||||
<div class="adoc-content" th:replace="doc:lessons/csrf/documentation/CSRF_Basic_Get-1.adoc"></div>
|
||||
|
||||
<div class="attack-container">
|
||||
<img th:src="@{/images/wolf-enabled.png}" class="webwolf-enabled"/>
|
||||
<div class="assignment-success">
|
||||
<i class="fa fa-2 fa-check hidden" aria-hidden="true">
|
||||
</i>
|
||||
</div>
|
||||
<br/>
|
||||
<form class="attack-form" accept-charset="UNKNOWN" id="confirm-flag-1"
|
||||
method="POST" name="form2"
|
||||
successCallback=""
|
||||
action="/WebGoat/csrf/confirm-flag-1">
|
||||
|
||||
Confirm Flag Value:
|
||||
<input type="text" length="6" name="confirmFlagVal" value=""/>
|
||||
|
||||
<input name="submit" value="Submit" type="submit"/>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
</form>
|
||||
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
|
||||
<div class="adoc-content" th:replace="doc:lessons/csrf/documentation/CSRF_Reviews.adoc"></div>
|
||||
|
||||
<!-- comment area -->
|
||||
<link rel="stylesheet" type="text/css" th:href="@{/lesson_css/reviews.css}"/>
|
||||
<script th:src="@{/lesson_js/csrf-review.js}" language="JavaScript"></script>
|
||||
|
||||
<div class="attack-container">
|
||||
<img th:src="@{/images/wolf-enabled.png}" class="webwolf-enabled"/>
|
||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||
<div class="container-fluid">
|
||||
<div class="panel post">
|
||||
<div class="post-heading">
|
||||
<div class="pull-left image">
|
||||
<img th:src="@{/images/avatar1.png}"
|
||||
class="img-circle avatar" alt="user profile image"/>
|
||||
</div>
|
||||
<div class="pull-left meta">
|
||||
<div class="title h5">
|
||||
<a href="#"><b>John Doe</b></a>
|
||||
is selling this poster, read reviews below.
|
||||
</div>
|
||||
<h6 class="text-muted time">24 days ago</h6>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="post-image">
|
||||
<img th:src="@{images/cat.jpg}" class="image" alt="image post"/>
|
||||
</div>
|
||||
|
||||
<div class="post-description">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="attack-container">
|
||||
<div class="post-footer">
|
||||
<div class="input-group">
|
||||
<form class="attack-form" accept-charset="UNKNOWN" id="csrf-review"
|
||||
method="POST" name="review-form"
|
||||
successCallback=""
|
||||
action="/WebGoat/csrf/review">
|
||||
<input class="form-control" id="reviewText" name="reviewText" placeholder="Add a Review"
|
||||
type="text"/>
|
||||
<input class="form-control" id="reviewStars" name="stars" type="text"/>
|
||||
<input type="hidden" name="validateReq" value="2aa14227b9a13d0bede0388a7fba9aa9"/>
|
||||
<input type="submit" name="submit" value="Submit review"/>
|
||||
</form>
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
<!--<span class="input-group-addon">-->
|
||||
<!--<i id="postReview" class="fa fa-edit" style="font-size: 20px"></i>-->
|
||||
<!--</span>-->
|
||||
</div>
|
||||
<ul class="comments-list">
|
||||
<div id="list">
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end comments -->
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lessons/csrf/documentation/CSRF_Frameworks.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lessons/csrf/documentation/CSRF_JSON.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lessons/csrf/documentation/CSRF_ContentType.adoc"></div>
|
||||
|
||||
<script th:src="@{/lesson_js/feedback.js}" language="JavaScript"></script>
|
||||
<div style="container-fluid; background-color: #f1f1f1; border: 2px solid #a66;
|
||||
border-radius: 12px;
|
||||
padding: 7px;
|
||||
margin-top:7px;
|
||||
padding:5px;">
|
||||
<div class="example-container">
|
||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="well well-sm">
|
||||
<form class="attack-form" accept-charset="UNKNOWN" id="csrf-feedback"
|
||||
method="POST"
|
||||
prepareData="feedback"
|
||||
action="/WebGoat/csrf/feedback/message"
|
||||
contentType="application/json">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="name">
|
||||
Name</label>
|
||||
<input type="text" class="form-control" name="name" id="name"
|
||||
placeholder="Enter name"
|
||||
required="required"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">
|
||||
Email Address</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><span class="glyphicon glyphicon-envelope"></span>
|
||||
</span>
|
||||
<input type="email" name="email" class="form-control" id="email"
|
||||
placeholder="Enter email"
|
||||
required="required"/></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="subject">
|
||||
Subject</label>
|
||||
<select id="subject" name="subject" class="form-control"
|
||||
required="required">
|
||||
<option value="na" selected="">Choose One:</option>
|
||||
<option value="service">General Customer Service</option>
|
||||
<option value="suggestions">Suggestions</option>
|
||||
<option value="product">Product Support</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="name">
|
||||
Message</label>
|
||||
<textarea name="message" id="message" class="form-control" rows="9"
|
||||
cols="25"
|
||||
required="required"
|
||||
placeholder="Message"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<button class="btn btn-primary pull-right" id="btnContactUs">
|
||||
Send Message
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
</div>
|
||||
</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-feedback"
|
||||
method="POST" name="form2"
|
||||
action="/WebGoat/csrf/feedback">
|
||||
|
||||
Confirm Flag Value:
|
||||
<input type="text" length="6" name="confirmFlagVal" value=""/>
|
||||
|
||||
<input name="submit" value="Submit" type="submit"/>
|
||||
|
||||
</form>
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lessons/csrf/documentation/CSRF_Login.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-login"
|
||||
method="POST" name="form2"
|
||||
action="/WebGoat/csrf/login">
|
||||
|
||||
Press the button below when your are logged in as the other user<br/>
|
||||
|
||||
<input name="submit" value="Solved!" type="submit"/>
|
||||
|
||||
</form>
|
||||
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lessons/csrf/documentation/CSRF_Impact_Defense.adoc"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<!--</div>-->
|
||||
|
||||
</html>
|
@ -0,0 +1,32 @@
|
||||
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.success=Congratulations! Appears you made the request from a separate host.
|
||||
|
||||
|
||||
csrf-get.hint1=The form has hidden inputs.
|
||||
csrf-get.hint2=You will need to use an external page and/or script to trigger it.
|
||||
csrf-get.hint3=Try creating a local page or one that is uploaded and points to this form as its action.
|
||||
csrf-get.hint4=The trigger can be manual or scripted to happen automatically
|
||||
|
||||
csrf-same-host=It appears your request is coming from the same host you are submitting to.
|
||||
|
||||
csrf-you-forgot-something=There's something missing from your request it appears, so I can't process it.
|
||||
|
||||
csrf-review.success=It appears you have submitted correctly from another site. Go reload and see if your post is there.
|
||||
|
||||
csrf-review-hint1=Again, you will need to submit from an external domain/host to trigger this action. While CSRF can often be triggered from the same host (e.g. via persisted payload), this doesn't work that way.
|
||||
csrf-review-hint2=Remember, you need to mimic the existing workflow/form.
|
||||
csrf-review-hint3=This one has a weak anti-CSRF protection, but you do need to overcome (mimic) it
|
||||
|
||||
csrf-feedback-hint1=Look at the content-type.
|
||||
csrf-feedback-hint2=Try to post the same message with content-type text/plain
|
||||
csrf-feedback-hint3=The json can be put into a hidden field inside
|
||||
|
||||
csrf-feedback-invalid-json=Invalid JSON received.
|
||||
csrf-feedback-success=Congratulations you have found the correct solution, the flag is: {0}
|
||||
|
||||
csrf-login-hint1=First create a new account with csrf-username
|
||||
csrf-login-hint2=Create a form which will log you in as this user (hint 1) and upload it to WebWolf
|
||||
csrf-login-hint3=Visit this assignment again
|
||||
csrf-login-success=Congratulations, now log out and login with your normal user account within WebGoat, remember the attacker knows you solved this assignment
|
||||
csrf-login-failed=The solution is not correct, you are clicking the button while logged in as {0}
|
BIN
src/main/resources/lessons/csrf/images/login-csrf.png
Normal file
BIN
src/main/resources/lessons/csrf/images/login-csrf.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 212 KiB |
46
src/main/resources/lessons/csrf/js/csrf-review.js
Normal file
46
src/main/resources/lessons/csrf/js/csrf-review.js
Normal file
@ -0,0 +1,46 @@
|
||||
$(document).ready(function () {
|
||||
// $("#postReview").on("click", function () {
|
||||
// var commentInput = $("#reviewInput").val();
|
||||
// $.ajax({
|
||||
// type: 'POST',
|
||||
// url: 'csrf/review',
|
||||
// data: JSON.stringify({text: commentInput}),
|
||||
// contentType: "application/json",
|
||||
// dataType: 'json'
|
||||
// }).then(
|
||||
// function () {
|
||||
// getChallenges();
|
||||
// $("#commentInput").val('');
|
||||
// }
|
||||
// )
|
||||
// });
|
||||
|
||||
var html = '<li class="comment">' +
|
||||
'<div class="pull-left">' +
|
||||
'<img class="avatar" src="images/avatar1.png" alt="avatar"/>' +
|
||||
'</div>' +
|
||||
'<div class="comment-body">' +
|
||||
'<div class="comment-heading">' +
|
||||
'<h4 class="user">USER / STARS stars</h4>' +
|
||||
'<h5 class="time">DATETIME</h5>' +
|
||||
'</div>' +
|
||||
'<p>COMMENT</p>' +
|
||||
'</div>' +
|
||||
'</li>';
|
||||
|
||||
getChallenges();
|
||||
|
||||
function getChallenges() {
|
||||
$("#list").empty();
|
||||
$.get('csrf/review', function (result, status) {
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var comment = html.replace('USER', result[i].user);
|
||||
comment = comment.replace('DATETIME', result[i].dateTime);
|
||||
comment = comment.replace('COMMENT', result[i].text);
|
||||
comment = comment.replace('STARS', result[i].stars)
|
||||
$("#list").append(comment);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
})
|
7
src/main/resources/lessons/csrf/js/feedback.js
Normal file
7
src/main/resources/lessons/csrf/js/feedback.js
Normal file
@ -0,0 +1,7 @@
|
||||
webgoat.customjs.feedback = function() {
|
||||
var data = {};
|
||||
$('#csrf-feedback').find('input, textarea, select').each(function(i, field) {
|
||||
data[field.name] = field.value;
|
||||
});
|
||||
return JSON.stringify(data);
|
||||
}
|
Reference in New Issue
Block a user