Security - Reliably Deploying Rails Applications: Hassle free provisioning, reliable deployment (2014)

Reliably Deploying Rails Applications: Hassle free provisioning, reliable deployment (2014)

7.2 - Security

Overview

In this chapter we’ll cover some basic steps which can be taken on all servers to help protect against unauthorised access.

A Note on security

One size does not fit all

Depending on the type of application, the environment you’re hosting in and the regulations associated with your industry, security requirements will vary.

There is no one secure server configuration which works for everyone. In this section I’ll cover the basic steps I apply to all new servers to provide a base layer of security. This is unlikely to be exhaustive for your application.

These are basic security tips, it’s essential you do your own research and if necessary engage an independent security expert to ensure the measures you’re taking are suitable for your requirements.

Security Gotchas

When we talk about security, it brings to mind firewalls and auto banning brute force attacks. In practice many security breaches are due to not following good practices rather than configuration errors, in particular:

Mistake 1 - Not Updating Gems

Security updates are regularly issued for gems, it’s a pain staying up to date. Not doing so can be fatal, as a minimum subscribe to receive security advisories for the Rails gem. If a major vulnerability is discovered within Rails, it’s essential you have a plan in place to upgrade within days if not hours of this being released.

Mistake 2 - Hard coding credentials

As an app grows and the number of people who have or have had access to the source code grows, the danger of having hard coded login credentials becomes clearer.

Common culprits are:

· AWS Keys

· Mail server Passwords

· Error logging services

· Database logins

Your development repository should contain no production credentials and it’s worth scouring initializers to make sure none remain. All credentials should be moved to standalone config files which are maintained independently on production and staging environments. The basics of this are covered when we look at deploying with Capistrano.

Remember even once these are removed, a record will still exist in version control so any passwords which have been hard coded should be changed.

Mistake 3 Re-using Passwords

Combined with hard coding credentials, re-using passwords this can be fatal. I’ve seen hard coded mail server credentials which were identical to the VPS providers login credentials.

It’s also tempting to use identical credentials across production and staging environments, this is bad for two main reasons:

· It means anyone you give access to staging, can access production. There may well be times (such as trialling a contractor) when you want to give someone access to a staging environment but aren’t yet ready to give access to production.

· It makes it far easier to accidentally make a change on production when you thought you were working on staging. Anyone who’s had a near miss and started typing “rake db:drop” on production thinking they were on staging knows this is bad for the blood pressure.

Basic Measures

We’ll primariy be looking at the basic-security-tlq cookbook in this section.

The default recipe begin with the following:

1 packages = %w(

2 fail2ban

3 ufw

4 unattended-upgrades

5 )

6

7 packages.each { |name| package name }

Which installs three security related packages.

Fail2Ban

Fail2Ban is a tool to prevent brute force attacks. If an IP has too many failed attempts to connect to a configured service, Fail2Ban can be configured to update the firewall to block any further connection attempts from this user.

This is to prevent brute force attacks where an attacker sequentially tries a large number of user and password combinations to a known service.

Its default configuration covers SSH brute forcing (although you’ll see below we make this extremely unlikely to occur anyway by disabling password authentication). It’s an extremely powerful tool which should be configured for the specific services you’re exposing to external access.

A good place to start is:

https://help.ubuntu.com/community/Fail2ban

and

http://www.fail2ban.org/wiki/index.php/Main_Page

SSH Hardening

By default when you use ssh user@yourserpip authentication will first be attempted by public key. This means looking at your private key, by default in ~/.ssh/id_rsa, and checking to see whether there is a matching public key in ~/.ssh/authorised_keys on the remote machine.

If there is not, you will then be prompted to enter the password for the user you are trying to connect as.

One of the first steps I take on any new server is to disable password login via ssh. Anyone whos run a publicly available sever and taken a look at the logs will have seen the regular and persistent attempts to brute force ssh login. Disabling it removes this attack vector completely.

It’s easy to think that the risk is minimal anyway if suitable long and unique passwords combined with fail2ban are used. Unfortunately it only takes one test account to be created with a weak or default password and the forgotten about to expose your server to significant risk of intrusions.

I also disable X11Forwarding simply because there’s no graphical interface on the server and so no need for it.

The below section uses the utility sed to automatically make changes to the ssh config file:

1 # path to ssh config

2 sshd_config = '/etc/ssh/sshd_config'

3

4 # changes to make to the config file

5 seds = [

6 's/^#PasswordAuthentication yes/PasswordAuthentication no/g',

7 's/^X11Forwarding yes/X11Forwarding no/g',

8 's/^UsePAM yes/UsePAM no/g'

9 ]

10

11 bash 'ssh hardening' do

12 user 'root'

13 code <<-EOC

14 #{seds.map { |rx| "sed -i '#{rx}' #{sshd_config}" }.join("\n")}

15 EOC

16 end

Sed is a great utility which allows you to automate the modification of files. It’s a little intimidating at first but if you have a spare afternoon well worth spending time getting to know as it’s tremendously powerful and can save huge amounts of time. The documentation is universally acknowledged as being terrible but there’s a great tutorial available at:

http://www.grymoire.com/Unix/Sed.html

Unattended Upgrades

On this occasion I’ve saved the most controversial for last. The unattended-upgrades package allows you to set certain updates to be installed automatically at a pre determined interval, without any manual intervention.

It should be noted at this point this can break things. If, as I do, you choose to setup unattended upgrades to automatically install security updates when they become available, it’s possible that a package update will break an element of your stack and take the server down.

This should be weighed up against the risk of leaving security updates to manual, forgetting to do them and having the server compromised.

In 99% of cases I choose to err on the side of automatic upgrades, the 1% where I don’t is when 99.999% uptime is a requirement and I know that there will be ongoing sysadmin experience available to check for, test and install updates.

The section which enables automatic updates is:

1 # Set the system to install security updates automatically each day

2 file '/etc/apt/apt.conf.d/10periodic' do

3 owner 'root'

4 group 'root'

5 mode '0644'

6 content <<-EOF

7 APT::Periodic::Update-Package-Lists "1";

8 APT::Periodic::Download-Upgradeable-Packages "1";

9 APT::Periodic::AutocleanInterval "7";

10 APT::Periodic::Unattended-Upgrade "1";

11 EOF

12 end

For more on this process and how it can be customised, see the official Ubuntu tutorial:

https://help.ubuntu.com/community/AutomaticSecurityUpdates

Automatically Updating Time

Finally we setup automatic time updating.

1 # updated time from central server every day, particularly important

2 # when certs are involved.

3

4 file '/etc/cron.daily/ntpdate' do

5 owner 'root'

6 group 'root'

7 mode '0755'

8 content <<-EOF

9 #!/bin/sh

10

11 ntpdate -s ntp.ubuntu.com pool.ntp.org

12 EOF

13 end

Here we setup a simple cron job which will update the system time from the Ubuntu time server each day. This is especially important when dealing with SSL certificates where incorrect server times can cause hard to debug errors.

Next will look at configuring the Firewall to keep control of which ports are accessible to the outside world.