The security of Ruby on Rails
At IADA we often use the Ruby on Rails web framework for developing the more complex web applications. Ruby on Rails, like any other web framework, eases the development of these applications, usually by proving many common functionalities that developers can directly put to use. Part of these functionalities are security functionalities that help protect the application against common web attacks, such as SQL injections and Cross Site Scripting (XSS) vulnerabilities. However, a question that now arises is whether these web frameworks and the protection mechanisms they offer are secure themselves. Web developers trust the frameworks to secure their applications, so it is important that they really do so. Otherwise, a vulnerability in a web framework could possibly endanger thousands of web applications at once. To prevent this, I developed a methodology to analyse the security of (arbitrary) web frameworks, as part of my master thesis research. To directly put this new methodology to use, and to try it in practice, I applied it to Ruby on Rails. The results of this were also interesting for IADA, since we often develop in Ruby on Rails and want to be sure that our applications are secure. In this blog post, I will shortly introduce my methodology, discuss the security functionalities that Rails offers and present the results of my security analysis of the Ruby on Rails framework. I assume you have a basic understanding of web development and web security.
At the beginning of my research it appeared there was no satisfying general method to analyse the security of web frameworks yet. Therefore I decided to develop one myself, the idea being that the method can be used to detect vulnerabilities in new framework versions before they are released, rather than detecting and fixing them when it is too late. There basically were three requirements:
- The approach should be (partially) automated. Frameworks are large and complex. Analysing them completely by hand requires much effort.
- It should re-use the (already well-thought) work of others. There are already many tools to analyse the security of web applications. Lets re-use those and apply them to frameworks as well. Why would we re-invent the wheel?
- The method itself should be general, such that in principle it can be applied to any arbitrary framework. It is however allowed to have framework specific steps that need to be taken to apply the method to another framework.
Following these requirements I arrived at a benchmark approach using dynamic web vulnerability scanners to analyse the security of frameworks. This approach uses a set of benchmark applications, written in the target framework, that are then analysed using dynamic web vulnerability scanners. The results of this analysis could indicate a vulnerability in the framework. Whether this really is the case, should be determined by manual verification. Since benchmark applications implemented in the framework are obviously not general (framework independent), the methodology does not include the actual applications, but instead a high-level benchmark design that can be used to implement the applications in any framework. I chose to perform the analysis using two dynamic scanners, Arachni and W3af, but in principle any dynamic scanner could be used.
Security functionalities of Rails
Rails offers many security functionalities that help developers protect their applications against common web vulnerabilities. Some examples of vulnerabilities Rails helps protect against:
- SQL injections
- Cross Site Scripting (XSS)
- Cross Site Request Forgery (CSRF)
- Command Line injection
- Header injection and HTTP response splitting (for the redirect_to method)
- Unvalidated redirects (using the only_path option for the redirect_to method)
- Mass Assignment (a rather Rails specific vulnerability type)
In total there are quite some vulnerabilities Rails helps protect against. It becomes even better, since the protection against the first three vulnerabilities (SQL injections, XSS and CSRF) are applied automatically by Rails (Security by default). This makes developing secure applications fairly easy. It also helps preventing hard-to-detect vulnerabilities that occur because the protection measures are not implemented consistently throughout the application. However, in order for this to work, the security mechanisms themselves should be secure. Unfortunately, history has proven this is not always the case:
Fortunately, these vulnerabilities have already been fixed in the newest version of Rails. The question is whether the current version of Rails is secure. Using my methodology I analysed Rails with respect to SQL injections and XSS vulnerabilities. I chose these two vulnerability types, since they are very common and harmful web vulnerabilities, and also often occurred in Rails in the past.
Results of the Rails analysis
I have implemented Rails benchmark applications for SQL injections as well as XSS vulnerabilities. These implementations follow the benchmark design as outlined in my thesis. The benchmark applications were then analysed with the dynamic scanners Arachni and W3af. The results of these analysis included some false positive results (that were eliminated during the manual verification phase). However, the analysis also showed five vulnerabilities in Ruby on Rails (version 4.0.0), of which three were yet undiscovered. All these vulnerabilities were XSS vulnerabilities caused by view helpers. View helpers are helper methods of Rails that can be used for various output formatting tasks, such as nicely format a piece of text with line breaks and paragraphs (HTML tags <br /> and <p>). The vulnerabilities are:
- The unit option of the number_to_currency helper (announcement)
- The key not found error message of the translate helper (announcement)
- The html_options parameter of the simple_format helper (announcement)
- The units option of the number_to_human helper (announcement)
- The format option of the number_to_currency, number_to_human and number_to_percentage helpers (announcement)
These results could look very alarming. However, these vulnerabilities are actually is not that bad, as they all occurred in specific options of specific helpers. In other words, they were not caused by a general or fundamental problem. Furthermore, most of these options are not likely to be exposed to untrusted input, making exploitation of these vulnerabilities in the wild unlikely. Another important thing to note is that Rails offers a lot of (automatically applied) protection mechanisms, certainly in respect to some other frameworks. If a framework offers more protection mechanisms, then there is also a higher chance that one of them contains a vulnerability.
That my approach found five vulnerabilities is positive for Rails in both ways. It is a reasuring idea that there seems to be only five vulnerabilities in this part of the Rails framework. Finding these vulnerabilities with my approach is also good news for the framework, since the vulnerabilities now all have been reported and fixed for the next version. It is also good to notice that no SQL injections were discovered at all.
To conclude, Rails does quite a good job with respect to security. It offers many protection mechanisms, which are often employed automatically. Regarding the protection mechanisms researched by me, as far as I can tell Rails performs excellent against SQL injections and reasonably well against XSS vulnerabilities. For the latter Rails can still be safely used, but there is some room for improvement.
For more information about my approach I refer to the full version of my thesis, which is available online: A benchmark approach to analyse the security of web frameworks. Here I describe the approach in detail, present the benchmark design, discuss the Rails implementation and present detailed results. I also evaluate the results and the approach, and discuss its strengths and weaknesses.