Lab Difficulty: Apprentice
Topic: Cross-Site Scripting (Reflected)
The objective of this lab is to perform a Reflected Cross-Site Scripting (XSS)
attack. The injection point is inside a JavaScript Template Literal (denoted
by backticks '). The application implements robust defenses: angle brackets
(<>), single quotes ('), double quotes ("), backslashes (\), and
backticks (') are all Unicode-escaped. The goal is to execute the alert(1)
function despite these restrictions.
Identification of Reflection Point
We began by injecting the string test123 into the search bar. The response
revealed that our input is reflected inside a JavaScript template
literal:
var message = `0 search results for 'test123'`;
Vulnerability Assessment
We are inside a string delimited by backticks: var message = INPUT;
Constraints:
String Breakout: Attempting to close the string with a backtick(``) fails
because the server escapes it to \u0060.
Standard Quotes: Single (``) and double (") quotes are also escaped
(\u0027, \u0022), preventing us from writing standard strings.
Tag Injection: Angle brackets (<>) are escaped (\u003c, \u003e),
preventing HTML tag injection.
The Loophole: While we cannot break out of the string, the context is a
Template Literal. Template literals in JavaScript have a unique feature
called String Interpolation. This allows embedded expressions to be evaluated
inside the string using the syntax ${expression}.
If the application does not escape the dollar sign $ or the curly braces
{}, we can execute JavaScript inside the string itself without needing
to break out of it.
Payload Construction
Our strategy is to use the interpolation syntax ${ ...} to run JavaScript.
Attempt 1: ${alert(1)}
alert(1) function runs, but the alert function returns
undefined. The string becomes “0 search results for ‘undefined’”.Crucial Check: The lab likely checks if the alert function executes, regardless of the return value.
Payload:
${alert(1)}
Execution
We sent the payload via the search parameter in Burp Suite.
Request: GET /?search=${alert(1)} HTTP/2
Response:
var message = `0 search results for '${alert(1)}'`;