XSS in Rails' JSON - ruby-on-rails

I'm rendering content using Backbone in Rails. Some of the json properties i'm getting from the models will be html attributes, some of them might be used inside the javascript and others will be inserted between html elements. All of these require different escaping mechanisms, how do people deal with this?

In our project we are using doT templates which (as most other) allow for interpolation with encoding ({{! ... }}). You could also try to encode all data and strip any possible javascripts server side when data is saved to be 100% sure you won't get anything malicious
Additionally if you are using jquery methods remember to use text method to insert data rather then html as text will automatically encode it.
And I really recommend the doT! It's super fast and we've managed to make it play really nicely with requirejs

Related

When do I need to encode with multiple codecs in Grails?

I'm not clear of when (or if) I should use multiple Grails encodeAsXXX calls.
This reference says you need to encodeAsURL and then encodeAsJavaScript: http://grailsrocks.com/blog/2013/4/19/can-i-pwn-your-grails-application
It also says you need to encodeAsURL and then encodeAsHTML, I don't understand why this is necessary in the case shown but not all the time?
Are there other cases I should me using multiple chained encoders?
If I'm rendering a URL to a HTML attribute should I encodeAsURL then encodeAsHTML?
If I'm rendering a URL to a JavaScript variable sent as part of a HTML document (via a SCRIPT element) should I encodeAsURL, encodeAsJavaScript then encodeAsHTML?
If I'm rendering a string to a JavaScript variable sent as part of a HTML document should I encodeAsJavaScript then encodeAsHTML?
The official docs - https://docs.grails.org/latest/guide/security.html - don't show any examples of multiple chained encoders.
I can't see how I can understand what to do here except by finding the source for all the encoders and looking at what they encode and what's valid on the receiving end - but I figure it shouldn't be that hard for a developer and there is probably something simple I'm missing or some instructions I haven't found.
FWIW, I think the encoders I'm talking about are these ones:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/JavaScriptUtils.html#javaScriptEscape-java.lang.String-
https://docs.oracle.com/javase/7/docs/api/java/net/URLEncoder.html#encode(java.lang.String,%20java.lang.String)
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/util/HtmlUtils.html#htmlEscape-java.lang.String-
.
It is certainly important to always consider XSS but in reading your question I think you are overestimating what you need to do. As long as you're using Grails 2.3 or higher and your grails.views.default.codec is set to html which it will be by default, everything rendered in your GSP with ${} will be escaped properly for you.
It is only when you are intentionally bypassing the escaping, such as if you need to get sanitized user input back into valid JavaScript within your GSP for some reason, that you would need to use the encodeAsXXX methods or similar.
I would argue (and the article makes a mention of this as well) that this should raise a smell anyway, as you probably should have that JavaScript encapsulated in a different file or TagLib where the escaping is handled.
Bottom line, use the encoding methods only if you are overriding the default HTML encoding, otherwise ${} handles it for you.

Is data.to_json.html_safe susceptible to XSS attack?

I'm trying to figure out if this code is safe.
Is it at all possible to attack this code?
<script>
data = <%= data.to_json.html_safe %>;
</script>
In other words, what value of data would result in a successful attack?
It kind of depends on what you are doing with the data and the version of Rails you are using. If you are using anything past Rails 3 then no, calling html_safe could make your code vulnerable to XSS.
Basically, what you are doing is telling the app that data.to_json is html safe. However, the application doesn't actually know that for sure.
What html_safe does is it marks a string as safe to be inserted directly into HTML without escaping anything within the string. As described in the method api, it should never be used on user input. Constructed input may be safe, but it is up to you to ensure that it is.
to_json converts a given string into JSON. By default, it does not escape HTML characters like <, / >
Thus, if data is user input, it is entirely possible for someone to insert their own script into it and have it marked as safe (and thus rendered as html) the way it is currently written.
The way this is written, if someone does the following:
data = "</script><script>insert_xss_attack_here</script>"
Your code will not escape the script, resulting in the script being executed by the code.
Many people have described the issues with html_safe and to_json:
This deals specifically with to_json.html_safe
http://jfire.io/blog/2012/04/30/how-to-securely-bootstrap-json-in-a-rails-view/
https://bibwild.wordpress.com/2013/12/19/you-never-want-to-call-html_safe-in-a-rails-template/
http://makandracards.com/makandra/2579-everything-you-know-about-html_safe-is-wrong

How to keep attributes with parseFragment in Firefox extension

In Firefox extension we use parseFragment (documentation) to parse a string of HTML (received from 3rd party server) into a sanitized DocumentFragment as it required by Mozilla. The only problem, the parser removes all attributes we need, for example, class attribute.
Is it possible somehow to keep class attributes while parsing HTML with parseFragment?
P.S. I know that in Gecko 14.0 they replaced this function with another which supports sanitizing parameters. But what to do with Gecko < 14.0?
No, the whitelist is hardcoded and cannot be adjusted. However, the class attribute is in the whitelist and should be kept, you probably meant the style attribute? If you need a customized behavior you will have to use a different solution (like DOMParser which can parse HTML documents in Firefox 12).
As to older Firefox versions, you can parse XHTML data with DOMParser there. If you really have HTML then I am only aware of one way to parse it without immediately inserting it into a document (which might cause various security issues): range.createContextualFragment(). You need an HTML document for that, if you don't have one - a hidden <iframe> loading about:blank will do as well. Here is how it works:
// Get the HTML document
var doc = document.getElementById("dummyFrame").contentDocument;
// Parse data
var fragment = doc.createRange().createContextualFragment(htmlData);
// Sanitize it
sanitizeData(fragment);
Here sanitizing the data is your own responsibility. You probably want to base your sanitization on Mozilla's whitelist that I linked to above - remove all tags and attributes that are not on that list, also make sure to check the links. The style attribute is a special case: it used to be insecure but IMHO no longer is given than -moz-binding isn't supported on the web any more.

Testing "HTML fixtures" with RSpec and rails

I have a web scraper built to parse html from a website and I'm trying to write tests for it.
The class I'm trying to test receives a Nokogiri HTML object and extracts the required data from it. Now as usual the html can vary, sometimes elements will be missing or whatnot. I need to test these different situations.
So what I'd like to do is make a bunch of html files, each one representing a case with a particular element missing etc. For each html file, I wish to also construct an associated hash of the data I would expect the scraper to extract, assuming it is working correctly.
So I would like to write a test which will iterate over these html files and compare the data extracted by the class being tested against the expected data and report whether or not it is correct.
Any suggestions as to how to do this?
Have a look at the Artifice, fakeweb or webmock gems, which override net/http in order to supply testable results.

How good is the Rails sanitize() method?

Can I use ActionView::Helpers::SanitizeHelper#sanitize on user-entered text that I plan on showing to other users? E.g., will it properly handle all cases described on this site?
Also, the documentation mentions:
Please note that sanitizing
user-provided text does not guarantee
that the resulting markup is valid
(conforming to a document type) or
even well-formed. The output may still
contain e.g. unescaped ’<’, ’>’, ’&’
characters and confuse browsers.
What's the best way to handle this? Pass the sanitized text through Hpricot before displaying?
Ryan Grove's Sanitize goes a lot farther than Rails 3 sanitize. It ensures the output HTML is well-formed and has three built-in whitelists:
Sanitize::Config::RESTRICTED
Allows only very simple inline formatting markup. No links, images, or block elements.
Sanitize::Config::BASIC
Allows a variety of markup including formatting tags, links, and lists. Images and tables are not allowed, links are limited to FTP, HTTP, HTTPS, and mailto protocols, and a attribute is added to all links to mitigate SEO spam.
Sanitize::Config::RELAXED Allows an even wider variety of markup than BASIC, including images and tables. Links are still limited to FTP, HTTP, HTTPS, and mailto protocols, while images are limited to HTTP and HTTPS. In this mode, is not added to links.
Sanitize is certainly better than the "h" helper. Instead of escaping everything, it actually allows the html tags that you specify. And yes, it does prevent cross-site scripting because it removes javascript from the mix entirely.
In short, both will get the job done. Use "h" when you don't expect anything other than plaintext, and use sanitize when you want to allow some, or you believe people may try to enter it. Even if you disallow all tags with sanitize, it'll "pretty up" the code by removing them instead of escaping them as "h" does.
As for incomplete tags: You could run a validation on the model that passes html-containing fields through hpricot, but I think this is overkill in most applications.
The best course of action depends on two things:
Your rails version (2.x or 3.x)
Whether your users are supposed to enter any html at all on the input or not.
As a general rule, I don't allow my users to input html - instead I let them input textile.
On rails 3.x:
User input is sanitized by default. You don't have to do anything, unless you want your users to be able to send some html. In that case, keep reading.
This railscast deals with XSS attacks on rails 3.
On rails 2.x:
If you don't allow any html from your users, just protect your output with the h method, like this:
<%= h post.text %>
If you want your users to send some html: you can use rails' sanitize method or HTML::StathamSanitizer

Resources