Basic security for Ruby on Rails applications

By Najaf Ali

Application security is an entire profession, so as a web developer trying to maintain a Rails application, there’s only so much you can do without expert help. Organisations that are serious about security have security-focused staff that will provide a far more sophisticated posture towards security than a development team on their own.

With regard to the security of your software, the single most important measure is how often it is attacked in production, either by real-life attackers or penetration testers and researchers that you’ve hired. This can be by for example, hiring a company to perform a pentest or code audit, running a bug-bounty program, or having an in-house red team.

Let’s assume that you don’t have the budget or the organisational awareness to hire a security team. You’re a developer and you want to make a secure Ruby on Rails application with the time and resources available to you. This article will give you an outline of the absolute basics you can do to be ready for security issues.

Security should be focused around your approach to handling security incidents. This could be a disgruntled employee stealing your data, a DDOS attack, your application being turned into a spam relay, or your users deliberately gaining access to features of your application that they’re not authorised to.

You can think of your approach in three broad areas of activity:

Prevention - Making security incidents less likely to happen. This is could be by finding and fixing security vulnerabilities in your software and by making certain classes of attack technically unfeasible.

Detection - Finding out when a security incident happens. This might be by using monitoring tools and log file analysis to look for unusual traffic patterns that could be the result of an attack.

Response - Minimising the damage done by security incidents. This is by putting infrastructure in place to quickly stop the effects of attacks in progress and return to normal service for your users.

Remember that these are the basics. Everything we recommend here is something we think you should look at every month.

Prevention

Prevention is about making security problems less likely to happen. You would ideally have the help of an expert security team with this, but there are low hanging fruit that you can pick off on your own relatively quickly.

Run brakeman scanner

Brakeman is a static code analysis tool that detects vulnerabilities in Ruby on Rails code. It will occasionally have false positives, but is generally right about your code when it reports a problem.

Before you use brakeman, you should update to the latest release of the gem. This is because checks for newly discovered vulnerabilities are added in subsequent versions of the gem.

You should default to changing the code to make brakeman pass. No one has a completely exhaustive knowledge of all web security vulnerabilities. This is especially true of people who don’t work in security full time. The safest bet is to keep brakeman happy, even if it means changing your code to pass false positives sometimes.

Run bundle audit

Bundler audit is a tool that looks at your dependency graph and reports any gems that are known to contain security vulnerabilities. It will suggest a next secure version for you to upgrade to.

Bundler audit will automatically update on use. You should run bundler audit every month and then either upgrade insecure dependencies immediately or create an issue in whatever task tracker you use to get around to it later (if the upgrade isn’t simple).

Especially for more severe vulnerabilities, you’re racing a for-loop to get your gems upgraded to secure versions. Exploit scripts that detect vulnerabilities in your code can iterate through all IP addresses within a matter of days, so keeping your dependencies at secure versions is the absolute minimum you must do to prevent security problems.

Detection

Detection is about establishing a baseline understanding of what traffic to your application looks like and then trying to detect anomalies in that traffic.

Log file analysis

When running in production your Ruby on Rails application will be generating log entries for every request that hits it. If your application runs processes on separate physical machines, it will be easier to analyse your logs if you aggregate those logs.

Use a log aggregation tool (like Papertrail) to get all of your logs in the same place and then spend a short, regular timebox looking at the logs. In particular look out for 4XX responses, 5XX responses, and odd-looking user agent strings.

If you do this over time, what you and your team will establish is the type of traffic you can expect on a normal day. This will include browser traffic, search engine crawlers, scrapers, mobile phones, and anything else that could conceivably send a HTTP request. You’ll also occasionally see automated attack tools probing your servers for weaknesses.

The goals of doing this regularly are to put log analysis tools close to hand, and to give you and your team a good understanding of what your regular traffic looks like. When a security incident takes place, you’ll be able to quickly rule out your usual traffic and identify traffic that might be the result of a security incident.

Monitoring and error reporting

Alongside log analysis, most teams have monitoring tools set up to tell them when their application throws errors, has performance problems or stops being responsive to users.

All of these things can be caused by security incidents, so setting them up and having someone on hand to respond to them is likely the only way you will be able to detect security incidents as they happen.

In particular, consider setting up monitoring of outward facing interactions (like sending emails, making requests to external APIs) in addition to alerts about receiving requests. This might help you identify when for example your application is being used as a spam relay or is perhaps behaving in unexpected ways because of a security breach at a third-party API provider.

Response

Ultimately how resilient you are to attacks is the same as how you’re able to respond to them and still keep providing working software to your users.

Provisioning

In the worst security breaches, your own infrastructure becomes completely untrustworthy. You don’ t know what part of your application or data are allowing an attacker to control your system. The best way to recover from that situation is to recreate your production environment from scratch.

Think about the steps you would need to to take to do this. Is there a well-defined process? Is that process written down somewhere? Will it take twenty minutes to do? Two hours? Two days? How can you shorten that time or make it less error-prone? Can you automate it?

Backups

You should make backups of all data you don’t want to lose. This is not particularly controversial advice.

What you probably haven’t done is drilled recovering from backups. You should practice setting up your environment from scratch and recovering from backups. You want to learn how to do this without panic, in a peaceful setting where mistakes are easily tolerated and learned from. You don’t want to learn how to recover from backups on the day of a major security breach.

This is the bare minimum you should do for the security of your Ruby on Rails application. If you have the budget, you should hire people to help you with security. If you don’t then the above is a good start.