Reflected/non-persistent cross-site scripting

What is reflected/non-persistent cross-site scripting?

Reflected cross-site scripting, also called non-persistent cross-site scripting, is a specific type of cross-site scripting (XSS) vulnerability. The terms reflected or non-persistent mean that the web application never stores the payload. The attacker does not send the payload to the web application. Instead, they send it to the victim in the form of a URL that includes the payload (often obfuscated). The victim clicks the URL and opens the vulnerable web application, unwittingly executing the payload.

Example of reflected/non-persistent cross-site scripting

In this example, the developer wants to display the name of the currently authenticated user on a welcome screen (welcome.php). They include the following login form on the login.php web page:

<form action="/welcome.php" method="get" id="login">
  <label for="name">Your name:</label>
  <input type="text" id="name" name="name">
  <label for "password">Your password:</label>
  <input type="password" id="password" name="password">
  <button type="submit" form="login" value="login">Log in</button>
</form>

The welcome.php file includes the following code:

// Display the name of the user
(...)
$name=$_GET["name"];
echo "<strong>Hello, ".$name."!</strong>";
(...)

As you can see, the application sends the name and password using the GET method and then displays the name on the welcome.php page without any validation or sanitization.

The reflected cross-site scripting attack

The attacker creates the following URL:


http://www.example.com/welcome.php?name=
%3c%73%63%72%69%70%74%3e%61%6c%65%72%74%28
%22%4c%45%41%56%45%20%54%48%49%53%20%50%41
%47%45%21%20%59%4f%55%20%41%52%45%20%42%45
%49%4e%47%20%48%41%43%4b%45%44%21%22%29%3b
%3c%2f%73%63%72%69%70%74%3e

The long string of hex codes in this payload is a URL-encoded form of the following content:

<script>alert("LEAVE THIS PAGE! YOU ARE BEING HACKED!");</script>

Then, the attacker sends the URL to the victim, for example, in an email or instant message. The victim clicks the URL, opens the welcome.php page, and their browser interprets the following code:

<strong>Hello, <script>alert("LEAVE THIS PAGE! YOU ARE BEING HACKED!");</script>!</strong>

The browser finds a <script> tag and executes the JavaScript code within it. As a result, it displays a pop-up window urging the user to leave the page. The consequences are that targeted users will stop visiting the web application, fearing for their safety.

The fix

Informed of the vulnerability, the developer decides to use HTMLPurifier filtering to safeguard the code and, additionally, escape HTML characters. They import the HTMLPurifier library and modify the welcome.php file in the following way:

// Display the name of the user
// Use HTMLPurifier with HTML escaping to avoid XSS
$name=$_GET["name"];

// Purify user data using HTMLPurifier
(...)
$purifier = new HTMLPurifier($config);
$purified_name = $purifier->purify($name);

// Just to be sure, HTML-escape special characters
$safe_name = htmlspecialchars($purified_name, ENT_QUOTES);

// Display the safe name
echo "<strong>Hello, ".$safe_name."!</strong>";
(...)

Consequences of reflected/non-persistent cross-site scripting attacks

Reflected cross-site scripting is regarded as less dangerous than stored/persistent XSS, but the consequences can also be dire. A reflected XSS attack is more difficult to perform because it needs more than just creating and delivering a single payload. The attacker also needs to use social engineering techniques to target a specific victim or group of victims.

Here are some actions that a black-hat hacker could perform based on the simple example presented earlier:

  • They could create a phishing campaign and send millions of emails containing a malicious link with a payload that redirects users to a phishing page designed to mimic your web application. As a result, millions of users could potentially have their credentials stolen and blame your web application, which would severely damage your reputation.
  • They could create a payload that sends the user to a malicious page that imitates your application’s login page. Then, they could send this malicious URL to your internal users, even your CEO. If even one of your users falls for the trick, the attacker will obtain their credentials to escalate the attack. Ultimately, this could let malicious actors gain access to other computer systems in your organization.

How to prevent reflected/non-persistent cross-site scripting vulnerabilities

To prevent reflected/non-persistent cross-site scripting, follow our overall guidelines for preventing cross-site scripting, listed in the general section dedicated to cross-site scripting.

Related blog posts