Nginx is the most widely used free and open-source web server nowadays. It is lightweight, fast, robust, has low resource consumption, and supports the major operating systems. But the default configurations are not secure and need some extra tweaks to protect the web server and give it the much-needed security to prevent attacks and breaches. In this article, I will give you tips on Nginx server security, showing how to secure your Nginx installation.
If you did not read my previous posts regarding Nginx Best Practices on Initial Setup and Nginx Performance Tuning, please first go and read them to get a basic idea about the Nginx web server and its configurations.
Install the SSL/TLS Certificate
HTTP is a plain text protocol and it transfers the data t between the client and the server in clear text hence, an important step in web server security is to have an SSL/TLS certificate. The SSL/TLS certificate is a cryptographic digital certificate that encrypts the traffic between the client (web browser) and the server. By doing the encryption is secured and kept safe from attackers who might try to eavesdrop and steal confidential information such as usernames, passwords, and credit card information using man-in-the-middle attacks.
For your website, you can use freely available certificates like LetsEncrypt, ZeroSSL, SSL For Free and etc… which are valid for 90 days, and every 90 days you have to renew them. Or else you can buy a paid certificate from DigiCert, Comodo like well-known sites.
In the Nginx server you can configure SSL/TLS certificate as follows:
server {
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/bundle.pem;
ssl_certificate_key /etc/nginx/ssl/sysopstechnix.com.key;
}
Once you have it installed, you can verify the strength of the SSL encryption by testing your domain on SSL Labs. The results are shown below.
Disable Weak and Old SSL/TLS Protocols
SSL and its successor, TLS has widely used protocols designed to secure the transfer of data between the client and the server through encryption, integrity, and authentication protection. Having weak SSL/TLS protocols (SSLv2.0, SSL v3.0, TLSv1.0, and TLSv1.1) may be vulnerable and lead to attacks such as BEAST (Browser Exploit Against SSL/TLS), POODLE (Padding Oracle On Downgraded Legacy Encryption) and CRIME (Compression Ratio Info-leak Made Easy) attacks. Therefore recommend using newer and more secure SSL/TLS protocols.
To configure it, add the following directive inside the server section of the Nginx configuration file:
ssl_protocols TLSv1.2 TLSv1.3;
Disable Weak Cipher Suites
A cipher suite is a combination of algorithms that provide encryption, authentication, and integrity. To secure the transfer data, TLS/SSL uses one or more cipher suites. These are used during the SSL/TLS negotiation as well as for the transfer of data.
Method | Algorithm |
Encryption | RC4, 3DES, AES |
Message Integrity | HMAC-SHA256, HMAC-SHA1, HMAC-MD5 |
Authentication | RSA, DSA, ECDSA |
Key Exchange | RSA, Diffie-Hellman, ECDH, SRP, PSK |
Weak and old cipher suite configurations may provide a false sense of security and make your website vulnerable to attacks. If you use them, the attacker may intercept or modify data in transit.
Depending on your use case or OpenSSL and Nginx versions, you may need to use different cipher suite configurations. Therefore you may use the Mozilla SSL Configuration Generator to obtain an optimal cipher suite using different browsers like modern, intermediate, or old.
In the Nginx configuration, you can change it inside the server block:
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
Use Secure Key Exchange Mechanism
The purpose of the DH parameter allows exchanging a secret that will be used to encrypt a transcript of messages within a session. Ephemeral DH offers forward security, meaning that the session key is deleted upon session termination. Hence an attacker could not retrieve the messages exchanged between two parties for more than the last session.
Generate Unique DH Group with at least 2048 bits by using OpenSSL:
openssl dhparam -out /etc/ssl/dhparam.pem 2048
Now in your server block, add this line:
ssl_dhparam /etc/ssl/dhparam.pem;
Remove Unwanted HTTP Methods
Commonly used HTTP methods are GET and POST. Allowing other methods like TRACE, DELETE, PUT and OPTIONS are risky because they can allow attackers to launch Cross-Site Tracking attacks and steal the cookie information from your website. So it is recommended to disable unwanted & unused HTTP methods.
If you add the following directive inside the location block of the Nginx virtual configuration file, the server will only allow GET, HEAD, and POST methods only.
location / {
limit_except GET HEAD POST { deny all; }
}
Another approach is you can add a condition inside the server block in the Nginx configuration file and it will allow only GET, HEAD, and POST methods and filter out any other HTTP methods by issuing a 444 No Response status code.
if ($request_method !~ ^(GET|HEAD|POST)$ )
{
return 444;
}
Control Buffer Overflow Attacks
Buffer is a small storage location inside system memory that temporally accommodates data as it begins transfers from one memory location to another. When the data size exceeds the capacity of the buffer size, a buffer overflow occurs. So the attacker can exploit this vulnerability to inject malicious code that can compromise a system. As security practice, it is recommended to do a few tweaks to the Web server to mitigate these types of issues by adding the lines of code below to the nginx.conf file.
client_body_buffer_size 1K;
client_header_buffer_size 1k;
client_max_body_size 1k;
large_client_header_buffers 2 1k;
CSP and XSS Protection
The Content Security Policy (CSP) is an extra layer of security that helps to mitigate certain attacks such as XSS and script injection attacks or packet sniffing attacks. CSP can tell the browser that it can only download content from the domains you explicitly allow, including Javascript and CSS files. You can add a CSP header as follows.
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
Cross-Site Scripting (XSS) is another type of web attack that allows attackers to inject and execute malicious code or browser-side script into a trusted website. For instance, when a visitor came to the site, the script is downloaded and can access various web browser resources such as cookies and session tokens and etc.
To prevent measures against such type of attack is to append the line below in the nginx.conf file.
add_header X-XSS-Protection "1; mode=block";
Avoid Click-jacking Attacks
Click-jacking is another well-known web application vulnerability. This vulnerability is used by the attacker to force the user to click without the user’s consent, leading to redirecting to an unknown website. The X-Frame -Option in the HTTP response header can be used to indicate whether or not a web browser should load a page in frame or iframe.
Therefore append the X-Frame-Options in the HTTP header in the nginx.conf file as shown below. This will instruct a browser to load the resources only from the same origin.
add_header X-Frame-Options "SAMEORIGIN";
Disable content-type Sniffing
Content sniffing, also known as MIME (Multipurpose Internet Mail Extensions) sniffing, is the technique used for inspecting the content of a byte stream to determine the file format of the data within it. This can also cause a security vulnerability because an attacker can leverage MIME sniffing to send an XSS (Cross-Site Scripting) attack.
As an example, if your site allows users to upload media content like images, an attacker might be able to upload a malicious image file that contains some JavaScript code. When a browser does content sniffing might then be tricked into executing that malicious file. To prevent content sniffing attacks, set the X-Content-Type-Options
response header to nosniff
and this tells browsers to avoid guessing response types and to depend only on the Content-Type
header.
add_header X-Content-Type-Options nosniff;
Prevent Image Hotlinking
Hotlinking means someone from an external party makes a link to your site images and displays it on their own site. This may result in an increase in your bandwidth use (which you pay for) while the other person happily displays the image.
As an example, let’s assume you have a directory named images inside your document root which stores all the images you used on your site. To prevent other parties from using your images, you will need to insert the following location block inside your virtual host configuration.
location /images/ {
valid_referers none blocked www.sysopstechnix.com sysopstechnix.com;
if ($invalid_referer) {
return 403;
}
}
#You can also specify the image extensions as shown:
valid_referers blocked www.sysopstechnix.com sysopstechnix.com;
if ($invalid_referer) {
rewrite ^/images/uploads.*\.(gif|jpg|jpeg|png)$ http://www.sysopstechnix.com/banned.jpg last
}
HTTP Strict Transport Security
HSTS feature allows clients (web browsers) to only connect using HTTPS, but this is a different concept from the return and redirect methods explained in earlier posts. When the browser receives the HSTS header, it will not try to contact the server using HTTP for a specified period of time and also prevent users from accepting insecure SSL certificates.
To enable HSTS to add the following headers to your Nginx configuration file:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Allow access to domain name only
If the bot making random server scans for all domains, just deny it. You must allow only for configured virtual host domain and you don’t want to allow requests using IP address. Then you can include the following section inside the virtual host configurations.
if ($host !~ ^(sysopstechnix.com|www.sysopstechnix.com)$ ) {
return 301 https://sysopstechnix.com$request_uri;
}
Deny automated user agents
To keep protect your server from bots, scripts, and other automated methods of web page retrieval, explicitly deny those user agents. As an example applications like wget can retrieve entire document root directory structures, making them useful DoS attackers or simply accessing secured files on the website.
Append the following line in the nginx.conf file to prevent this:
if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
return 403;
}
Prevent Server Information Disclosure
The default configuration of the Nginx server, server_tokens directive displays the Nginx version number on all automatically generated error pages as well as the HTTP response header. This could cause information disclosure to unauthorized parties and they can gain knowledge about the version of Nginx which lead to narrows the focus for anyone trying to attack. Add the following line to your nginx.conf file to disable publishing this kind of info.
server_tokens off;
Keep Nginx Up to Date
Last but not least, recommended to keep your Nginx server updated to the latest and stable version as there are a lot of performance improvements, security fixes, and new features are being added. Nginx security advisories can be found here and the latest updates can be found here.
Configuration File as a Summary
If you followed all the above steps, you should end up with a final configuration like the following one:
#Mian nginx.conf File
#======================
#Prevent Server Information Disclosure
server_tokens off;
#Avoid Click-jacking Attacks
add_header X-Frame-Options SAMEORIGIN;
#Disable content-type Sniffing
add_header X-Content-Type-Options nosniff;
#CSP and XSS Protection
add_header X-XSS-Protection "1; mode=block";
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
#HTTP Strict Transport Security
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
#Control Buffer Overflow Attacks
client_body_buffer_size 1K;
client_header_buffer_size 1k;
client_max_body_size 1k;
large_client_header_buffers 2 1k;
#Virtual Host Configuration File
#===============================
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name sysopstechnix.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name sysopstechnix.com;
#Install the SSL/TLS Certificate
ssl_certificate /etc/nginx/ssl/bundle.pem;
ssl_certificate_key /etc/nginx/ssl/sysopstechnix.com.key;
#Use Secure Key Exchange Mechanism
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_prefer_server_ciphers on;
#Disable Weak and Old SSL/TLS Protocols
ssl_protocols TLSv1.2 TLSv1.3;
#Disable Weak Cipher Suites
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
#Remove Unwanted HTTP Methods
if ($request_method !~ ^(GET|HEAD|POST)$ ){
return 444;
}
#Prevent Image Hotlinking
location /images/ {
valid_referers none blocked www.sysopstechnix.com sysopstechnix.com;
if ($invalid_referer) {
return 403;
}
}
#Allow access to domain name only
if ($host !~ ^(sysopstechnix.com|www.sysopstechnix.com)$ ) {
return 301 https://sysopstechnix.com$request_uri;
}
#Deny automated user agents
if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
return 403;
}
}
That was a wrap-up of some of the important key measures you can take to secure your Nginx web server from common exploitation techniques. This will go a long way in securing your website content and protecting the visitors on your site as well.