One of the upcoming Linting Ruby book sections is about automating security checks in Ruby. We never specialized in security in Rails applications, so we didn't feel qualified to give our opinions as general advice on such an important topic.
We decided to conduct thorough research and reach out to people who know better.
The questions were asked by Stanislav Katkov
I ended up working for a company that did penetration testing and security consultancies. They hired me as a Ruby on Rails developer to work on their internal applications. They were always telling me about all the cool things they do and got me infected with all of that.
I wanted to learn more about the world of InfoSec. Unfortunately, I had to leave that company and England, but I took a penetration testing course that they recommended to me.
This course is supposedly one of the hardest out there, it's called Offensive Security Certified Professional or OSCP for short. It's a very hands-on penetration testing course. For the exam, they give you five IP addresses and 48 hours. Your task is to find vulnerabilities, and get root access on all of them, and write a report. And since then, I have been splitting my time between doing development and security work.
I do penetration tests, not only for Ruby on Rails projects. I don't mind the underlying technology actually.
Most of my work is for companies with a requirement of being PCI compliant. Part of that is to have yearly penetration test on their application. For instance if a company works in the financial industry, their customers and partners likely require them to be PCI compliant due to the sensitive data they handle. But I also work for companies getting a test done to just cover their bases.
Assessing infrastructure testing is not really something that I typically do. In fact, I can't remember when I last did it because usually, these tasks are separated in companies. There's the development team which handles the web penetration test - the application's test. Then, there's the operations team, which is responsible for their own security tests and they hire their own consultants.
The most common vulnerability, I believe, is still Cross-Site Scripting(XSS). XSS is very frequent, but often, I find cases where proper configuration via X-XSS-Protection and alike headers prevent full exploitation, even when developers make mistakes. So, vulnerability is there, but nobody can exploit it. I can run the script, but it won't execute - an exception is thrown in the browser console saying you are not allowed to do this. Besides that, authorization issues are the most common ones. When a user can access or do things they shouldn't be permitted.
bundle-audit works same way as other alternatives as far as I know, so relying on that should be enough I think. But if someone hijacks a ruby gem and publishes a version with a malware, nothing can really save you except your own manual due diligence.
I recommend to always cross-check the repository and rubygems for updates when you upgrade a gem. When you get an new version of a gem from rubygems, go to GitHub to search for the same tag. If you can't find that tag on GitHub, you have to ask why is that. When I also always the changelog on GitHub if there is one. I consider it a red flag, if I can't find the tag or a changelog for the version I am getting from rubygems.
No, to be honest, never particularly liked this tool, even before GitHub acquired it. Now, I don't favor GitHub either due to the Microsoft acquisition. I strive to maintain my independence and avoid reliance on a tool unique to GitHub. For instance, with bundle-audit, I can take my repository anywhere and still use that tool.
If there's a security update, and it is likely exploitable in the apps I work on, I update immediately. As for the regular gem updates, I batch them and do upgrade days when I upgrade as many as I can.
Yes, bundle-audit and brakeman, which are very well-known and widely used.
I actually created my own gem, similar to brakeman.
My gem, Spektr is somewhat similar, bit it built with a different parsing library and it has a different license, so penetration testers can run it for free during assignments. But the core idea is the same as Brakeman's. It might report a few false positives, but even those might give ideas for patterns to look into during a test.
Yes, RuboCop does have security features, but I think they overlap with Brakeman, so I don't really use them. I use RuboCop% for style enforcement, but not for the security aspects.
Perhaps I should take a closer look and see how it compares to the other tools. I believe that Brakeman and bundle-audit pretty much cover everything that can be detected automatically.
However, there are other security issues, particularly those of logical nature, that cannot be flagged automatically. If you forget enforce authorization for an endpoint - no automatic tool can point it out. For that, I often recommend writing tests for every different role, to ensure they have access to only the things they're supposed to. Use a whitelist, not a blacklist - if you add something new, it's blocked by default and can only be enabled intentionally.
I believe you can automate about half of security checks, but the other half still requires vigilance. You still need to write tests and make sure you're implementing all authorization and authentication rules properly, and continually check that they are functioning as they should.
Certainly, you can - or rather, should - automate some portion, primarily because it's a straightforward process. Why wouldn't you take advantage of it if it's that easy and offers a head start against potential attacks?
Rails' default security settings protect against a lot of common mistakes. It's hard to create an XSS vulnerability because everything is escaped by default, with only a few exceptions. You need to explicitly state that a string is HTML safe; otherwise, it's automatically treated as unsafe. This makes life much easier.
90% of the ActiveRecord API is immune to SQL injection, which means that you don’t need extensive security knowledge to maintain a safe environment.
I believe, however, that this could lead to people not taking security as seriously as they should, they think Rails takes over that responsibility, but that's impossible, there is no way to make a functioning framework without letting people to shoot themself in the leg if they want to.
When I'm writing code, I'm solving a problem. I don't think about security as a first class citizen. I always think about, okay, let's solve this problem in the most efficient way. And then I look at it and think about the security aspect. But it's only because I care about security, but a lot of people miss that second step.
Another aspect to consider is for instance, with PHP, if I discover a vulnerability in a PHP application, it is relatively easy to gain access to the entire server or infrastructure, because it is running on a server with a bunch of tools installed and those usually help to open a remote shell and elevate privileges. This is much easier than finding a vulnerability in, say, a Rails app running on Heroku in a container.
Thank you Greg for sharing your thoughts and experiences with us!
Enter your email address to receive early previews of the book content, as well as announcements, promotions, interviews and updates related to our book or book related content.