Securing your LAMR a.k.a. Being a devops but not a so lame one

When deploying stuff in production environment, security is always a concern.
Here is a summary of some basic guidelines when running a LAMR (linux, apache, mysql, ruby) server, to make your server more secure.

1) Linux

Disable root account
To disable root access, run the following command:
sudo passwd -l root

User password strength
Having a strong password is recommend to avoid dictionary attacks.
Always set a long random generated password.
Avoid using dictionary word and passwords related to your personal life.

Use ssh keys
Allow access only using ssh keys and from trusted hosts, since passwords are more easily broken. To do so, you must add your public key to the  ~/.ssh/authorized_keys file
from="trusted_host" ssh-rsa encrypted_key Comment describing key

Secure your ssh server
To secure your ssh server you must do some changes in the sshd_config
- Do not allow root login

PermitRootLogin no

- Change the listen port

Port 666

- Allow only certain users to have access via ssh

AllowUsers username ref username@email

- Disable the protocol version 1

Protocol 2

- Add a banner to users connecting to the ssh server (legal protection)

Banner /etc/some_file

- Don't allow password authentication

PasswordAuthentication no

- Disable unused authentication modules (even if disabled by default)
- Restrict access to file transfer

Keep your system and packages updated
Once a vulnerability is found, software updates are released to fix it. Old software versions may have a lot of well known vulnerabilities well-known to the hacker community.

Run the minimum number of services required and install the minimum amount of software required
More software means more vulnerabilities possibilities, so keep your software to a minimum necessary.

Don't install C compilers and other development utilities in your production server
Development tools may help an attacker compromise the system even further, allowing him to do privilege escalation.

Always run daemons under a new user and group
An attack to a software running as a certain user (nobody e.g.) may compromise other software running as this same user.
Also, remove shell access for these users.

2) Apache

Hide the apache version and other sensitive information
Attackers can use this information to exploit this version vulnerabilities.
It is also an indicator that you left most defaults alone.
Change your apache configuration file to be set like this:

ServerTokens Prod
ServerSignature Off
TraceEnable Off

Run using its own user and group
Make sure apache is running as its own user (sometimes it runs as nobody).

Files outside the web root directory should not be served

Turn off file browsing
This can be achieved setting:

Options -Indexes
Turn off server side includes
SSI-enabled files can execute any CGI script or program under the permissions of the apache user, using the exec cmd element. Thus, this is a security risk.

Turn off support for .htaccess files
htaccess files override the default configuration of your apache folder. To avoid this, you need to set your configuration ass follows:

AllowOverride None
Disable unused modules
The more modules you have enabled, greater the chance you have a security vulnerability.

Don't allow apache to follow symbolic links
Following symlinks makes your apache serve files outside your root directory.
To avoid this, set the following in your config file:

Options -FollowSymLinks

3) Mysql

Restrict access to the user table

Multiple applications should access the mysql server with different users

Grant only the necessary privileges to your application user in database

Secure root account with a strong password

Do not use plain text passwords in the database

Secure access to mysql port from untrusted hosts

Always escape SQL statement inputs in your application code

4) Ruby

SSL provides a secure connection, where the data is encrypted. This helps avoiding session hijacks through  cookie sniffing.

Expire sessions on inactivity
Sessions that never expire are a danger that can lead to attacks (CSRF, session hijacking e.g.). Expiring session leave a smaller time-frame in which attacks can happen

Reset session on every successful login
This way you can avoid session fixation attacks (attacker using a fixed session identifier to access an user session)

Use protect_from_forgery when possible
protect_from_forgery adds a security token as hidden input in your forms, that helps prevent CSRF attacks.

Do not allow user to supply parts of the URL to be redirected to
Allowing users to provide parts of the URL, can redirect someone to a complete different site (sometimes looking like yours, as in fishing attacks).

Use ip restriction to access admin interface
You usually won't need your admin interface open to all the world, so restricting access by ip address would narrow the range of attacks to your admin pages.

Use separated credentials to admin login
Having a separated admin credential can prevent a user to achieve privilege escalation changing some parameters of his profile.

Use attr_protected in sensitive model information
Mass assignment allows users to change any column related to the model being edited/created.
If you have any sensitive model information in a column, you should use attr_protected method to avoid mass assignment of this attribute.
But as in any security guideline, it is preferable to use whitelist rather than blacklist, so it's better to use attr_accessible.

Use captcha after some failed login attempts
Using captcha after some unsuccessful login attempts helps preventing brute force attacks to access an user account.

Be careful not to log sensitive information
Be careful not to log stuff like passwords, credit card numbers and other sensitive informations. Log filter_parameters helps you with that, but it is not 100% efficient,  so be aware of what you are logging.

Design your controllers restricting resources access
If some resources belongs to an user only, design your controllers according to it, avoiding users to access other users resources simply by changing the url.

# wrong
@project = Project.find(params[:id])
# right
@project = @current_user.projects.find(params[:id])

Escape all inputs (specially client ones)
Never trust inputs in your system, always escape then.
- To avoid SQL injection use placeholders

Project.where(["name in (?)", names])

- To avoid command injection use methods with sanity check

system("/bin/echo","hello; rm *")

- To avoid HTML/JavaScript Injection escape inputs (default in Rails 3)
- To avoid Header Injection don't let users inputs to set parts of a header.

Run your daemons with a new user and group
As told before, you should avoid running multiple softwares under the same user.

There is a lot to improve yet, but I hope this small guideline is useful to you guys. Feel free to ask any questions.



fnando said...

The Apache block should read "Install Nginx".

Nasreen Basu said...

Really cool post, highly informative and professionally written and I am glad to be a visitor of this perfect blog, thank you for this rare info! , Regards ,devops training in hyderabad

jatin tyagi said...

I have been reading out a lot of your articles.
I will certainly bookmark your Blog.
Free Devops Training
Hybris Training
Emc San Training