While there are many ways to harden the security on your NginX server with peripheral applications like  Google PAM, OSSEC, Fail2Ban and SNORT, the best place to start is probably the default security policies that are implemented natively in NginX and on your Linux Distro. In this instance, we’ll be bolstering the security on NginX only.

To keep things clean and easily readable, I like to create separate .conf files my own best practice for security policies. So in this example we’ll create the policies using this logic.

First we’ll write a new file via Nano Editor and call it sec.conf. We’ll place this file in the NginX native folder located at /etc/nginx/common:

sudo nano /etc/nginx/common/sec.conf

Inside this file we’re going to add 8 security policies to guard and protect against some of the most common threats. You’ll note that I use return 404 for all of them. This is because rendering specific error codes actually provides better insight to hackers than you probably want them to have. You’ll need to copy and paste each one so that the end result looks like figure #9:

1. Protect Against SQL Injection

##
# Protect against SQL injection
##
location ~* "(eval()" { deny all; }
location ~* "(127.0.0.1)" { deny all; }
location ~* "([a-z0-9]{2000})" { deny all; }
location ~* "(javascript:)(.*)(;)" { deny all; }
location ~* "(base64_encode)(.*)(()" { deny all; }
location ~* "(GLOBALS|REQUEST)(=|[|%)" { deny all; }
location ~* "(<|%3C).*script.*(>|%3)" { deny all; }
location ~ "(|...|../|~|`|<|>||)" { deny all; }
location ~* "(boot.ini|etc/passwd|self/environ)" { deny all; }
location ~* "(thumbs?(_editor|open)?|tim(thumb)?).php" { deny all; }
location ~* "('|")(.*)(drop|insert|md5|select|union)" { deny all; }
location ~* "(https?|ftp|php):/" { deny all; }
location ~* "(='|=%27|/'/?)." { deny all; }
location ~ "({0}|(/(|...|+++|"")" { deny all; }
location ~ "(~|`|<|>|:|;|%||s|{|}|[|]||)" { deny all; }
location ~* "/(=|$&|_mm|(wp-)?config.|cgi-|etc/passwd|muieblack)" { deny all; }
location ~* "(&pws=0|_vti_|(null)|{$itemURL}|echo(.*)kae|etc/passwd|eval(|self/environ)" { deny all; }
location ~* ".(aspx?|bash|bak?|cfg|cgi|dll|exe|git|hg|ini|jsp|log|mdb|out|sql|svn|swp|tar|rdf)$" { deny all; }
location ~* "/(^$|mobiquo|phpinfo|shell|sqlpatch|thumb|thumb_editor|thumbopen|timthumb|webshell).php" { deny all; }

2. Block SQL Injection Attempts

##
# Block SQL injections
##
set $block_sql_injections 0; if ($query_string ~ "union.*select.*(") { set $block_sql_injections 1; }
if ($query_string ~ "union.*all.*select.*") { set $block_sql_injections 1; }
if ($query_string ~ "concat.*(") { set $block_sql_injections 1; }
if ($block_sql_injections = 1) { return 404; }

3. Block File Injections

##
# Block File injections
##
set $block_file_injections 0;
if ($query_string ~ "[a-zA-Z0-9_]=http://") { set $block_file_injections 1; }
if ($query_string ~ "[a-zA-Z0-9_]=(..//?)+") { set $block_file_injections 1; }
if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?)+") { set $block_file_injections 1; }
if ($block_file_injections = 1) { return 404; }

4. Block Common Exploits

##
# Block common exploits
##
set $block_common_exploits 0;
if ($query_string ~ "(<|%3C).*script.*(>|%3E)") { set $block_common_exploits 1; }
if ($query_string ~ "GLOBALS(=|[|%[0-9A-Z]{0,2})") { set $block_common_exploits 1; }
if ($query_string ~ "_REQUEST(=|[|%[0-9A-Z]{0,2})") { set $block_common_exploits 1; }
if ($query_string ~ "proc/self/environ") { set $block_common_exploits 1; }
if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|%3D)") { set $block_common_exploits 1; }
if ($query_string ~ "base64_(en|de)code(.*)") { set $block_common_exploits 1; }
if ($block_common_exploits = 1) { return 404; }

5. Block SPAM

##
# Block SPAM
##
set $block_spam 0;
if ($query_string ~ "b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)b") { set $block_spam 1; }
if ($query_string ~ "b(erections|hoodia|huronriveracres|impotence|levitra|libido)b") { set $block_spam 1; }
if ($query_string ~ "b(ambien|bluespill|cialis|cocaine|ejaculation|erectile)b") { set $block_spam 1; }
if ($query_string ~ "b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)b") { set $block_spam 1; }
if ($block_spam = 1) { return 404; }

6. Block User Agents

##
# Block user agents
##
set $block_user_agents 0;
# Don't disable wget if you need it to run cron jobs!
#if ($http_user_agent ~ "Wget") { set $block_user_agents 1; }
# Disable Akeeba Remote Control 2.5 and earlier
if ($http_user_agent ~ "Indy Library") { set $block_user_agents 1; }

7. Protect Against Bandwidth Hogs and Hacking Tools

##
# Protect against common bandwidth hoggers and hacking tools.
##
if ($http_user_agent ~ "libwww-perl") { set $block_user_agents 1; }
if ($http_user_agent ~ "GetRight") { set $block_user_agents 1; }
if ($http_user_agent ~ "GetWeb!") { set $block_user_agents 1; }
if ($http_user_agent ~ "Go!Zilla") { set $block_user_agents 1; }
if ($http_user_agent ~ "Download Demon") { set $block_user_agents 1; }
if ($http_user_agent ~ "Go-Ahead-Got-It") { set $block_user_agents 1; }
if ($http_user_agent ~ "TurnitinBot") { set $block_user_agents 1; }
if ($http_user_agent ~ "GrabNet") { set $block_user_agents 1; }
if ($block_user_agents = 1) { return 404; }

8. Protect Against IP Spoofing

##
#Protect against IP spoofing
##
if ($host !~* ^(.*ayrne.com|d+.d+.d+.d+)$ ) { return 404; }
server_name 159.203.14.3; # Public IP
server_name 127.0.0.1; # Private IP

9. Your Complete Sec.conf Should Look Like This

##
# Protect against SQL injection
##
location ~* "(eval()"  { deny all; }
location ~* "(127.0.0.1)"  { deny all; }
location ~* "([a-z0-9]{2000})"  { deny all; }
location ~* "(javascript:)(.*)(;)"  { deny all; }
location ~* "(base64_encode)(.*)(()"  { deny all; }
location ~* "(GLOBALS|REQUEST)(=|[|%)"  { deny all; }
location ~* "(<|%3C).*script.*(>|%3)" { deny all; }
location ~ "(|...|../|~|`|<|>||)" { deny all; }
location ~* "(boot.ini|etc/passwd|self/environ)" { deny all; }
location ~* "(thumbs?(_editor|open)?|tim(thumb)?).php" { deny all; }
location ~* "('|")(.*)(drop|insert|md5|select|union)" { deny all; }
location ~* "(https?|ftp|php):/" { deny all; }
location ~* "(='|=%27|/'/?)." { deny all; }
location ~ "({0}|(/(|...|+++|"")" { deny all; }
location ~ "(~|`|<|>|:|;|%||s|{|}|[|]||)" { deny all; }
location ~* "/(=|$&|_mm|(wp-)?config.|cgi-|etc/passwd|muieblack)" { deny all; }
location ~* "(&pws=0|_vti_|(null)|{$itemURL}|echo(.*)kae|etc/passwd|eval(|self/environ)" { deny all; }
location ~* ".(aspx?|bash|bak?|cfg|cgi|dll|exe|git|hg|ini|jsp|log|mdb|out|sql|svn|swp|tar|rdf)$" { deny all; }
location ~* "/(^$|mobiquo|phpinfo|shell|sqlpatch|thumb|thumb_editor|thumbopen|timthumb|webshell).php" { deny all; }
##
# Block SQL injections
##
set $block_sql_injections 0; if ($query_string ~ "union.*select.*(") { set $block_sql_injections 1; }
if ($query_string ~ "union.*all.*select.*") { set $block_sql_injections 1; }
if ($query_string ~ "concat.*(") { set $block_sql_injections 1; }
if ($block_sql_injections = 1) { return 404; }
##
# Block File injections
##
set $block_file_injections 0;
if ($query_string ~ "[a-zA-Z0-9_]=http://") { set $block_file_injections 1; }
if ($query_string ~ "[a-zA-Z0-9_]=(..//?)+") { set $block_file_injections 1; }
if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?)+") { set $block_file_injections 1; }
if ($block_file_injections = 1) { return 404; }
##
# Block common exploits
##
set $block_common_exploits 0;
if ($query_string ~ "(<|%3C).*script.*(>|%3E)") { set $block_common_exploits 1; }
if ($query_string ~ "GLOBALS(=|[|%[0-9A-Z]{0,2})") { set $block_common_exploits 1; }
if ($query_string ~ "_REQUEST(=|[|%[0-9A-Z]{0,2})") { set $block_common_exploits 1; }
if ($query_string ~ "proc/self/environ") { set $block_common_exploits 1; }
if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|%3D)") { set $block_common_exploits 1; }
if ($query_string ~ "base64_(en|de)code(.*)") { set $block_common_exploits 1; }
if ($block_common_exploits = 1) { return 404; }
##
# Block SPAM
##
set $block_spam 0;
if ($query_string ~ "b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)b") { set $block_spam 1; }
if ($query_string ~ "b(erections|hoodia|huronriveracres|impotence|levitra|libido)b") { set $block_spam 1; }
if ($query_string ~ "b(ambien|bluespill|cialis|cocaine|ejaculation|erectile)b") { set $block_spam 1; }
if ($query_string ~ "b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)b") { set $block_spam 1; }
if ($block_spam = 1) { return 404; }
##
# Block user agents
##
set $block_user_agents 0;
# Don't disable wget if you need it to run cron jobs!
#if ($http_user_agent ~ "Wget") { set $block_user_agents 1; }
# Disable Akeeba Remote Control 2.5 and earlier
if ($http_user_agent ~ "Indy Library") { set $block_user_agents 1; }
##
# Common bandwidth hoggers and hacking tools.
##
if ($http_user_agent ~ "libwww-perl") { set $block_user_agents 1; }
if ($http_user_agent ~ "GetRight") { set $block_user_agents 1; }
if ($http_user_agent ~ "GetWeb!") { set $block_user_agents 1; }
if ($http_user_agent ~ "Go!Zilla") { set $block_user_agents 1; }
if ($http_user_agent ~ "Download Demon") { set $block_user_agents 1; }
if ($http_user_agent ~ "Go-Ahead-Got-It") { set $block_user_agents 1; }
if ($http_user_agent ~ "TurnitinBot") { set $block_user_agents 1; }
if ($http_user_agent ~ "GrabNet") { set $block_user_agents 1; }
if ($block_user_agents = 1) { return 404; }
##
#Protect against IP spoofing
##
if ($host !~* ^(.*ayrne.com|d+.d+.d+.d+)$ ) { return 404; }
server_name 159.203.14.3; # Public IP
server_name 127.0.0.1; # Private IP

10. Save The Sec.conf File

Assuming your complete file looks like the one above, go ahead and close out the file and save it.

11. Make the New Security Policies Active

To make your new security policies active you'll need to call the file from your default NginX configuration by adding the following line to include it:

include common/sec.conf;

You'll also need to restart NginX for the new policies to go into effect, but before doing that, let's verify the integrity of the entries we've made:

nginx -t

If all is well, you'll get a confirmation that looks like this:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@nginxisawesome:~#

Now restart NginX so that the policies become active:

service nginx restart

That's it - you're done!

Share this post