October 24, 2006 - 14:27 UTC - Tags: Ruby rails XSS sql injection security
Ruby on rails (RoR) is rapidly gaining popularity as a platform for developing web applications. However most tutorials teach you to write highly unsecure code that will allow attackers to exploit your applications. This is especially true for XSS (Cross Site Scripting).
The meta character problemAs you should know by now, both SQL injection and XSS are metacharacter problems where input from users or other applicatoins makes the application behave in unexpected ways. And the solution to metacharacter problems is of course to:
- Create a list of all metacharacters of the system you are communicating with (browser or SQL database)
- Escape them
The creators of RoR have of course thought about this, and provide methods for escaping the metacharacters.
Cross Site ScriptingIn most of the RoR tutorials I have read, I see code like this:
<%= blogpost.body %>
The text in blog.body is written to the web page without any escaping, and writing unescaped strings to web pages are the cause of XSS. While writing unescaped data to a web page may be ok when you know the origin of the data, writing unescaped data from an uknown origin should never be allowed in your web application. Blogs often contain the ability to comment on the posts, and unfortunately the code in the tutorials often looks like this:
<%= comment.body %>
As I mentioned RoR contains methods for escaping metacharacters. To HTML escape data in RoR simply add an "h" inside you output tag:
<%=h comment.body %>
This h function replaces all ">" with ">" and reverse for "<".
I wish though, that the creators of RoR would have done this the other way around. <%= %> should always be escaped, while some function like "u" (unescape) would unescape data when needed (<%u blogpost.body %>). This would first of all secure applications using scaffolding and would also create secure code by default. If you wanted to write unescaped ouput to the browser you would have to explicitly state that this is what you want.
But for now, get used to writing "<%=h %>" instead of just "<%= %>".
Avoiding SQL injectionRoR allows the use of prepared statements (or at least something that looks like prepared statements) which you can use to avoid SQL injection problems. The syntax is:
Blog.find_all [ "category = ?", category ]
As you can see, you simply put the a question mark where you want the parameters to be inserted just like when using prepared statements in say Java. You then specify the parameters as a comma separated list after the query. Neat stuff.
More informationIf you want more information on these topics, make sure you read the
About "Securing your Rails application" on rubyonrails.com