Portswigger Academy — Reflected XSS into a template literal with angle brackets, single, double quotes, backslash and backticks Unicode-escaped — Write-up
In this write-up I will be showing my thought process behind solving the aforementioned Portswigger Academy challenge. DISCLAIMER! This write-up contains the answer to the challenge, so if you are here for hints, watch out:)
To start off, we can see from the title that there are a lot of things that are unicode escaped, meaning a lot of our usual tools for XSS are gone, but there is one thing that is not escaped and that makes this lab quite easy.
The title says "Reflected XSS into template literals…". Template literals? What is that you may ask. Here is my explanation: Template literals is a way of including variables, user input for example, into a string. Most important of all they allow for embedded JavaScript that will be run as normal. Template literals are enclosed in backticks, and the way you add a variable to a template literal is:
num_apples = 5;
string = `I have ${num_apples} apples`;
The key takeaway from the description and this article written by Portswigger, is that if JavaScript is given as input, it will be run.
The solution to the lab is given in the aforementioned article, which tells us that when we give "${alert(1)}" as input to the template literal, it will be evaluated as valid JavaScript and run.
Solution:
${alert(1)}
Nice that I found a solution, but I had a hard time understanding how user input can be run as JavaScript, because when I made a lab myself that I ran on localhost, with the following code:
<body>
<h1 id="text"></h1>
<script>
var input = prompt("Give me something");
var output = `I am saying ${input}`;
document.getElementById("text").innerHTML = output;
</script>
</body>
The code above treats the 'input' as text and it gets literally put in, without being run as code. I even tried this with taking the input from the URL parameters, but it still only treats it as text.
After searching a bit on the internet and asking Copilot, I came to the conclusion that the input needed to be enclosed in script tags. Which still did not work on my own lab. Therefore I am turning to the people of the internet for help. If you have any idea how to get this to work, so that the input that solved the Portswigger lab, will work on my own lab as well, let me know.
Thank you for taking the time to read this write-up, and if you have any feedback, I will be more than happy to receive it! Make to sure to also check out my other write-ups that I have posted here on Medium.