How to Prevent Cross-Site Scripting (XSS) Attacks
Input sanitization is key to defending against XSS attacks. Is your company's website secured?
Worried about distributed denial-of-service and SQL injection attacks on your website? You should be. But don't stop there, because chances are you're overlooking what is potentially the most prevalent website attack today: Namely, cross-site scripting (XSS). In one recent study, 75 percent of U.S. government websites were found to be vulnerable to XSS attack.
XSS attacks exploit the relationship between the user and the web site he or she is accessing. When you visit a web site, there is a presumption that the data transferred between your browser client and the web server is visible only to the owner of the web site and its authorized partners. But when an XSS attack muscles its way into this relationship, it can expose data to a malicious third-party – without the knowledge of either the end-user or web site owner.
The same-origin policy
The code downloaded from bigcorp.com can access document elements on the page generated from bigcorp.com; for example, this may include fields with a username or password, or information such as a user's account balance. This code can also call on code from any other scripts downloaded from bigcorp.com, such as methods or functions.
But the code downloaded from noodlecorp.com is typically prohibited from accessing these elements. This "same-origin policy" protects the user because we don't know if the code from noodlecorp.com can be trusted.
In practice, the same-origin policy is not equally implemented in all web browsers, and even web pages can explicitly expand the range of origin domains allowed to share data. The goal of an attacker is to slip code into the browser under the guise of conforming to the same-origin policy.
To achieve this, XSS attacks typically fall into two strategies: reflected attacks and persistent attacks.
In a reflected cross-site scripting attack, the user unwittingly sends code to a web server which then "reflects" that code back to the user's browser, where it is executed and performs a malicious act.
For example, consider a web site that accepts user input in the form of a search request. Suppose that the web application returns the search request with the results (or lack thereof), such as "Results of your search for XYZ…"
When the web application reflects the user input as output to the browser, it passes the same-origin policy test. This code could be rigged to retrieve sensitive information from the end-user and deliver it to a server controlled by the attacker.
In a typical reflected XSS attack, the malicious code will be baked into a hyperlink that is presented to the end-user. This link might be delivered via a phishing e-mail, for example, in the hopes of baiting the user into clicking it and triggering the attack sequence.
The scale of a reflected XSS attack is limited by how many users can be tricked into launching the malicious code. An attacker who wants to exploit XSS on a large scale will prefer to employ a persistent XSS attack.
The basic mechanism in a persistent XSS attack is the same – to embed malicious code into a web page delivered by the server, so that it satisfies the same-origin policy. But in this strategy, the attacker plants this code into a web page that every visitor will see.
Consider a web-based discussion board. The messages posted to a discussion board are seen by everyone who visits that page, but the content is submitted by a user. If the attacker can plant malicious code into a message they post themselves, most visitors to that page will wind up unwittingly executing the code.
Once again, the fundmanetal vector being exploited is inadequate sanitizing of user input. Message board posts – or any web site that displays user submissions – necessarily display content posted by unknown parties. If this content is not thoroughly scrubbed ofpotentially malicious code, a persistent XSS attack can easily be planted on the site.
Consequences of an attack
XSS code can be crafted to lift a variety of sensitive data including any information presented on the same page where the cross-site code was planted. But the most dangerous risk is the theft of user authentication credentials.
Many sites save authentication or session credentials in a browser cookie. Malicious code can lift this cookie and send it to a server controlled by the attacker. With that cookie in hand, the attacker might be able to access the same web site masquerading as the victim user, bypassing any login.
Even if the compromised site does not provide access to highly sensitive content like e-mail or finances, a hacker might be able to access personal details that can be leveraged against a more sensitive site such as the user's webmail account.
Malicious code can also be designed to alter the content on the page presented to the site visitor. One nasty trick would be to change the destination of a link on the page (or present a new link that the visitor is urgently told to click), baiting them into visiting a malicious site fully engineered by the attacker to launch a more serious attack.
Alternatively, an attacker might use an XSS attack against the site owner rather than the site visitor. The same trick of altering output can be used to vandalize content – imagine a news site where the XSS attack defaces headlines and undermines the credibility of the site.
Defending against XSS
Ultimately, XSS is a type of code injection very similar in nature to SQL injection. Like protecting against any code injection attack, the best defense is thorough and well-tested santization of any and all user input.
Site owners need to determine every input path by which their web site accepts incoming data. Each path must be hardened against malicious data that can represent executable code. Often this requires implementing mulitple filters along the communication pathway – for example, a web application firewall such as ModSecurity plus input sanitization within server-side input processing code.
As a secondary defense, a site could link browser cookie credentials to the user's IP address. While not a perfect defense, this would prevent easy abuse of users' cookies. An attacker could engineer a system to lift the user's IP address and spoof their own actions under that address but this degree of attack will be far less widespread than simple cookie theft.
Aaron Weiss is a technology writer and frequent contributor to eSecurity Planet and Wi-Fi Planet.