Nginx Basic Security Practices

1. Prevent information disclosure

Open up a terminal window and issue the command:

curl -I http://SERVER_ADDRESS

Chances are you'll see something similar to that shown in Figure A.

No alt text provided for this image

That information could invite attack. How? Because attackers can make use of that information to forge a hack for your system. To prevent that, we're going to configure NGINX to not display either the NGINX release or the hosting platform information. Open up the configuration file with the command sudo nano /etc/nginx/nginx.conf. Scroll down until you see the line:

# server_tokens off;

Uncomment that line by removing the # character, like so:

server_tokens off;

Save and exit the file. Once NGINX is reloaded with the command sudo systemctl reload nginx, the curl -I command will no longer show the NGINX version or the host platform (Figure B).

Figure B

No alt text provided for this image

2. Hide php settings

If you make use of NGINX with PHP, you cannot hide the PHP information via the NGINX configuration file. Instead, you have to edit the php.ini file. Issue the command sudo nano /etc/php/7.0/fpm/php.ini and make sure expose_php is set to off. The configuration option falls around line 359. Once you've changed that configuration, save and close the file. Reload NGINX and your PHP information will be hidden from prying eyes.

3. Redirect server errors

Next we need to configure the error pages in the default sites-enabled configuration, such that error 401 (Unauthorized) and 403 (Forbidden) will automatically redirect to 404 (Not Found) error page. Many believe handing out errors 401 and 403 is akin to exposing secure information--so rerouting them to error 404 offers a bit of security-by-obfuscation, in similar fashion to hiding server information.

To do this, issue the command sudo nano /etc/nginx/sites-enabled/default. In the resulting configuration file, scroll down to the server { section and add the line:

error_page 401 403 404 /404.html; 

Save and close the file. Reload NGINX with the command sudo systemctl reload nginx and your server will now redirect 401 and 403 errors to 404 errors.

4. Secure sensitive directories

Say you want to block certain directories from all but specific addresses. Let's say you have a Wordpress site and you want to block everyone but your local LAN addresses from accessing the wp-admin folder. And let's say your local LAN IP address scheme is 192.168.1.0/24. To do this, issue the command sudo nano /etc/nginx/sites-enabled/default. Scroll down to the server { location and add the following under the location / directive:

location /wp-admin {
allow 192.168.1.0/24;
deny all;
}

Once you reload NGINX, if anyone attempts to access the wp-admin folder, they will be redirected to the error 403 page, unless you've configured NGINX to redirect to error 404--at which point it will redirect to the error 404 page.

5. Limit the rate of requests

It is possible to limit the rate NGINX will accept incoming requests. For example, say you want to limit the acceptance of incoming requests to the /wp-admin section. To achieve this, we are going to use the limit_req_zone directory and configure a shared memory zone named one (which will store the requests for a specified key) and limit it to 30 requests per minute. For our specified key, we'll use the binary_remote_addr (client IP address). To do this, issue the command sudo nano /etc/nginx/sites-enabled/default. Above the server { section, add the following line:

limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;

Scroll down to the location directive, where we added the wp-admin section. Within that directive, add the following line:

limit_req zone=one;

So our wp-admin section might look like:

location /wp-admin {
allow 10.10.1.0/24;
deny all;
limit_req zone=one;
}

Save and close the default file. Reload NGINX with the command sudo systemctl reload nginx. Your wp-admin section will now only allow 30 requests per minute. After that 30th request, the user will see the following error ( Figure C).

Figure C

No alt text provided for this image


Our service has reached its rate limit.

You can set that rate limit on any directory that needs protected by such a mechanism.

Avoid A Smurf Attack

Open /etc/sysctl.conf and add

net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_echo_ignore_all=1

Controlling Buffer Overflow Attack

Edit nginx.conf and set the buffer size limitations for all clients as follows:

## Start: Size Limits & Buffer Overflows ##
 client_body_buffer_size  1K;
 client_header_buffer_size 1k;
 client_max_body_size 1k;
 large_client_header_buffers 2 1k;
 ## END: Size Limits & Buffer Overflows ##

client_body_buffer_size – (default is 8k or 16k) The directive specifies the client request body buffer size.

client_header_buffer_size 1k – Directive sets the header-buffer size for the request header from client. For the overwhelming majority of requests a buffer size of 1K is sufficient. Increase this if you have a custom header or a large cookie sent from the client (e.g., wap client).

client_max_body_size – Directive assigns the maximum accepted body size of client request, indicated by the line Content-Length in the header of request. If size is greater the given one, then the client gets the error “Request Entity Too Large” (413). Increase this when you are getting file uploads via the POST method.

large_client_header_buffers – Directive assigns the maximum number and size of buffers for large headers to read from client request. By default the size of one buffer is equal to the size of page, depending on platform this either 4K or 8K, if at the end of working request connection converts to state keep-alive, then these buffers are freed. 2x1k will accept 2kB data URI. This will also help combat bad bots and DoS attacks.

Control Maximum Number Of Simultaneous Connections For A Session

Edit Nginx.conf Add :

limit_conn slimits 20; ##change according to your need

Only Allow Following Request Methods

Edit nginx.conf and add ( Do not accept DELETE, SEARCH and other methods )

if ($request_method !~ ^(GET|HEAD|POST)$ ) {
  return 444;
  }

Block Unwanted Guests ( User-Agents )

You Should Block Unwanted user agent ex. libwww, lwp-trivial, curl,wget, PHP/, urllib, GT::WWW, Snoopy, MFC_Tear_Sample, HTTP::Lite, PHPCrawl, URI::Fetch, Zend_Http_Client, http client, PECL::HTTP, Java and many more.

if ($http_user_agent ~* wget|curl|Java) {  
return 403; 
}

Block Some Robots

 if ($http_user_agent ~* msnbot|scrapbot) {
  return 403;
  }

Block Referer Spam

Referrer spam is dangerous. It can harm your SEO ranking via web-logs (if published) as referer field refer to their spammy site. You can block access to referer spammers with these lines

if ( $http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen) )
  {
  return 403;
  }

Block Attackers Based On GeoIP Countries

apt-get install geoip-database libgeoip1 ( for ubuntu )

It is possible that it is a bit outdated. Therefore we can optionally download a fresh copy from the GeoIP web site:

mv /usr/share/GeoIP/GeoIP.dat /usr/share/GeoIP/GeoIP.dat_bak
cd /usr/share/GeoIP/
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
gunzip GeoIP.dat.gz

Edit Nginx.conf http {} configuration block:

geoip_country /usr/share/GeoIP/GeoIP.dat;

Next, let’s tell Nginx which countries are gonna be blocked:

go to virtualhost ( Here is the list of country code you want to block )

if ($geoip_country_code ~ (CN|KR|PK) ) {
  return 403;
  }

Disable SSL 3 and keep only TLS

SSL 3 is vulnerable, and we will allow only strong TLS protocol.

  • Edit ssl.conf file and add below in server block
ssl_protocols       TLSv1.2;
  • Save the ssl.conf file and restart the nginx

Disable weak cipher suites

Weak cipher suites may lead to vulnerability like a logjam, and that’s why we need to allow only strong cipher.

  • Add the following to server block in ssl.conf file
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA HIGH !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";
  • Save the file and restart Nginx

Information Leakage

In default nginx installation you will have much sensitive information revealed, which can help hacker to prepare for an attack.

If you are working on PCI compliance environment, this is considered as information leakage vulnerability and must fix the item.

You have to use server_tokens off to disable the information leakage. I have explained this above. 

Web Application Security

Default nginx configuration is not perfect and can have many vulnerabilities that’s why we harden them to make it secure.

Disable unwanted HTTP methods

Most of the time, you need just GET, HEAD & POST HTTP request in your web application. Allowing TRACE or DELETE is risky as it can allow Cross-Site Tracking attack and potentially allow a hacker to steal the cookie information.

  • Modify default.conf and add following under server block
if ($request_method !~ ^(GET|HEAD|POST)$ )
{
       return 405;
}

Save the file and restart the nginx. This will now show 405 Not Allowed if someone is trying to use TRACE, DELETE, PUT, OPTIONS.

lalit-iMac:~ chandan$ telnet bestflare.com 80
Trying 128.199.100.162...
Connected to bestflare.com.
Escape character is '^]'.
TRACE / HTTP/1.1
Host: testing
HTTP/1.1 405 Not Allowed
Server: nginx
Date: Sat, 11 Jul 2015 06:04:34 GMT
Content-Type: text/html
Content-Length: 166
Connection: close

Clickjacking Attack

You can inject X-FRAME-OPTIONS in HTTP Header to prevent clickjacking attack.

This is achieved by adding below in nginx.conf file

add_header X-Frame-Options "SAMEORIGIN";

Above header will instruct a browser to load the resources ONLY from the same origin.

X-XSS Protection

Inject HTTP Header with X-XSS protection to mitigate Cross-Site scripting attack.

  • Modify default.conf or ssl.conf file to add the following
add_header X-XSS-Protection "1; mode=block";


  • Save the configuration file and restart Nginx.

Implement Mod Security WAF

Add an additional layer of security by implementing Web Application Firewall ModSecurity with OWASP Core Rule Set.

Keep nginx up-to-date

Last but not least, you need to keep your nginx up-to-date as there are many performance enhancement, security fixes and new features are being added.

I hope this helps you to keep your Nginx secure.



To view or add a comment, sign in

More articles by Lalit Kumar Jain

Others also viewed

Explore content categories