DVWA Stored XSS Exploit

Dvwa Stored XSS exploit

In my previous article on DVWA, I have demonstrated how to exploit reflected XSS vulnerability at low, medium, and high security in the DVWA web app and we have also reviewed the PHP code which was running on the server. In this article, I will show you how to exploit Stored XSS vulnerability in the same web application at low, medium and high security simultaneously by reviewing their source code. This article is written from a very beginner’s point of view, keeping in mind you don’t know anything about XSS.

If you have directly reached to this article then I will suggest you to read my previous post on DVWA reflected XSS where I have introduced about XSS vulnerability, why it arises, and the types of XSS vulnerability. Before we begin to exploit this vulnerability in the DVWA web application, let us know about Stored XSS vulnerability in detail.

What is Stored XSS vulnerability?

Unlike Reflected XSS, Stored XSS is the most dangerous cross-site scripting vulnerability. This type of vulnerability arises whenever a web application stores user-supplied data for later use in the backend without performing any filter or input sanitization. Since the web application does not apply any filter therefore an attacker can inject some malicious code into this input field. This malicious code can also be a valid XSS payload. So whenever any person visits the vulnerable page where malicious code is injected he will get a popup on his browser window. This will prove that the given webpage is vulnerable to Stored XSS vulnerability.

Let us understand it with an example. Suppose you are reading an article at a website https://xyz.com/article.php and there is a comment section at the bottom of the post to share your experience or to ask your doubt. So, whenever you will enter your comment, that comment will be publicly available. Further, if any other user visits the same page i.e., https://xyz.com/article.php he can see the comment at the bottom of the page. This is a normal condition.

But let us think from a hacker’s point of view. What if instead of a valid comment an attacker enters some XSS payload? If the website does not validate input before storing them in its database then the XSS payload will be saved for forever in the database until it is removed by the admin. In this way, the attacker’s XSS payload is injected into the comment section. If this website is vulnerable to Stored XSS vulnerability then anyone visiting this page at https://xyz.com/article.php will definitely get an XSS pop-up. In this way, this is not just affecting a single user but it is affecting all those users who are accessing the vulnerable webpage.  

Stored XSS is most commonly seen in

  1. Forum or Message Board
  2. Blog comments of any post
  3. Shopping cart of e-commerce website
  4. User Profiles Page: the application allows the user to edit/change profile details such as first name, last name, nickname, avatar, picture, address, etc.
  5. File Manager: application that allows the upload of files
  6. Application settings or preferences: an application that allows the user to set preferences
  7. Log: if the application stores some users’ input into logs.

How to Exploit Stored XSS in General

Hacking Steps

These are the general steps that have to be followed every time while testing for stored XSS on any website:

The first step is to identify all points where user input is being stored into the back-end and then displayed by the application and the remaining steps are similar to reflected XSS i.e.,

  1. Firstly, input some unique string in the input fields of the website and submit it.
  2. Open page source by right click or by pressing CTRL+U and search for the unique string in the Page Source.
  3. Use CTRL+F to find the unique string which you have entered in step one. If the unique string reflects back in the browser windows or in the page source then the site may be vulnerable to Stored XSS.
  4. At last, fire XSS payload viz. <script>alert()</script> and submit it to get a further response in the browser. If the site is vulnerable you will definitely get an alert box.

Now we have learned the basics let us exploit Stored XSS vulnerability in the DVWA web application. First of all login into your DVWA web application by default credential admin: password or something other which you have set.

Login page of DVWA web application

Low Security

We will start from low level and will proceed to high level gradually. Click on DVWA security on the left pane to change the difficulty to low

Changing the security to low in Dvwa Stored XSS exploit

Select Security Level to low and submit to submit the request. Further, click on XSS (Stored) on left pane to select the vulnerability to Stored XSS because we are going to practice Stored XSS attack.

Changing the security to low part 2

As we can see there are two fields Name and Message.

Stored XSS Low security Page

Let us input some unique string to check whether they are reflecting in the browser window or not. In my case, I have entered test1 & test2 in Name & Message field respectively. Then click on Sign Guestbook to submit the request.

Testing to Reflecting Keys at low security in Dvwa Stored XSS exploition

Soon our request is submitted, our next step is to check the page source whether our unique string is reflecting or not. On pressing CTRL+U to check page source and then searching for test string revealed that test1 and test2 both are reflecting. Since both are reflecting in the browser so both these fields may be vulnerable to Stored XSS attack.    

Checking the page source in low level security

Now our last step is to fire the XSS payload into either of these two input fields. I am using a very basic XSS payload <script>alert()</script> in Message field. Click on Sign Guestbook to submit the message. If this site is vulnerable to stored XSS vulnerability then we will get a popup when we refresh this page.

Finally entering the XSS payload to get alert box as PoC

When I refreshed this same page I got an XSS alert box. This box confirms that this site is vulnerable to stored XSS attacks.

Getting alert box in Low level and confirming the exploitation

So we have successfully exploited Stored XSS at low security. Now each time we refresh the same page we will get this alert box because our XSS payload is stored in the Guestbook. If we want to exploit this vulnerability at other security levels we have to first clear the Guestbook otherwise we will get this alert box again and again. So before proceeding further click on Clear Guestbook to delete our XSS payload from the guestbook.

Clearing the guestbook after exploiting at low level in Dvwa Stored XSS exploitation

Medium Security

Change the security level to Medium by clicking on DVWA Security and then choose XSS (Stored) on the left pane.

Changing the security to medium in DVWA Web application

We will follow the same steps as we have followed at low level security. First of all input some unique strings into Name and Message field. Then check page source whether the inputted string is reflecting or not. When I tried to find my unique string in the browser I could easily find both the strings in page source. So here these fields may be vulnerable to Stored XSS attack. Let us fire our basic XSS payload <script>alert()</script> into Message field and then click on Sign Guestbook  to submit the message.

Injecting XSS payload in medium security during Dvwa Stored XSS exploitation

Upon refreshing the page I could not get any pop up. Why we didn’t get any alert message although we entered a valid XSS payload? There may be chances that the backend code is performing some type of input sanitization or html encoding on the message field when it is accepting the user’s input. Don’t know exactly how message data is being processed in the backend. Let us look at the source code of the server page which is accepting user data.­­

Analyzing the source code to verifiy the issue

First block is for performing input sanitization on message field. This block contains two php functions for performing input sanitization.  First one is strip_tags(). It removes all html tags from the message field before storing them in database. Second function is htmlspecialchars(). It converts all the bad characters like &, ", ', > and < in their equivalent HTML character encoding so they won’t remain in their original form when they reflect back in the browser. You can confirm it by checking the page source.

So, in message field there are two levels of sanitization. Firstly strip_tags() function removes all the HTML tags from the message field and even if some text containing quotes or bad characters passes through this function, htmlspecialchars() will definitely encode them into equivalent HTML characters. So our XSS payload becomes useless. From here we conclude that the message field is completely secure and we cannot inject any XSS payload into it. This was the reason when we gave <script>alert()</script> as our input in message field it only showed alert() text in page source because strip_tags() function removed <script> and </script> tags from it.

Second block is for performing input sanitization on Name field. It uses just one function for performing input sanitization. The function is str_replace(). Here this function is replacing all the occurrences of <script> tag with null or blank character. We can use this field to inject our XSS payload. Since this field is replacing all occurrences of <script> tag so we cannot use any XSS payload which contains <script> tag in it.  

Bypass

We can bypass this security by using some other payloads which do not contain <script> tags in it and we can use script tag with different casing enabled. Like we can use <Script> or <scRiPt> or <ScRiPt> in place of <script>. So our new payload will be something like this <Script>alert(“Hacked”)</Script>. Let us inject it in Name field. So when I tried to enter this payload in Name field it does not accept all the characters of our payload because it has some client side restriction. The restriction is, that a user can enter a maximum of 10 characters in the name field. Since it is a client-side restriction so it can be bypassed very easily.

To bypass the character max length restriction simply open inspect element by clicking CTRL+SHIFT+C and take your mouse pointer to Name field and click on it. Then at the bottom of the windows in source code double click on maxlength and change it to 100 from 10. Press Enter to apply the changes and close the Inspect window.

Bypassing the client-side-length restriction in Name field part -1
Bypassing the client-side-length restriction in Name field part -2

Now our maxlength restriction has been removed let us enter our XSS payload. Inject the payload <Script>alert(“Hacked”)</Script> in the Name field and in Message field you can enter anything.

Finally injecting XSS payload in Name field to get Pop up

After entering the payload click on Sign Guestbook to inject the payload and store in the database. Now refresh the page you will get a pop up showing Hacked.

Getting Alert message on the screen which proofs stored XSS exploitation at medium security

We have got alert box which proves that we have successfully exploited this vulnerability at medium level difficulty also.

High Security

Let us exploit it at high security. But before changing the security to high level clear the guest book and then change the security to high.

Changing the security to high level in dvwa Stored XSS exploitation

We will follow the same steps as we have followed at low and medium security level. First of all input some unique strings into Name and Message field. Then check page source whether the inputted string is reflecting or not. When I tried to find my unique string in the browser I could easily find both the strings in page source. So here both the fields may be vulnerable to Stored XSS attack. Let us fire our XSS payload <Script>alert()</Script> into Message field and then click on Sign Guestbook  to submit the message.

Injecting XSS payload to test XSS vulnerability

It did not give me alert message. Let us analyze the source code of the page which is accepting our input. According to source code block 1 is accepting input of Message field and performing sanitization on it. Again this code is using strip_tags() and htmlspecialchars() functions to sanitize user input as we have seen in medium security. So there is no chance to inject XSS payload in this field because they will be filtered by these functions.

Block 2 is for performing input sanitization on Name field. It uses just one function for performing input sanitization. The function is preg_replace(). Here this function replaces every occurrences of <script> tag irrespective of their cases with null or blank. So here every XSS payload which includes <script> tag into it will be useless. 

Analyzing the source code to check the issue

Bypass

To bypass this we have to use some other XSS payload which does not contains <script> tag into it. There are many number of payloads available to bypass this. I am again using very basic one and the payload is <svg/onload=alert(“Hacked”)>. This will be injected and won’t be blocked by preg_replace() function.

So our new payload is <svg/onload=alert(“Hacked”)>. Let us inject it in Name field. So when I tried to enter this payload in Name field it does not accept all the characters because it has some client side restriction. The restriction is that, that a user can enter a maximum of 10 characters. Since it is a client side restriction so it can be bypassed very easily. And the bypassing steps I have already explained in medium security.

After we have bypassed the length restriction, inject the XSS payload in Name field and in Message field you can insert anything since it is not vulnerable.

Injecting final XSS payload to get alert message on the screen in dvwa Stored XSS exploitation

After injecting the payload click on Sign Guestbook to store the Message and Name in the database. Refresh the page you will get popup.

Getting final alert box on screen which proofs Stored XSS vulnerability at High level

We have got a popup that confirms that we have successfully exploited Stored XSS vulnerability at High-Level Security. So we have successfully exploited Stored XSS vulnerability in DVWA web app at low, medium and high security.

Thanks for reading this article on stored XSS. Hope you have learnt something new from it. For any queries and suggestions feel free to contact us at [email protected].

Update [29/08/2022]

If you are trying to exploit Stored XSS at high-level security on DVWA 1.0.7 [which is present in the default installation of Metasploitable Linux 2] then it is already patched in high-level security. The above payload (or in fact, any other payloads) will not work as of now.

This Post Has 2 Comments

  1. Haroon Rehman

    Can strip_tags() and htmlspecialchars() be defeated to Exploit XSS ?

    1. Deepak Kumar Maurya

      htmlspecialchars() can prevent XSS if properly implemented and till now it is the best way to prevent XSS in php. And we can’t completely rely on strip_tags() for XSS prevention because it can even be bypassed by using JavaScript Pseudo-Protocols, Event-Handlers, etc.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Deepak Kumar Maurya

Hi everyone, I am Deepak Kumar Maurya, creator of Ethicalhacs.com. I am InfoSec Consultant in day and Bug Bounty Hunter & CTF player at night. Sometimes write walkthrough and other cyber security articles here. You can connect me at https://www.linkedin.com/in/deepakdkm/