What is it and why should I care?
Cross-Site Scripting (XSS) is another issue that is caused because of poor code/data separation. The general issue is that a developer intends the user input to be interpreted as data, but an attacker can manipulate the input to cause the browser to interpret the input as tags or commands.
XSS is exceedingly popular and well-known, and along with SQLi, is probably 1 of the 2 best-known vulnerabilities across web app security.
What should I do about it?
Note: One great resource which I drew from for both this post as well as the more in-depth post is the XSS Prevention Cheat Sheet over at OWASP.
I’ve already written here on the problems with and solutions for XSS. However, I’ll cover the basic solutions briefly here for clarity’s sake.
1. Canonicalize Input
Get your input data into it’s simplest base form in preparation for validation so that you’re more confident your validation routines aren’t being circumvented.
2. Validate Input Using a Whitelist
Whitelist validation (accept only known good data) is a key tenet of good security. Check the content of the data, the length, data type, etc.
3. Contextual Output Encoding/Escaping
Output Escaping is the last step, and must be done for the appropriate context. You must understand where you’re sticking data, and how that location is interpreted from the browser’s view. This can be a sticky issue, so this one gets a bit problematic.
Now that we’ve covered the basic technology solution for XSS, let’s consider the larger context of eradicating entire classes of vulnerabilities from our codebase as I discussed a couple weeks ago. Let’s look at each specific subpoint I mentioned in that post and consider what you might do regarding XSS.
1. Understand the problem.
I’d read available documentation on XSS to make sure I understood the issue as well as I *think* I do. The cheat sheets at OWASP are good for basic theory, but there are books that talk about the issue in more detail, and there are additionally books that discuss how browsers work that can be helpful to understand. XSS is actually one of the more complex vulnerabilities around, and it actually is still changing because it’s so closely tied to browser feature sets which are always expanding. In addition, javascript frameworks of significant capability have had a huge impact on web applications in the last 5-7 years, thereby compounding the problem.
2. Consider all use cases where the issue can occur.
I would think about all the different types of XSS interactions that occur in my application portfolio. How many languages am I developing in or supporting? What frameworks am I developing with? Do I need to allow users to enter HTML that is then displayed (JSoup / AntiSamy problem space)? Do I have a constrained browser environment (or do I still need to support IE 6)?
3. Evaluate solutions.
I would look at the XSS cheat sheet from OWASP (and any associated weaknesses with the approaches that it espouses). Once I understood the recommended solution(s), I would consider whether said solution(s) would work in the environment in which I’m working. For XSS, there’s really not a lot of alternatives to how to solve the basic problem. However, there are differing implementations of solutions. For example, there are solutions where that require more effort to solve the issue, but do leave the maximum of flexibility (plain ol’ JSP’s), there are frameworks that default to solving the most common version of the problem (struts, springmvc, etc. – all default to basic html entity encoding), all the way up to templating solutions which constrain flexibility but offer a safer-by-default scenario (JXT). Consider also solutions for special use cases, such as the requirement to allow certain constrained amounts of HTML along with plain data, and how you might solve that class of issue (JSoup / AntiSamy).
4. Institutionalize the chosen solution.
After deciding on your collective solution, you have to work with development teams to determine the current status of vulnerability to XSS (beware: it’s probably gonna be pretty bad). This step is a good place to (re)train developers on this specific topic from a security perspective, since they’ll be implementing the solution. You then just have to do the work of implementing the chosen framework(s), making necessary modifications to the source, and re-testing applications to make sure everything still works as expected.
5. Add technology and processes for verification.
At this point, I would add a few tools in to make sure the technology is being used. I would make sure that there were static and dynamic analysis tools in place to check for XSS, though tools vary in usefulness here and coverage can sometimes be spotty. I would also make sure to code review UIs to see where dynamic data is emitted. I might go so far as to write custom rules for my static toolset that “trusts” my safe output functions to reduce any false positives. Lastly, I would specifically look for “known bad data”. Using something like AppSensor or a WAF is a way to automate some of that process.
In conclusion, hopefully it’s clear that solving XSS is a manageable task, but just takes some focused effort on research, training, implementation and verification. The pattern I’ve described for both SQLi and XSS are useful to follow for other vulnerability classes in order to really build a robust environment and suite of applications.
References
———–
https://www.owasp.org/index.php/XSS
https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet
https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet
https://www.owasp.org/index.php/Abridged_XSS_Prevention_Cheat_Sheet
What is it and why should I care?
X-XSS-Protection is a Microsoft IE technology used to help prevent reflected XSS attacks in IE.
Note 1: This is not a “panacea” for XSS. There is no excuse for not developing your site in a secure manner to prevent XSS. This however is a protection offered by the browser itself (as opposed to an application), meant to protect the masses from the vast amount of XSS litter on the internet.
Note 2: Firefox (by way of NoScript), Chrome (by way of WebKit) and Safari(also WebKit) have similar protections, but apparently don’t use the X-XSS-Protection header as a controlling mechanism.
The XSS protection provided essentially checks for request content that is matched in the response and would cause an XSS vulnerability to be exploited. The filter then performs some mangling of the content to prevent the attack from succeeding. According to the docs, IE has the protection turned on by default for most security zones, including the Internet zone, which is the primary concern for most users.
What should I do about it?
The first thing you should do is work towards resolving any and all XSS issues in your application. As a security minded developer, this is a must.
The recommendation for the use of this header is actually not so straightforward in my opinion. In general, the other HTTP headers I’ve described already in the series have had very little downside. However, the X-XSS-Protection header has had some problems in the past. As far as I’m aware, the IE folks have done a good job of dealing with the known vulns, but I still have concerns since some of the vulns have exposed security problems.
In general, I would recommend keeping the protection enabled, unless you are very sure you have XSS all cleaned up in your app. However, this comes with the caveat that you should at least put some thought into the use cases in your site first. Depending on your choice, here are the options you have available to use, and how you enable them in your application using the X-XSS-Protection HTTP header.
1. Enable the protection for all security zones in blocking mode (Blocking mode means the site won’t display at all if an XSS attempt is found, but rather a simple warning to the user that the attack has been blocked):
X-XSS-Protection: 1; mode=block
2. Enable the protection for all security zones:
X-XSS-Protection: 1
3. Leave the protection enabled for the default zones:
Do nothing.
4. Disable the protection entirely (I only recommend this in 2 cases: either you’re positive that you’ve completely resolved XSS in your app, or there’s an issue in the XSS filter that you’re aware of that causes an additional vulnerability) :
X-XSS-Protection: 0
The protection provided by the X-XSS-Protection header is not complete, but it does raise the bar against attackers and helps protect users. While there have certainly been some implementation issues, the fact that all the major browsers have some implementation of reflected XSS protection shows the importance of this issue. Be prudent in implementation, but certainly do everything you can to help your users be safe.
References
———–
http://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx
http://blogs.msdn.com/b/ie/archive/2008/07/02/ie8-security-part-iv-the-xss-filter.aspx
http://blogs.msdn.com/b/mikeormond/archive/2009/01/26/ie8-cross-site-scripting-xss-protection.aspx
http://msdn.microsoft.com/en-us/library/dd565647(v=vs.85).aspx
http://michael-coates.blogspot.com/2009/07/ie-8-anti-xss-bit-overblown.html
http://jeremiahgrossman.blogspot.com/2010/01/to-disable-ie8s-xss-filter-or-not.html
http://www.jtmelton.com/2009/01/12/the-owasp-top-ten-and-esapi-part-2-cross-site-scripting-xss/
http://michael-coates.blogspot.com/2009/11/ie8-xss-filter-bug.html
http://xforce.iss.net/xforce/xfdb/47442
http://hackademix.net/2009/11/21/ies-xss-filter-creates-xss-vulnerabilities/
http://www.theregister.co.uk/2009/11/20/internet_explorer_security_flaw/
What is it and why should I care?
Content Security Policy (CSP) is a new(ish) technology put together by Mozilla that web apps can use as an additional layer of protection against Cross Site Scripting (XSS), which is the primary goal of the technology. A secondary goal is to protect against clickjacking.
XSS is quite a complex issue, as is evidenced by the recommendations in the OWASP prevention cheatsheets for XSS in general and DOM based XSS. CSP does several things to help app developers deal with XSS.
Whitelist Content Locations
One reason XSS is quite harmful is that the browsers implicitly trust the content received from the server, even if that content has been manipulated and is loading from an unintended location. This is where CSP comes in: CSP allows app developers to declare a whitelist of trusted locations for content. Browsers that understand CSP will then respect that list and only load content from there, and will ignore content that references locations outside the list.
No Inline Scripts
Adding scripts inline to content is the way XSS is done, made possible because browsers have no way of telling whether the site actually sent that content, or if the attacker added the script to the site content. CSP prevents this entirely by forcing the separation of content and code (Great design!). This means that you have to move all your scripts to external files, which will require work for most apps, though it can be done (Twitter is one example of a high-profile site using CSP). The upside is in order for an attack to be successful with CSP, an attacker has to be able to:
Step 1) Inject a script tag at the head of your page.
Step 2) Make that script tag load from a trusted site within your whitelist.
Step 3) Control the referenced script at that trusted site.
This makes an XSS attack significantly more difficult.
Note: one common question here is what about event handling. CSP does still allow event handling through the onXXX handlers or the addEventListener mechanism.
No Code From Strings (eval dies)
Another welcome addition is the blacklisting of functions that create code from strings. This means that usage of the evil eval is out (along with a few others). Creating code from strings is a popular attack technique and is rather difficult to trace, so the removal of all these functions is actually quite helpful.
Another common question stemming from this is how to deal with JSON parsing. The right way to do this from a security perspective has always been to actually parse the JSON instead of eval it anyhow, and this functionality is still available, so nothing changes there.
Policy Violation Reporting
A rather cool feature of CSP is that you can configure your site to have a violation reporting handler, and then have that data available whether you run in report-only or in enforcing mode. In report only mode, you can get reports of locations in your site that will be prevented from execution when you enable CSP (a nice way to test). In enforcing mode, you can still get this data, but in production, you can also use this as a simple XSS detection mechanism (bad guy tried XSS and it didn’t run).
What should I do about it?
Well, you should use it! Actually, CSP doesn’t really seem to have a downside. It’s there to make your site safer, and even if a client’s browser doesn’t support it, it’s entirely backwards compatible, so your site won’t break for the client.
In general, I think the basic approach should be:
Step 1) Solve XSS through your standard security development practices (you should already be doing this)
Step 2) Learn about CSP – read the specs thoroughly
Step 3) Make the changes to your site and test and re-test (normal dev process)
Step 4) Run in report-only mode and monitor any violations to find areas you still need to fix. (could be avoided if you have a full functional test suite you can execute against your app in testing – good for you if you do!)
Step 5) After you’re confident your site is working properly, turn it on in enforcing mode.
As for how you actually implement it, you have 2 basic options: an HTTP header and a META tag. The header option is preferred, and an example is listed below.
Content-Security-Policy: default-src 'self';
img-src *;
object-src media1.example.com media2.example.com *.cdn.example.com;
script-src trustedscripts.example.com;
report-uri http://example.com/post-csp-report
The example above says the following:
Line 1: By default, only allow content from ‘self’ or the site represented by the current url.
Line 2: Allow images from anywhere.
Line 3: Allow objects from only the listed urls.
Line 4: Allow scripts from only the listed url.
Line 5: Use the listed url to report any violations of the specified policy.
CSP is a very interesting and useful new technology to help battle XSS. It’s definitely a useful tool to add to your arsenal.
Update (2/15/2012) Here’s an interesting post on using ModSecurity to add CSP to your site – a nice look for the administrators. (h/t @ryancbarnett)
References
———–
https://developer.mozilla.org/en/Introducing_Content_Security_Policy
https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html
https://wiki.mozilla.org/Security/CSP/Design_Considerations
https://wiki.mozilla.org/Security/CSP/Specification
https://dvcs.w3.org/hg/content-security-policy/raw-file/bcf1c45f312f/csp-unofficial-draft-20110303.html
http://www.w3.org/TR/CSP/
http://blog.mozilla.com/security/2009/06/19/shutting-down-xss-with-content-security-policy/
https://mikewest.org/2011/10/content-security-policy-a-primer
http://codesecure.blogspot.com/2012/01/content-security-policy-csp.html
https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet
https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet
http://blog.spiderlabs.com/2011/04/modsecurity-advanced-topic-of-the-week-integrating-content-security-policy-csp.html
This is usually a Java-only site, but I thought this paper was fairly interesting, so thought I’d do a quick post. The implementation is .NET, but the concepts are transferrable.
The good folks at Microsoft Research have come up with a clever new technique for XSS “prevention” called ScriptGard. The paper is located here. (Looks like there was a previous version of the paper in 2010, but this is the latest updated copy.) The paper is a good read, but I just wanted to summarize for folks with short attention spans like me :>.
Essentially, they’ve come up with a performant solution for runtime context-sensitive XSS protection in legacy applications, without requiring changes to the code. That’s quite an achievement, so how do they do it?
Here are the basic steps:
[Training phase]
1. Instrument the code and insert hooks to perform taint propagation
2. Apply a simulation algorithm to execute the code and see where tainted data reaches a sink
3. Evaluate whether or not the trace (flow) from source to sink is XSS’able (via a browser implementation that actually analyzes the output context)
4. Mark and cache any “bad” flows
[Runtime phase]
5. If any “bad” flows are executed, process the input and appropriately encode/sanitize the output.
There is a lot more that you can get from the paper, but that’s the gist as I read it.
There are several interesting points to consider from the paper:
- The proposed solution is meant to work on legacy code, in contrast to templating libraries which seem to be a good solution for new code. Templating libraries are good in that they help structure the code better and provide a better separation of code and data, but that doesn’t really help for legacy code, which is quite a challenge. [templating libraries such as OWASP jxt or Google AutoEscape are examples from Java]
- They initially tried doing all this work at runtime, but it was prohibitive from a performance perspective (one extreme example noted 175X – not %, 175 times – worse performance). This meant the process had to be broken up and some data carried over from testing and analysis to runtime.
- They found a significant number of examples in real tested code where a) the wrong encoding was used [bad, common], b) encoding was applied, but not necessary [ok, reasonably common], or c) the right encoders were applied, but in the wrong order [bad, becoming more common]. Lesson: applying encoding/sanitization is hard, even if you are paying attention and know what you’re doing. The rules can become somewhat esoteric, especially when browser bugs cause weird things to happen in corner cases and browser vendors don’t always agree on how things should be handled. Automation is your friend here.
- In order to figure out the context, they actually had to include a browser. I’ve been saying this was required for years now, but had no idea how to make it performant. Looks like they are smarter than I am (DOH!). This does have a certain issue, however, regarding browser implementation quirks. What if the internal browser implementation is wrong? Now the trained algorithm is wrong and the sanitization is wrong …
In conclusion, this paper is a good read if you have the time. XSS doesn’t appear to be going away anytime soon, but research like this gives me hope for novel ways of solving the problem.
Thanks to @securityninja for pointing this paper out.
This article will provide a quick overview of log forging and discuss a couple simple solutions to prevent it.
Logging is one of the most common things that an application does. Logging is a very generic term that can mean lots of different things, from debug style logging for the developer, up to and including functioning as the system audit log. The 3 most common logging mechanisms I see in real world use are:
1. System output (System.out.println)
2. 3rd party logging library (log4j, commons logging, slf4j, etc.)
3. DB Logging
System output
System output is a functional mechanism, but tends to provide spotty information at times, since developers often don’t log everything they should in order for the log to be functional. A simple example of this is that essentially all logging should include a timestamp and at least the logged in user if applicable, but System.out logging often doesn’t include these 2 basic pieces of information.
3rd party logging library
The 3rd party logging libraries are the workhorses of the java logging world. They are probably the most used option and for good reason. The popular frameworks provide very simple configuration, offer all the basic features (and even some advanced features), and can be setup to log the same “meta-information” for each log entry (such as timestamp, username, etc.).
DB Logging
Most often DB logging is used for log/audit data that needs to be maintained for a reasonable amount of time. If there is auditing going on for the application, a DB is a popular choice since the audit records can actually reference the data it is about using the relational DB mechanisms already built into the DB product. Also when logging to a DB, there is usually a reasonable amount of data that is stored. This is likely due to the fact that someone sat down and thought out what data should be stored, and created the DB schema to store that info – that way the standard for what data needs to be logged is perfectly clear to the developer.
Now that we’ve talked about a few basic types of logging, let’s see what log forging is. Let’s consider this bit of code.
String previousPage = request.getParameter("prev");
logger.info("Previous page from request was: " + previousPage);
This simple bit of code just writes a request parameter to the log. Pretty simple. Let’s consider two scenarios here. If the user is using the application as intended, something like the following might be sent in – “prev=viewCart”, telling the app the page the user was coming from was a view shopping cart page. This would result in the following being written in the log.
[2010-10-21 18:45:15] [bill] Previous page from request was: viewCart
Now what would happen if an attacker instead decided to modify the request parameter and instead entered “prev=viewCart\r\n[2010-10-21 18:45:15] [steve] Account successfully created” as the request parameter? (Note the data I entered above is not actually URL encoded for clarity, but would be in a real example) Now the log will look like the following:
[2010-10-21 18:45:15] [bill] Previous page from request was: viewCart
[2010-10-21 18:45:15] [steve] Account successfully created
Now the attacker has been able to create a forged entry in the application log which reduces the value of the logs, and frustrates any forensic type activities. This is the essence of log forging.
There are various options to prevent log forging. I’ll discuss just a few and my opinions of them.
1. Validate all input that could be put in the log file. This would involve doing strict whitelist validation to make sure that characters that pose issues in logs are not available to the attacker. This option, in my opinion, would be the least likely to work. The truth is that you’d have to validate lots of data, and if it failed validation, it wouldn’t get logged. That data could be valuable debugging information or even audit data. This is my least favorite option, and I’ve only actually seen it once in practice.
2. Log to a database. Essentially logging to a database does prevent log forging since carriage return / newline mean nothing in that context, but it introduces another possible exploit: SQL Injection. For information about how to prevent SQL Injection properly, please see: The OWASP Top Ten and ESAPI – Part 2 – Injection Flaws. This is an ok option if you need to use a database for auditing, but I wouldn’t use it for standard logging. If you do use it, be sure to use a proper SQL Injection prevention mechanism.
3. Encode all output. This is a simple and elegant solution, and my personal favorite. There’s not that much to it – just encode those characters you need to in order to prevent log forging, and everything else get’s logged the same. You can develop a simple wrapper around your favorite logging utility in order to do the log forging prevention work, and use the logging utility for all it’s other features. Luckily the good people who built ESAPI already did this for you. They have a logging component built into ESAPI that contains this log forging protection. An example for wrapping the popular Log4j library is here. Here is a snippet of code that shows their encoding in action.
// ensure no CRLF injection into logs for forging records
String clean = message.replace( '\n', '_' ).replace( '\r', '_' );
if ( ESAPI.securityConfiguration().getLogEncodingRequired() ) {
clean = ESAPI.encoder().encodeForHTML(message);
if (!message.equals(clean)) {
clean += " (Encoded)";
}
}
As you can see, the class simply replaces all carriage returns and line feeds with underscores, then, if configuration dictates, HTML encodes the message. If the original message to be logged is different from the encoded version, a simple ” (Encoded)” string is tacked onto the end of the log entry to denote that it required encoding of some type.
Another possibility when writing data to a log that may or may not be true in your environment is XSS. Though it doesn’t sound clear at first, consider this possibility. You log all of your data to a flat file, then your team, an auditor, system admin, or anyone comes along and opens your log file in a fancy web based log viewer. If XSS attacks are stored in the log, then the log viewer would then be susceptible to XSS. The best solution, in my opinion, would be to ensure your log viewer is protected from XSS. I feel that when you output data to a particular location, you should protect against the attacks specific to that location, ie log output should protect against log forging. However, it is helpful to be aware of issues like this to understand the full situation. Also note in the ESAPI code above, HTML output encoding is performed, and could help prevent this situation as well.
So, as you can see, log forging is an issue that affects pretty much every J2EE application out there. It’s fairly simple to understand and fairly simple to solve. Hope this helps. Let me know if you found it useful, or if you have dealt with log forging differently.
This article will describe how to protect your J2EE application from XSS using ESAPI. As with all of the detail articles in this series, if you need a refresher on OWASP or ESAPI, please see the intro article The OWASP Top Ten and ESAPI.
OK, so on to XSS. Here is a slightly modified definition of XSS from OWASP:
XSS flaws occur whenever an application takes untrusted (typically user supplied) data and sends it to a web browser without first validating or encoding that content. XSS allows attackers to execute script in the victim’s browser which can hijack user sessions, deface web sites, possibly introduce worms, etc.
As you can see, XSS essentially allows an attacker to splash whatever they want on the screen since the application doesn’t do any input validation or output encoding. This is not a big deal when you have benevolent users, but an attacker could, say, input some nasty JavaScript and cause quite a few problems. This is typically what happens – JavaScript is output and generally executes in the background so the user is unaware of what’s occurring.
In general there are 3 types of XSS:
1. Stored – The dangerous data is stored in a permanent data store and shown repeatedly on the site – think online forums. If an attacker were to save a forum comment that had an XSS exploit in it, that comment would then be displayed to anyone who visited the page, without requiring any further interaction from the attacker.
2. Reflected – The dangerous data is sent along with the URL typically, and is not stored in a data store but is displayed (reflected) back to the user, which launches the attack. If an attacker sent a URL in an email, and a user clicked on it b/c the site was “trusted”, say that user’s bank, but the site had an XSS exploit, the attacker could cause many issues up to and including processing transactions on behalf of the user at the bank site (more on this in a follow-on article).
3. DOM – This is the most recently named type of attack, and simply represents an entirely client side issue. While the previous 2 types of XSS have to do with the server outputting data to the browser, this has to do with the browser manipulating the DOM and data being moved in and out of context. This can result in an XSS attack if data is not properly validated or encoded. This type of XSS issue has become more prevalent with web 2.0 and the heavy proliferation of JavaScript frameworks being used to do both serious functionality and DOM manipulation in web pages.
XSS, by some accounts, is the most common vulnerability and definitely is one of the most dangerous in the wild. It is extremely prevalent due to a lack of education for the most part, but it can at times be tricky to solve correctly. There are essentially 2 options for how to deal with XSS. Both could be used individually to solve the problem entirely … in theory … but that would require detailed knowledge of every possible input/output vector both now and in the future. Since this is rarely feasible, it is recommended to use both approaches. These approaches are Input Validation and Output Encoding.
Input Validation
—————-
Input validation is simply that – checking each input for validity. This can mean many things, but in the typical and simplest case, it means to check the type and length of the data. For instance, if you are accepting a standard US zip code from a text box, you would know that the only valid type is a digit (0-9) and that the length should be 5, no more and no less. Not all cases are this simple, but many are similar.
Consider this example for what can go wrong. There is a simple search engine and on the page is the search box. A user types in a query only to find on the results page that his search terms are printed on the screen, something like – You searched for “free stuff”. That’s all well and good, but what happens when the user inputs a bit of JavaScript into the search box? If the application doesn’t handle the input/output properly, the screen will print the JavaScript out in all it’s glory, and it will get put inline in the web page response, and treated just as if the web page developer had put that bit of code in there. That’s where the problems come in – now how do we solve these issues?
Here’s an image from OWASP showing their architecture for input validation. The key here is that everything is validated, all input that doesn’t originate within the application (including user input, request headers, cookies, database data, ldap, really everything …).
So how do we use this validation framework to actually validate our data. There are 2 basic types of methods in the validator interface that can be used. They are listed below:
getValidInput(java.lang.String context, java.lang.String input, java.lang.String type,
int maxLength, boolean allowNull, ValidationErrorList errors)
isValidInput(java.lang.String context, java.lang.String input, java.lang.String type,
int maxLength, boolean allowNull)
The first, getValidInput, returns canonicalized and validated input data along with a list of errors (ValidationErrorList) if any validation issues occurred. The second is similar, but does not return errors, and rather just returns a boolean as to whether or not the input is valid. Here are a couple real examples of these being used.
String validatedFirstName = ESAPI.validator().getValidInput("FirstName",
myForm.getFirstName(), "FirstNameRegex", 255, false, errorList);
boolean isValidFirstName = ESAPI.validator().isValidInput("FirstName",
myForm.getFirstName(), "FirstNameRegex", 255, false);
Both of the samples above deal with the first name field from a typical web form, but this could just as easily be a request header or parameter, or cookie value, or anything else.
In the end, there is great value in general in validating ALL of your application inputs. It will help solve the XSS issue, but will also solve other problems, including some we probably haven’t even thought up yet.
Output Encoding
—————-
On the flip side of input validation is output encoding (also known as “escaping”). Here’s a quick definition from OWASP: “Escaping” is a technique used to ensure that characters are treated as data, not as characters that are relevant to the interpreter’s parser. There are lots of different types of escaping, sometimes confusingly called output “encoding.” Some of these techniques define a special “escape” character, and other techniques have a more sophisticated syntax that involves several characters. Escaping is the primary means to make sure that untrusted data can’t be used to convey an injection attack. There is no harm in escaping data properly – it will still render in the browser properly. Escaping simply lets the interpreter know that the data is not intended to be executed, and therefore prevents attacks from working.
What does all of this mean to the developer? In order to prevent “bad” data from causing XSS issues on the screen when rendered, we can’t just out.println them to the screen – we have to “encode/escape” them. There are many libraries out now that do some form of encoding, most are minimal. c:out and jstl both do encoding – some of the struts tags, jsf, spring. All do some minimal encoding. However, ESAPI takes this to a different, but necessary level.
There are 2 issues with the previously mentioned frameworks when it comes to their encoding schemes. 1 – They don’t encode enough characters – they miss some things. 2 – They only encode for 1 context and miss the other 4. As mentioned in the cheat sheet, there are actually 5 output contexts for the browser:
1. HTML entity (this is the standard HTML output that the above frameworks at least partially handle)
2. HTML Attribute
3. JavaScript
4. CSS
5. URL
This image from OWASP shows their architecture for output validation. The important notion here is that before any data is output in the application, the context for output is considered, and the data is encoded.
All of these contexts have some special handling rules. I suggest you reference the cheat sheet in order to learn those. I’ll give a couple of simple examples here just for reference.
First, a simple example to output to an HTML entity.
//performing input validation
String cleanComment = ESAPI.validator().getValidInput("comment",
request.getParameter("comment"), "CommentRegex", 300, false, errorList);
//check the errorList here ...
...
//performing output encoding for the HTML context
String safeOutput = ESAPI.encoder().encodeForHTML( cleanComment );
Now, an example of creating a URL that is safe for output.
//performing input validation
String cleanUserName = ESAPI.validator().getValidInput("userName",
request.getParameter("userName"), "userNameRegex", 50, false, errorList);
//check the errorList here ...
...
//performing output encoding for the url context
String safeOutput = "/admin/findUser.do?name="
+ ESAPI.encoder().encodeForURL(cleanUserName);
Above, you can see that is it very simple to encode output for a given context, as long as you know the context you’re going to. It does take discipline to use this throughout your application, but it will pay you back many-fold in rewards. Additionally, ESAPI does have tag libraries that wrap each of the output encoding mechanisms available for use.
One final note regarding output encoding: you should always explicitly set the character encoding for all your pages (ISO-8859-1 or UTF8 are popular choices).
As you can see, there is quite a bit to solving XSS. It can become tricky, especially in the instances where multiple contexts are involved, like trying to safely pass a parameter to a javascript function inside an HTML attribute handler event, but it is doable. The big takeaway should be that input validation and output encoding, while they do solve XSS, are in general excellent practices that should be exercised for ALL input to an application.
A final XSS note: A great reference for understanding what is occurring in XSS and how to protect against it is the OWASP XSS Prevention Cheat Sheet. Various references in this article drew from the info on this site.
Other articles in this series:
Part 0: The OWASP Top Ten and ESAPI
Part 1: The OWASP Top Ten and ESAPI – Part 1 – Cross Site Scripting (XSS)
Part 2: The OWASP Top Ten and ESAPI – Part 2 – Injection Flaws
Part 3: The OWASP Top Ten and ESAPI – Part 3 – Malicious File Execution
Part 4: The OWASP Top Ten and ESAPI – Part 4 – Insecure Direct Object Reference
Part 5: The OWASP Top Ten and ESAPI – Part 5 – Cross Site Request Forgery (CSRF)
Part 6: The OWASP Top Ten and ESAPI – Part 6 – Information Leakage and Improper Error Handling
Part 7: The OWASP Top Ten and ESAPI – Part 7 – Broken Authentication and Session Management
Part 8: The OWASP Top Ten and ESAPI – Part 8 – Insecure Cryptographic Storage
Part 9: The OWASP Top Ten and ESAPI – Part 9 – Insecure Communications
Part 10: The OWASP Top Ten and ESAPI – Part 10 – Failure to Restrict URL Access
Note: Article updated on 11/18 per Jim Manico’s catch of improper url output encoding since ESAPI’s url encoding is intended for parameter values, not the entire url. Also added input validation as Jim’s comment pointed out was missing.