Cross Site Scripting (JSON)
Cross site scripting (or XSS) is #2 on the 2010 OWASP Top Ten web security risks and it pops up nearly everywhere.
XSS occurs when a user-manipulatable value is displayed on a web page without escaping it, allowing someone to inject Javascript or HTML into the page. Calls to Hash#to_json
can be used to trigger XSS. Brakeman will check to see if there are any calls to Hash#to_json
with ActiveSupport#escape_html_entities_in_json
set to false (or if you are running Rails < 2.1.0 which did not have this functionality).
ActiveSupport#escape_html_entities_in_json
was introduced in the “new_rails_defaults” initializer in Rails 2.1.0 which is set to false
by default. In Rails 3.0.0, true
became the default setting. Setting this value to true
will automatically escape ‘<’, ‘>’, ‘&’ which are commonly used to break out of code generated by a to_json call.
See ActiveSupport#escape_html_entities_in_json for more details.
Exploiting to_json
Consider the following snippet of Rails 2.x ERB:
# controller
@attrs = {:email => '[email protected]</script><script>alert(document.domain)//'}
<!-- view -->
<script>
var attributes = <%= @attrs.to_json %>
</script>
Which generates the following html:
<script>
var attributes = {"email":"[email protected]</script><script>alert(document.domain)//"}
</script>
While the generated Javascript appears valid, the browser parses the script tags first, so it sees something like this:
<script>
var attributes = {"email":"[email protected]
</script>
<script>
alert(document.domain)//"}
</script>
The attribute assignment causes a Javascript error, but the alert triggers just fine!
With escape_html_entities_in_json = true
, you will receive the following innocuous output:
<script>
var attributes = {"email":"[email protected]\u003C/script\u003E\u003Cscript\u003Ealert(document.domain)//"}
</script>
Back to Warning Types