Reflected

Reflected XSS occurs when malicious scripts are reflected off a web server, executed immediately, and displayed in the user's browser, typically via URL parameters or form inputs.

Reflected Server XSS

The example below is based on OffSec's WEB-200 course.

This type of XSS is often found in GET requests and is based on the fact that the user trusts the domain. The application below has a search functionality where the search term is passed through a GET request and the s parameter. It is also reflected on the page via a div element (Figure 1).

Figure 1: Searching for potential XSS entry points.

A good starting point for finding XSS, is to first test for HTML injection as it has less potential for error. However, being able to inject HTML doesn't guarantee an XSS vulnerablity (Figure 2).

<!-- the HTML payload used -->
<h1>test</h1>
Figure 2: Testing for HTML injection.

Since the app is vulerable to HTML injection, we can proceed testing for XSS (Figure 3).

// the JavaScript payload used
<script>prompt("XSS")</script>
Figure 3: Testing for XSS.

If our target clicks the link that includes the payload, it will be executed on their browser.

search.com/search.php?s=%3Cscript%3Eprompt%28%22XSS%22%29%3C%2Fscript%3E

In this case, the server initiates the appending of the payload (Figure 4) and the client just executes it.

Figure 4: Confirming the server-side reflected XSS.

Reflected Client XSS

The example below is based on OffSec's WEB-200 course.

The impact of Reflected Client, aka DOM-based, XSS is similar to that of Reflected Server XSS, although the discovery and payload may differ. The payload is appended on the client-side rather on the server-side, and this mean that we can't enumerate Client XSS by intercepting the traffic and reviewing the server's response. Instead, we need to let the browser render the page fully and check if the payload has worked. The application we are testing includes a GET request with the parameter name which seems to be vulnerable to HTML injection (Figure 5).

<!-- the HTML payload used -->
<h1>x7331</h1>
Figure 5: Testing for HTML injection.

Testing for XSS seems unsuccessful, although the payload seems to be appended correctly (Figure 6).

// the JavaScript payload used
<script>prompt("XSS")</script>
Figure 6: Testing for XSS.

Diving into the Network tab and reading the HTTP response, we can see that the string returned is Welcome, User! which is not what we get on our browser (Figure 7).

Figure 7: Inspecting the network tab.

Scrolling down the JS file, we can find that two more resources are loaded (Figure 8).

Figure 8: Enumerating JavaScript resources.

Diving deeper into the survey.js file, we find out that it sets the innerHTML of the welcome DOM element to the value set in the name parameter. This is where our payload gets injected.

Figure 9: Investigating the survey.js file.

According to MDN, HTML specifies that a <script> tag inserted with innerHTML should not execute and it suggests using the <img> tag instead (Figure 10).

// the JavaScript payload used
<img src='x' onerror='alert(1)'>
Figure 10: Successfully performing an XSS attack.

Filter Bypass

The example below is based on PortSwigger's Reflected XSS into HTML context with most tags and attributes blocked lab.

In this web application, there is a search functionality and the search term is reflected back into the page within HTML tags (Figure 11).

Figure 11: Identifying where our input is reflected.

When our payload is inside HTML tags, we can simply add new HTML tags to trigger it. It seems that there is a blocking specific tags (Figure 12).

Figure 12: Common JavaScript tags seem to be blocked by a WAF.

We can create a tag wordlist using PortSwigger's XSS Cheatsheet, and fuzz the application to see which tags are allowed (Figure 13).

Figure 13: Fuzzing JavaScript tags with Burp's Intruder.

Trying the <body> tag results in another verbose error message (Figure 14).

Figure 14: Another verbose error message informing us about a blacklisted attribute.

We can repeat the same process and enumerate allowed attributes (Figure 15).

Figure 15: Fuzzing JavaScript attributes with Burp's Intruder.

Now, all we have to do is delivering our XSS payload to the victim via the exploit server.

// the JavaScript payload used
<iframe src="https://0a64008c03c63be4804ada980065007b.web-security-academy.net/?search=%3Cbody+onresize%3Dprint%28%29%3E" onload=this.style.width='1em'>

Within JS

The example below is based on PortSwigger's Reflected XSS into a JavaScript string with angle brackets HTML encoded lab.

This time the search keyword ends up within a block of code (Figure 16).

Figure 16: Identifying the context of a potential XSS flaw.

We can treat this similar to an SQLi and try injecting JavaScript code to the search keyword (Figure 17).

Figure 17: Achieving XSS via JavaScript Injection.

Last updated

Was this helpful?