security snippets

How to Secure an nginx Server with Fail2Ban

Tagged nginx, fail2ban, filters, configuration, security, throttling  Languages apacheconf

Our Security Requirements

  • Block anyone trying to run scripts (.pl, .cgi, .exe, etc)
  • Block anyone trying to use the server as a proxy
  • Block anyone failing to authenticate using nginx basic authentication
  • Block anyone failing to authenticate using our application's log in page
  • Block bad bots
  • Limit the number of connections per session

We could use ModSecurity to support these requirements, but it's not compatible with nginx. We want a lightweight and easy-to-use solution. We can fulfill all these requirements with fail2ban and nginx.

Configuring Fail2ban

All except the last requirement of connection throttling is supported by Fail2Ban. To start blocking unwanted guests, put this in Fail2Ban's jail.conf file:

[nginx-auth]
enabled = true
filter = nginx-auth
action = iptables-multiport[name=NoAuthFailures, port="http,https"]
logpath = /var/log/nginx*/*error*.log
bantime = 600 # 10 minutes
maxretry = 6

[nginx-login]
enabled = true
filter = nginx-login
action = iptables-multiport[name=NoLoginFailures, port="http,https"]
logpath = /var/log/nginx*/*access*.log
bantime = 600 # 10 minutes
maxretry = 6
 
[nginx-badbots]
enabled  = true
filter = apache-badbots
action = iptables-multiport[name=BadBots, port="http,https"]
logpath = /var/log/nginx*/*access*.log
bantime = 86400 # 1 day
maxretry = 1
 
[nginx-noscript]
enabled = true
action = iptables-multiport[name=NoScript, port="http,https"]
filter = nginx-noscript
logpath = /var/log/nginx*/*access*.log
maxretry = 6
bantime  = 86400 # 1 day
 
[nginx-proxy]
enabled = true
action = iptables-multiport[name=NoProxy, port="http,https"]
filter = nginx-proxy
logpath = /var/log/nginx*/*access*.log
maxretry = 0
bantime  = 86400 # 1 day

Filter configuration

The following filter configuration files are stored in /etc/fail2ban/filter.d/:

# Proxy filter /etc/fail2ban/filter.d/nginx-proxy.conf:
#
# Block IPs trying to use server as proxy.
#
# Matches e.g.
# 192.168.1.1 - - "GET http://www.something.com/
#
[Definition]
failregex = ^<HOST> -.*GET http.*
ignoreregex =
 
# Noscript filter /etc/fail2ban/filter.d/nginx-noscript.conf:
#
# Block IPs trying to execute scripts such as .php, .pl, .exe and other funny scripts.
#
# Matches e.g.
# 192.168.1.1 - - "GET /something.php
#
[Definition]
failregex = ^<HOST> -.*GET.*(\.php|\.asp|\.exe|\.pl|\.cgi|\scgi)
ignoreregex =
 
#
# Auth filter /etc/fail2ban/filter.d/nginx-auth.conf:
#
# Blocks IPs that fail to authenticate using basic authentication
#
[Definition]
 
failregex = no user/password was provided for basic authentication.*client: <HOST>
            user .* was not found in.*client: <HOST>
            user .* password mismatch.*client: <HOST>
 
ignoreregex =
#
# Login filter /etc/fail2ban/filter.d/nginx-login.conf:
#
# Blocks IPs that fail to authenticate using web application's log in page
#
# Scan access log for HTTP 200 + POST /sessions => failed log in
[Definition]
failregex = ^<HOST> -.*POST /sessions HTTP/1\.." 200
ignoreregex =

Testing fail2ban Rules

You should test your fail2ban rules with the fail2ban-regex command:

# Test against a log file
# fail2ban-regex <log file> <filter configuration>
fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-login.conf 

# Test using strings
# fail2ban-regex <e.g. row from log file> <failure regex from filter configuration>
fail2ban-regex "127.1.1.1 - - [21/Feb/2012:10:31:08 +0200] \"POST /sessions HTTP/1.1\" 200 1532 \"https://xxx.com/sessions\" \"Mozilla/5.0 Safari/535.11\" \"-\"" "^<HOST> -.*POST /sessions HTTP/1\..\" 200"

Limiting the number of connections

We limit the number of connections to 2 per second and allow a burst of 50 with the following nginx configuration:

http {
    limit_req_zone  $binary_remote_addr  zone=app:10m   rate=2r/s; 
    ... 
    server {
         ... 
        location / {
            limit_req   zone=app burst=50;
        }

Note that you could also use Rack::Attack to implement many of these requirements.

References

http://wiki.nginx.org/HttpLimitReqModule http://www.fail2ban.org/wiki/index.php/Main_Page http://serverfault.com/questions/307575/fail2ban-doesnt-process-jail-even-though-regex-matches

Ruby on Rails Security Checklist

Tagged ruby, ruby on rails, security, checklist  Languages ruby

Checklist

* Don't store passwords (config/database.yml, db/seeds.rb), API keys (Amazon AWS), the Rails secret token (config/initializers/secret_token.rb), etc in version control. * Don't store production passwords and API keys on developer laptops. * Inject secrets, API keys, etc with e.g. dotenv * Don't import production data to other environments without obfuscating or cleaning data. * Use a different secret token in production than staging, development, and other environments. * AR serialize and store (YAML) is using eval. Don't use YAML, use JSON. * Don't write redirect_to params[:url]. If you have to then add only_path: true, or use URI.parse to get the path component. * ActiveRecord is not safe from SQL injection. See http://rails-sqli.org for details. * Enforce password strength. * Set cookie timeout expire_after: 30.minutes. * Hash passwords before storing them in a database (has_secure_password). * Don't use GET for actions that change data (RequestForgeryProtection). * Uploaded files should be sanitized, name, path, etc. * Downloads of uploaded files should most likely be authorized (send_file , Downloads done right).

Recommended Software

* secure_headers gem (Content Security Policy) * mod_security (Apache & nginx web application firewall) * rack::attack gem (Similar to mod_security) * bundler_audit gem (Checks Gemfile.lock for vulnerable gems)

Further resources

* Ruby on Rails Security Guide * XSS (Cross Site Scripting) Prevention Cheat Sheet * Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet * DOM based XSS Prevention Cheat Sheet * HTML5 Security Cheat Sheet * SQL Injection Prevention Cheat Sheet * Attack Surface Analysis Cheat Sheet * Ruby on Rails Cheatsheet * http://12factor.net/config * http://gauntlt.org/