PortSwigger: XSS Labs - Apprentice
Foreword
Prerequisite reading: https://portswigger.net/web-security/cross-site-scripting
Link to all XSS labs: https://portswigger.net/web-security/all-labs#cross-site-scripting
What is a site? The combinations of a domain name and valid TLD. E.g., example.com
or example.co.uk
(.co.uk
is a single TLD)
Goal: Bring JavaScript from one site to another. Although the Same-Origin Policy (SOP) is applied against origins, which are distinct from sites, XSS is used to circumvent SOP.
Apprentice Labs
Reflected XSS into HTML context with nothing encoded
It is stated that the vulnerability is present in the search bar.
Payload: <script>alert(document.window)</script>
Success
Stored XSS into HTML context with nothing encoded
Pick any post.
Navigate to the comments.
Any one of these fields could be vulnerable to HTML injection, and possibly vulnerable to XSS.
Payloads:
- Comment:
<script>alert(1)</script>
- Name:
<script>alert(1)</script>
- Email:
fake@email.com
- Utilizes client-side regex for input validation
- Website:
http://fake.com?maybe=<script>alert(1)</script>
An attempt to go back to the blog should show the alert box on screen.
DOM XSS in document.write
sink using source location.search
I would recommend reading about what Sources and Sinks
are in the context of web security. Basically, Sources
are origins of attacker/user-controlled input. This could be anything from the search bar (in the first XSS lab covered in this post), to a user’s profile. Sinks
are dangerous/vulnerable functions that take this input without prior input validation and input sanitization.
In this lab, location.search
is the source, and document.write
is the sink.
document.write
will write our input to the DOM, sourcing the input from location.search
.
Final payload: "><img src="" onerror=alert(3)>
src=""
points to nothing, forcing an erroronerror=alert(3)
will execute the JavaScript “alert(3)
” once an error is triggered
">
is necessary because we need to escape the HTML tags that precede our injection. This is similar to circumventing the logic in vulnerable query strings for SQLi. Since document.write
will copy and paste our input directly into the DOM, we need to escape the HTML tag that the payload is being put into.
An alert should be raised immediately after submitting the payload.
Spot HTML tag to break out of
Submit your input and use inspect element to search for a <img>
tag. This is where the input is being pasted to in the DOM. There you will see that the payload must break out of the <img>
attribute. Using ">
as a prefix to the core of the payload will be sufficient for this lab