Is URLEncoder.encode(string, "UTF-8") a poor validation? - java

In a portion of my J2EE/java code, I do a URLEncoding on the output of getRequestURI() to sanitize it to prevent XSS attacks, but Fortify SCA considers that poor validation.
Why?

The key point is that you need to convert HTML special characters to HTML entities. This is also called "HTML escaping" or "XML escaping". Basically, the characters <, >, ", & and ' needs to be replaced by <, >, ", & and '.
URL encoding does not do that. URL encoding converts URL special characters to percent-encoded values. This is not HTML escaping.
In case of web applications, HTML escaping is normally to be done in the view side, exactly there where you're redisplaying user-controlled input. In case of a Java EE web applications, that depends on the view technology you're using.
If the webapp is using modern Facelets view technology, then you don't need to escape it yourself. Facelets will already implicitly do that.
If the webapp is using legacy JSP view technology, then you need to ensure that you're using JSTL <c:out> tag or fn:escapeXml() function to redisplay user-controlled input.
<c:out value="${bean.foo}" />
<input type="text" name="foo" value="${fn:escapeXml(param.foo)}" />
If the webapp is very legacy or bad designed and using servlets or scriptlets to print HTML, then you've a bigger problem. There are no builtin tags or functions, let alone Java methods which can escape HTML entities. You should either write some escape() method yourself or use the Apache Commons Lang StringEscapeUtils#escapeHtml() for this. Then you need to ensure that you're using it everywhere you're printing user-controlled input.
out.print("<p>" + StringEscapeUtils.escapeHtml(request.getParameter("foo")) + "</p>");
Much better would be to redesign that legacy webapp to use JSP with JSTL.

URL encoding does not affect certain significant characters including single quote (') and parentheses, so URL encoding will pass through unchanged certain payloads.
For example,
onload'alert(String.fromCharCode(120))'
will be treated by some browsers as a valid attribute that can result in code execution when injected inside a tag.
The best way to avoid XSS is to treat all untrusted inputs as plain text, and then when composing your output, properly encode all plain text to the appropriate type on output.
If you want to filter inputs as an additional layer of security, make sure your filter treats all quotes (including back-tick) and parentheses as possible code, and disallow them unless the make sense for that input.

Related

Preventing xss attack in java web app while saving actual values in database

In a Recent scan of our java based web application through AppScan it was found that the application was prone to XSS attacks.
I did my research and found that a ServletFilter was probably the easiest way to protect the application.
I introduced the filter where I extended HttpServletRequestWrapper (because java does not allow request param to be changed, there is no request.setParam method). I introduced a sanitize method there and here is what it does
result = ESAPI.encoder().canonicalize( input);
// Avoid null characters
result = result.replaceAll("\0", "");
// Clean out HTML
result = Jsoup.clean( result, Whitelist.none() );
Post this change, it was good, I tested for XSS vulnerabilites myself and most of them were fixed. But this posed another problem. Suppose I have a form to create a product, and in product name a user enters something like
<script>alert('somethingStupid')</script>
Now Ideally I should be able to save this to database, but still be protected from XSS attack. Not sure what to do in my filter or anywhere else to achieve this.
HTML-injection is an output-stage issue, caused by forgetting to encode text when injecting it into a context where characters are special. ESAPI offers encoders for various contexts, as discussed by #Zakaria. If you use these consistently, each in the correct context, you have fixed injection-related XSS issues.
If you are using purely JSTL tags like <c:out> for your templating, these will also HTML-escape by default. In general, it is best to generate HTML using a templating system that works HTML-escaping out for you automatically, because otherwise you are likely to forget to manually encodeForHTML occasionally.
(Aside: on project where I am compelled to use the mostly-terrible owasp-esapi-java library, my preference is for encodeForXML over the HTML encoders, as it produces output that is safe for HTML content and quoted attribute values whilst not needlessly attempting to produce entity references for non-ASCII characters. I would typically try to avoid injecting into JavaScript string literals; it is typically easier and more maintainable to inject run-time content into HTML data- attributes and read them from separate JavaScript DOM code.)
Trying to filter out HTML at the input stage is a lamentably still-popular but completely misguided approach. It prevents you from entering HTML-like input when you need to—as you have found out, with the <script> example. Indeed, if StackOverflow used such an input filter we would not be able to have this conversation.
What's more, it's not resilient: there are many ways to smuggle potential injections past input filters. To make a filter effective you'd have to consider blocking pretty much all punctuation, which is generally not considered acceptable. Plus, any data that gets into your application by means other than request parameters won't be vetted.
Input validation is great for enforcing business rules on the formats of particular input fields, and can be used to filter out input that you never want, like control characters. But it's the wrong place to be worrying about escaping or removing HTML. The time to do that is when you're creating HTML.
Cross Site Scripting (XSS) is a security issue which occurs when there is no mechanism of validating user input so the result will be an exploitable javascript code generally.
3 types of XSS are known : Reflexive XSS, DOM-based XSS and Persistant XSS.
In your case and since you're using OWASP ESAPI, canonicalizing inputs is not enough, sure it's a good way to defense against Untrusted URL in a SRC or HREF attribute but it's not enough.
You should Follow thess Rules : Source ( XSS (Cross Site Scripting) Prevention Cheat Sheet of OWASP ) (here are some rules for further reading follow the link) :
1- HTML Escape Before Inserting Untrusted Data into HTML Element Content: see the example :
String safe = ESAPI.encoder().encodeForHTML( request.getParameter( "input" ) );
2- Attribute Escape Before Inserting Untrusted Data into HTML Common Attributes :
String safe = ESAPI.encoder().encodeForHTMLAttribute( request.getParameter( "input" ) );
3- JavaScript Escape Before Inserting Untrusted Data into JavaScript Data Values:
String safe = ESAPI.encoder().encodeForJavaScript( request.getParameter( "input" ) );

How to replace smilies in text such as :) with an image?

I would like to show smilies as images in my JSF/PrimeFaces web application. For this I would need to replace text like :) with an image. How can I achieve this?
JSF doesn't offer any facilities for this.
At its simplest, you could just use the available methods of the String class to perform manipulations on a String instance, such as replace().
text = text.replace(":)", "<img src=\"smile.png\" />");
(you might want to apply more finer-grained matching, perhaps with regex or a lexer, to prevent that legit character sequences such as "... a semicolon ; (or a colon, :) ..." are incorrectly been replaced)
Then, to present the manipulated String instance with HTML images in it in JSF, you'd need to use <h:outputText> with the escape attribute set to false to disable the builtin HTML-escaping which is been used to prevent XSS attack holes.
<h:outputText value="#{bean.text}" escape="false" />
This way the HTML <img> element will be literally interpreted by the webbrowser instead of being displayed plaintext to the enduser due to the escaping.
But, as you might already have guessed, this puts of course possible XSS attack holes open if you don't sanitize the enduser's input beforehand. The enduser would be able to do bad things with input such as adding a <script>stealCookies()</script> to the text which would be literally interpreted by the webbrowser as well. To sanitize enduser's input beforehand, you can use among others Jsoup which offers a clean() method for this:
text = Jsoup.clean(text, Whitelist.basic());
(do this before replacing the smilies, or it might strip off those <img> tags as well!)

How to escape JavaScript in an HTML String while keeping the HTML unescaped?

We have a webapplication. At some points there is a JavaScript based WSIWYG / RichText Editor. It filters some JavaScript but uses HTML text to format it's content.
Unfortunately it does not filter all JavaScript. I was able to proof a XSS attack with an event handler. I think the JavaScript client side filtering of JavaScript is not safe at all, because at client side it can be manipulated.
So I would like to filter or escape JavaScript at the server side. I had a short look at ESAPI for Java. But we have a requirement, I don't know if it is special or a problem:
The HTML elements the editor uses should not be filtered or escaped, only JavaScript. The HTML should be ordinary rendered in the browser.
Is there a safe way, to escapce or filter JavaScript while keeping the HTML like it is?
Does ESAPI or any other API help me doing this?
How do I do it.
Thanks in advance.
It is difficult to state what escaping schemes have to be used to escape JavaScript without knowing whether the application is vulnerable to DOM-based XSS attacks or the run-of-the-mill (reflected and persistent) XSS attacks.
ESAPI for Java will help in both cases though. In the case of DOM-based XSS attacks, you would need to encode the unsafe data multiple times (and using different encoding schemes if necessary) to ensure that each parser in the parsing chain will not be subject to XSS attacks. In the case of reflected or persistent XSS attacks, you'll usually need to apply the escaping only once, in the appropriate context.
It should be kept in mind that, allowing raw HTML on its own is also unsafe, resulting in XSS. You might want to take a look at a different approach to sanitizing inputs; using AntiSamy for filtering HTML might be warranted in this case.
You need to parse the HTML and reject any tags and attributes that aren't in a strict whitelist of safe tags/attributes.
The whitelist would not include tags like <script>, <style>, or <link>, and it wouldn't include attributes like onclick, onload, or style.
You should also make sure that href and src attributes use the http or https protocols (or a relative path), and not javascript:.

Struts 2 encode input parameters to avoid XSS

I have an application built with Struts 2. It has some issues with Cross-site scripting (XSS) attacks. I want to encode some of the actions input parameters in a similar fashion to JSP <c:out value="${somevalue}"/> Is there any easy approach to do this in Struts 2? Java API method would do fine.
EDIT I found this one - http://www.owasp.org/index.php/Talk:How_to_perform_HTML_entity_encoding_in_Java
Any experience with it?
You can use
<%# taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
${fn:escapeXml(someValue)}
There is also a Good API JSoup
Sanitize untrusted HTML
Problem
You want to allow untrusted users to supply HTML for output on your website (e.g. as comment submission). You need to clean this HTML to avoid cross-site scripting (XSS) attacks.
Solution
Use the jsoup HTML Cleaner with a configuration specified by a Whitelist.
String unsafe =
"<p><a href='http://example.com/' onclick='stealCookies()'>Link</a></p>";
String safe = Jsoup.clean(unsafe, Whitelist.basic());
// now: <p>Link</p>
So, all you basically need to do is the the following during processing the submitted text:
String text = request.getParameter("text");
String safe = Jsoup.clean(text, Whitelist.basic());
// Persist 'safe' in DB instead.
There is struts2securityaddons
This project contains additional configuration, interceptors, and other code used to improve the security of struts 2 applications.
See also
XSS Prevention oin Java
Prevent jsp from XSS
struts2securityaddons
Escaping input parameters as an XSS prevention mean has several disadvanteges, especially:
You can't be certain about destination of the particular input data, therefore you can't choose proper escaping scheme.
Escaping input data masks lack of output escaping. Without consistent output escaping, you can still pass unescaped data to the unescaped output accidentially.
Presence of escaping complicates data processing.
Therefor it would be better to apply consistent output escaping instead.
See also:
OWASP XSS Prevention Cheat Sheet
There is no easy, out of the box solution against XSS with struts 2 tags. The OWASP ESAPI API has some support for the escaping that is very usefull, and they have tag libraries.
My approach was to basically to extend the stuts 2 tags in following ways.
Modify s:property tag so it can take extra attributes stating what sort of escaping is required (escapeHtmlAttribute="true" etc.). This involves creating a new Property and PropertyTag classes. The Property class uses OWASP ESAPI api for the escaping.
Change freemarker templates to use the new version of s:property and set the escaping.
If you didn't want to modify the classes in step 1, another approach would be to import the ESAPI tags into the freemarker templates and escape as needed. Then if you need to use a s:property tag in your JSP, wrap it with and ESAPI tag.
I have written a more detailed explanation here.
http://www.nutshellsoftware.org/software/securing-struts-2-using-esapi-part-1-securing-outputs/
I agree escaping inputs is not ideal.

HttpServletRequest - Quick way to encode url and hidden field paramaters

In my java app I'm preventing XSS attacks. I want to encode URL and hidden field paramaters in the HttpServletRequest objects I have a handle on.
How would I go about doing this?
Don't do that. You're making it unnecessarily more complicated. Just escape it during display only. See my answer in your other topic: Java 5 HTML escaping To Prevent XSS
To properly display user-entered data on an HTML page, you simply need to ensure that any special HTML characters are properly encoded as entities, via String#replace or similar. The good news is that there is very little you need to encode (for this purpose):
str = str.replace("&", "&").replace("<", "<");
You can also replace > if you like, but there's no need to.
This isn't only because of XSS, but also just so that characters show up properly. You may also want to handle ensuring that characters outside the common latin set are turned into appropriate entities, to protect against charset issues (UTF-8 vs. Windows-1252, etc.).
You can use StringEscapeUtils from the library Apache Jakarta Commons Lang
http://www.jdocs.com/lang/2.1/org/apache/commons/lang/StringEscapeUtils.html

Categories

Resources