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:
@ -0,0 +1,30 @@
|
||||
= Spoofing an Authentication Cookie
|
||||
|
||||
Bypass the authentication mechanism by spoofing an authentication cookie.
|
||||
|
||||
*Notes about the login system*
|
||||
|
||||
When an authentication cookie is sent, the system will log in the user directly if the cookie is valid.
|
||||
|
||||
When a cookie is not sent, but credentials provided are correct, the system will create an authentication cookie.
|
||||
|
||||
The login will be denied on any other cases.
|
||||
|
||||
Pay attention to the feedback message that you will get during the attacks.
|
||||
|
||||
Known credentials:
|
||||
|
||||
[frame=ends]
|
||||
|===
|
||||
|user name |password
|
||||
|
||||
|webgoat
|
||||
|webgoat
|
||||
|
||||
|admin
|
||||
|admin
|
||||
|===
|
||||
|
||||
*Goal*
|
||||
|
||||
When you understand how the authentication cookie is generated, try to _spoof_ the cookie and login as Tom.
|
@ -0,0 +1,18 @@
|
||||
= Spoofing an Authentication Cookie
|
||||
|
||||
== Concept
|
||||
|
||||
Authentication Cookies are used for services that require authentication, when the user logs in with a personal user name and password, the server validates the provided credentials and if those are valid, it creates a session.
|
||||
|
||||
Every session usually has a unique ID that identifies the user's session; when the server returns the response to the user, it includes a Set-Cookie header that contains, among other things, the cookie name and value.
|
||||
|
||||
The authentication cookie is typically stored on the client and server side.
|
||||
|
||||
On the one hand, having the cookie stored on the client side implies that can be stolen by exploiting certain vulnerabilities or intercepted using man in the middle attacks or XSS. On the other, cookie values can be guessed if the algorithm for generating the cookie can be obtained.
|
||||
|
||||
Many applications will automatically login a user if the right authentication cookie is provided.
|
||||
|
||||
|
||||
== Goals
|
||||
|
||||
The user should be able to guess the cookie generation algorithm and bypass the authentication mechanism by logging in as a different user.
|
32
src/main/resources/lessons/spoofcookie/html/SpoofCookie.html
Normal file
32
src/main/resources/lessons/spoofcookie/html/SpoofCookie.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="http://code.jquery.com/ui/1.9.1/themes/base/jquery-ui.css" />
|
||||
|
||||
<script language="JavaScript" th:src="@{/lesson_js/handler.js}"></script>
|
||||
|
||||
<!-- 1 -->
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lessons/spoofcookie/documentation/SpoofCookie_plan.adoc"></div>
|
||||
</div>
|
||||
|
||||
<!-- 2 -->
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lessons/spoofcookie/documentation/SpoofCookie_content0.adoc"></div>
|
||||
<div class="attack-container">
|
||||
<div class="assignment-success">
|
||||
<i class="fa fa-2 fa-check hidden" aria-hidden="true"></i>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div th:include="/lessons/spoofcookie/templates/spoofcookieform.html" id="content"></div>
|
||||
</div>
|
||||
|
||||
<div class="attack-feedback" id="spoof_attack_feedback"></div>
|
||||
<div class="attack-output" id="spoof_attack_output"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</html>
|
@ -0,0 +1,7 @@
|
||||
spoofcookie.title=Spoofing an Authentication Cookie
|
||||
|
||||
spoofcookie.wrong-login=Login failed.
|
||||
spoofcookie.login=Logged in using credentials. Cookie created, see below.
|
||||
spoofcookie.cookie-login=Logged in using cookie.
|
||||
spoofcookie.wrong-cookie=Wrong cookie sent.
|
||||
spoofcookie.cheating=Don't cheat!
|
31
src/main/resources/lessons/spoofcookie/js/handler.js
Normal file
31
src/main/resources/lessons/spoofcookie/js/handler.js
Normal file
@ -0,0 +1,31 @@
|
||||
function getCookieValue() {
|
||||
var cookie = document.cookie.match(new RegExp('(^| )spoof_auth=([^;]+)'));
|
||||
if (cookie != null)
|
||||
return [2];
|
||||
return null;
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
document.cookie = 'spoof_auth=;Max-Age=0;secure=true';
|
||||
$('#spoof_username').removeAttr('disabled');
|
||||
$('#spoof_password').removeAttr('disabled');
|
||||
$('#spoof_submit').removeAttr('disabled');
|
||||
$('#spoof_attack_feedback').html('');
|
||||
$('#spoof_attack_output').html('');
|
||||
}
|
||||
|
||||
var target = document.getElementById('spoof_attack_feedback');
|
||||
|
||||
var obs = new MutationObserver(function(mutations) {
|
||||
mutations.forEach(function() {
|
||||
var cookie = getCookieValue();
|
||||
if (cookie) {
|
||||
$('#spoof_username').prop('disabled', true);
|
||||
$('#spoof_password').prop('disabled', true);
|
||||
$('#spoof_submit').prop('disabled', true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
obs.observe(target, { characterData: false, attributes: false, childList: true, subtree: false });
|
||||
|
@ -0,0 +1,88 @@
|
||||
= Spoofing an Authentication Cookie
|
||||
|
||||
== Solution
|
||||
|
||||
Some standard Linux tools have been used on this solution; other kind of tools -like online tools- can be used and the same results should be obtained.
|
||||
|
||||
=== Analysis and reversing
|
||||
|
||||
Inspect the webgoat user spoof_auth cookie value:
|
||||
|
||||
[source, text]
|
||||
----
|
||||
NjM3OTRhNGY0ODRiNTQ0OTU3NDU3NDYxNmY2NzYyNjU3Nw==
|
||||
----
|
||||
|
||||
It look like a base64 encoded text.
|
||||
|
||||
Decoding the base64 text:
|
||||
|
||||
[source, sh]
|
||||
----
|
||||
echo NjM3OTRhNGY0ODRiNTQ0OTU3NDU3NDYxNmY2NzYyNjU3Nw== | base64 -d
|
||||
63794a4f484b5449574574616f67626577
|
||||
----
|
||||
|
||||
Now, it look like a hexadecimal encoded text.
|
||||
|
||||
Hexadecimal text decoding:
|
||||
|
||||
[source, sh]
|
||||
----
|
||||
echo 63794a4f484b5449574574616f67626577 | xxd -p -r
|
||||
cyJOHKTIWEtaogbew
|
||||
----
|
||||
|
||||
Now, reverse the text:
|
||||
|
||||
[source, text]
|
||||
----
|
||||
webgoatEWITKHOJyc
|
||||
----
|
||||
|
||||
We can see the user name with some random text appended. If we request some more different cookies for the same user, we will observe that the cookie generation appends random text of ten characters together with the user name, after it reverses the whole string and encodes it as hexadecimal and base64 respectively.
|
||||
|
||||
=== Attacking the system
|
||||
|
||||
Let's see how to forge our authentication cookie for tom.
|
||||
|
||||
Our initial string will be the user name and a random text of ten characters.
|
||||
|
||||
[source,text]
|
||||
----
|
||||
tomAAAAAAAAAA
|
||||
----
|
||||
|
||||
Reverse it:
|
||||
|
||||
[source, text]
|
||||
----
|
||||
AAAAAAAAAAmot
|
||||
----
|
||||
|
||||
Now, encode the text to hexadecimal:
|
||||
|
||||
[source,text]
|
||||
----
|
||||
# warn: do not encode any whitespace or new line character
|
||||
echo -n AAAAAAAAAAmot | xxd -ps
|
||||
414141414141414141416d6f74
|
||||
----
|
||||
|
||||
Encode to base64:
|
||||
|
||||
[source,text]
|
||||
----
|
||||
# warn: do not encode any whitespace or new line character
|
||||
echo -n 414141414141414141416d6f74 | base64
|
||||
NDE0MTQxNDE0MTQxNDE0MTQxNDE2ZDZmNzQ=
|
||||
----
|
||||
|
||||
The spoof_auth cookie value is:
|
||||
|
||||
[source,text]
|
||||
----
|
||||
NDE0MTQxNDE0MTQxNDE0MTQxNDE2ZDZmNzQ=
|
||||
----
|
||||
|
||||
Finally, send the cookie to the system using any method that you prefer; OWASP ZAP, curl, the browser developer tools, etc.
|
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this block for each 'page' of content -->
|
||||
<!-- include content here ... will be first page/tab multiple -->
|
||||
<div class="adoc-content" th:replace="doc:SpoofCookie_solution.adoc"></div>
|
||||
</div>
|
||||
|
||||
|
||||
</html>
|
@ -0,0 +1,30 @@
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<form class="attack-form" accept-charset="UNKNOWN" method="POST"
|
||||
action="/WebGoat/SpoofCookie/login">
|
||||
<div style="padding: 20px;" id="password-login">
|
||||
<h4 style="border-bottom: 1px solid #c5c5c5;">Account Access</h4>
|
||||
<fieldset>
|
||||
<div class="form-group input-group">
|
||||
<span class="input-group-addon"> <i
|
||||
class="glyphicon glyphicon-user"></i>
|
||||
</span> <input class="form-control" placeholder="User name"
|
||||
name="username" type="text" id="spoof_username"></input>
|
||||
</div>
|
||||
<div class="form-group input-group">
|
||||
<span class="input-group-addon"><i
|
||||
class="glyphicon glyphicon-lock"></i></span> <input class="form-control"
|
||||
placeholder="Password" name="password" type="password"
|
||||
id="spoof_password" />
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-block"
|
||||
id="spoof_submit">Access</button>
|
||||
<div style="padding-top: 10px">
|
||||
<a id="cleanup" href="#" onclick="cleanup();return false;">Delete
|
||||
cookie</a>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
Reference in New Issue
Block a user