JavaScript Attack/Defend
Tim Kulp | June 8, 2011
As developers and designers we work hard to build visually attractive, fast and easy to maintain applications. Our goals are to make sure the applications we build stick to users and keep them coming back for more. Security is not always at the forefront of our minds. No one intentionally builds insecure software but often a lack of security knowledge leads developers to build vulnerabilities into their applications. In this article we are going to examine two web security attacks, how they are executed and how to defend against them. By the end of this article you will have a few techniques in your security tool belt to help you build more secure web applications.
The Open Web Application Security Project (OWASP) is a global organization that focuses on improving web application security and security awareness among the developer community. OWASP maintains a list of what are considered the most serious top ten security threats to web applications: the OWASP Top Ten project. We are going to examine two attacks from the Top Ten list, Cross Site Scripting (XSS) and Cross Site Request Forgery (CSRF). These attacks are both widespread and can be easily overlooked when developing an application. The good news is that finding these attacks is simple and building mitigations for them is just as easy.
Cross Site Scripting (XSS)
Many web applications today allow users to generate content to share with other users. To find examples of this look no further than a corporate blog. Many companies use blogs to communicate with their customers by writing about new products, ad campaigns, or just the everyday happenings of the business. To encourage a conversation between the customer and company, these blogs permit comments. Comments are user generated content that is posted to the blog for others to see, including the company’s blog administrator. In this scenario, Cross Site Scripting attacks occur when a user leaves a comment on the blog with the intent to execute a malicious payload against another user.
Cross Site Scripting (XSS) is an exploitation of the trust that the user has with the web site where the attack is hosted. When a user is interacting with a site that they trust they do not expect that a malicious user has poisoned the site against them. Anywhere in a site that allows input from a user opens the door for a possible XSS attack. The malicious input is often in the form of some client side script (usually JavaScript but it could also be VBScript, ActionScript, etc…) that executes when the user performs an action such as clicking a link or loading the page.
Three Types of XSS
Three Types of XSS There are three types of XSS attacks:
- Stored: The attack is saved into a persistent storage medium such as a database or file.
- Reflected: Non-persistent attacks needing a delivery method to initiate the attack such an email or malicious form.
- DOM based XSS: This attack manipulates the DOM to execute the attack payload.
For this article we will be referring to Reflected XSS in our examples but the defenses we will cover work for all the flavors of XSS. More information can be found at: https://www.owasp.org/index.php/Cross-site\_Scripting\_(XSS)XSS attacks can impact your users in a variety of ways. The attack can steal information from the user, perform unintended actions in the application or even load malicious software to the user’s machine. A XSS attack can also have significant impacts on your web application as well. Once the attack is exposed, users will lose faith in the safety of your application causing damage to your company’s reputation.
XSS Attack
So how does a XSS attack work? Here is an example of a very simple Reflected XSS attack:
<span id="message-text">
<%=Request.QueryString["msg"]%>
</span>
This quick code snippet grabs a string from the query string variable named “msg” and writes it directly to the HTML element “message-text”. Imagine the query string variable was the following:
<script>alert('123');</script>
This would load the script tag and execute the alert message to the HTML of message-text.
While this example is very simplistic, XSS attacks can become more difficult to find when they are invoked from an Ajax request or when created during a data binding expression. When the attack is brought to the page from a database or other stored data, which is called a Stored XSS Attack. The example of the corporate blog is a Stored XSS attack as the malicious user has left the code to perform the XSS attack in the corporate blog Comments database.
XSS Defense
To defend against XSS attacks you must be conscious of input to your application. Input can come from many different sources such as configuration files, databases, web services, and any other source that populates the application with data. With this in mind, the best defense against XSS is sanitizing data as it is input into your application.
Fortunately sanitizing your input is simple using tools like the Microsoft AntiXSS Library (available for download at https://www.microsoft.com/en-us/download/details.aspx?id=28589). This code library makes it very easy to sanitize code on the server side. Using the AntiXSS library for our above example, we would update the code to be the following:
<span id="message-text">
<%=Microsoft.Security.Application.Encoder.HtmlEncode(Request.QueryString["msg"])%>
</span>
The library offers a multitude of encoding options including JavaScript, CSS, and XML encoding among others. Using the Anti-XSS Library, you can clean the input going in to your data store and sanitize the output coming through your application. While this library is an excellent resource for server side coding, sometimes you need a client side sanitizer to make sure the data you retrieve in JavaScript is clean.
The OWASP Enterprise Security API (ESAPI) is one of the many projects available on the OWASP site. This API allows developers to wrap output into encoder methods for most development platforms. The JavaScript ESAPI library can be found at https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API#tab=JavaScript. Encoding with the ESAPI JavaScript library is just as simple as using the AntiXSS encoder. Here is an example:
<script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
<!-- ESAPI requirements -->
<script src="Scripts/lib/log4js.js" type="text/javascript"></script>
<script src="Scripts/esapi.js" type="text/javascript"></script>
<script src="Scripts/resources/i18n/ESAPI_Standard_en_US.properties.js" type="text/javascript"></script>
<script src="Scripts/resources/Base.esapi.properties.js" type="text/javascript"></script>
<!-- ESAPI usage -->
<script language="javascript" type="text/javascript">
function cleanData() {
org.owasp.esapi.ESAPI.initialize();
var cleanedInput = $ESAPI.encoder().encodeForHTML("<script>alert('123');<//script>");
$("#message-text").html(cleanedInput);
}
</script>
Using the $ESAPI object, we can encode the malicious string to be treated like text data and not interpreted like HTML tags. The ESAPI encoder is an excellent tool to ensure clean data from Mashups or the results of an Ajax call.
Libraries like the Anti-XSS library and ESAPI do have a downside, performance. By channeling all your data through a sanitization library, you incur some overhead in the application. The security benefit from using these libraries far outweighs the slight performance hit as XSS attacks can damage not just your company’s image but also your user’s information.
Cross Site Request Forgery (CSRF)
While XSS exploits the user’s trust in a specific web site, Cross Site Request Forgery (CSRF) exploits a user’s trust in how their Web Browser works. A CSRF attack happens when an attacker crafts a malicious HTTP request and then tricks the user into executing the request. When an HTTP request is sent to a web site all the cookies, session and header information are sent as well. With this in mind, using CSRF an attacker could execute commands against a site posing as the user.
Let’s look at an example of this attack. One day a user is checking their bank balance online using the new XYZBank.com website. The user makes a few transfers moving money around different accounts. Leaving the site, the user clicks around on the web until they land on the corporate blog we discussed in the XSS example. The user reads the latest blog entry and looks at the various comments. One of the comments was left by a malicious user who has setup an invisible image tag whose SRC attribute is an HTTP request to transfer money from the users account to the attacker’s account. Since the user was already authenticated to the XYZBank.com website, the browser and server assume this is a valid request from the user and executes the money transfer. The next time the user goes to XYZBank.com and sees they are missing money; it is likely they will assume their account was hacked and not connect the loss to the corporate blog.
CSRF Attack
Building a CSRF attack requires a lot of homework. The first step of any attack is building a profile on the target, in this case XYZBank.com. By using the banking site, the attacker can learn what cookies are stored, what fields perform what actions, how data flows through the site, etc… By creating an account on XYZBank.com and using the site, our attacker has learned the following items:
- Primary account number is stored in a cookie to save the user from selecting which account is their primary account on each visit.
- On the money transfer page there are three fields required to transfer money:
- Source Account Number: Where the money is coming from. If the value is blank, the site assumes the use of the Primary Account.
- Destination Account Number: Where the money is going to
- Dollar amount: How much is being transferred
- The site also uses query string parameters for persisting data between HTTP requests.
Using this information, the attacker can create the following image tag:
<img src="https://www.xyzbank.com/transfer.php?txtSource=&txtDest=[Attacker's Account]&txtAmount=1500" width="0" height="0" />
This zero height, zero width image would be invisible to the user but when the image is called by the Browser, the SRC attribute will send the transfer request to XYZBank.com. When the request is sent, the cookies and session for any existing connections to XYZBank.com will be sent as well making the website think that the request is legitimate. CSRF attacks can use images as in the example above or they could use anything that can make an HTTP request.
CSRF Defense
While XSS defense is simply a matter of cleaning data in your system, CSRF exploits how an Internet Browser is supposed to work. The good news is that there are multiple defenses that you can put in place to protect your application against CSRF. We will examine a few server side options first and then discuss some best practices to present to your users on how they can defend against CSRF on other sites.
Our goal is to create multiple layers of defense against a CSRF attack. The first step to this is to try and validate that the request is coming from your own site (in this case, a request to XYZBank.com is coming from XYZBank.com). Checking the HTTP Referrer Header can usually tell you where a request is coming from. This HTTP Header keeps track of where the HTTP request originatedfrom (for more information about the HTTP Referrer Header see: https://www.w3.org/Protocols/HTTP/HTRQ_Headers.html#z14). If the request originates from XYZBank.com then the HTTP Referrer will be XYZBank.com. Unfortunately, the Referrer Header can be spoofed and is not always present for every HTTP request. Checking the Referrer is simply an added layer of validation that you can use.
A much more reliable method for preventing CSRF attacks is to use the Synchronizer Token Pattern. This design pattern uses a randomly generated token that is associated with a user’s session to ensure that the request originated from the site. The random token is then stored in a hidden field and checked on each request. Using this method, the attacker would not be able to guess the random token (as it is only stored in a hidden field) and thus the request would be rejected. Using this method we would setup a Hidden Field on the HTML page and populate it with a random token:
<input type="hidden" id="hdn1" value="29ldfoa9210129041jljfmcaoj39141" />
Now, for our banking site we would be expecting another parameter in the query string. The requested URL would now look like the following:
https://www.xyzbank.com/transfer.php?txtSource=\&txtDest=\[Attacker's Account]&txtAmount=1500&hdn1=29ldfoa9210129041jljfmcaoj39141
When the request arrives at the transfer.php page, we can check the value of “hdn1” against what has been stored in the Session. If the values match, then the request is valid and can continue. If not, then the request is rejected and an error message presented to the user.
For ASP.NET developers, ViewState already validates the requests coming in to the server but it is possible to forge or copy a ViewState with known valid data. By default, ViewState is not tied to a particular user but by using the Page.ViewStateUserKey, developers can bind a ViewState to a specific user or session. Setting the ViewStateUserKey to the SessionID will make the ViewState valid only for that SessionID so if an attacker attempts to reuse/forge the ViewState value, the ASP.NET application will see the request as invalid. Enabling this ViewState feature is simple. Add the following to the Page_PreInit method of your ASP.NET page:
void Page_PreInit(object sender, EventArgs e)
{
Page.ViewStateUserKey = Session.SessionID;
}
You could use other properties such as User ID but whatever data point you use, it must be unique per user. Otherwise, it totally defeats the purpose of the ViewStateUserKey and opens your application to ViewState forgery.
The best defense against CSRF is an easy tactic that your users can do…just log out. Most CSRF attacks leverage actions that are available to authenticated users. Encourage your users to log out from your site and others when they are finished. Learn more about all of these defenses and more on the OWASP CSRF Prevention Cheat Sheet.
Tip of the iceberg
The two attacks we examined in this article, Cross Site Scripting (XSS) and Cross Site Request Forgery (CSRF), are common attacks but not the only security threats on the web. OWASP’s Top Ten list is an excellent resource to start your web application security training. Correcting XSS and CSRF vulnerabilities on your site is an excellent starting point on your application security journey. By increasing your security awareness implementing some of the mitigations presented in this article, you will be well on your way to protecting your user’s data and the reputation of your application.
About the Author
Tim Kulp leads the development team at FrontierMEDEX in Baltimore, Maryland. You can find Tim on his blog or the Twitter feed @seccode, where he talks code, security and the Baltimore foodie scene.
Find Tim on:
- Tim's Blog
- Twitter: @seccode