Securing your WordPress site running on Nginx
5 March, 2021 by
Securing your WordPress site running on Nginx
Administrator
| No comments yet


 

Nginx is a modern and fast web server software. If you are not familiar with Nginx, you might be familiar with the Apache HTTP web server software. Both of them can serve your WordPress-powered site, though there are notable differences in performance and the way they work. I won’t be comparing them in this article, we’ll do it the other day. Instead, I’m going to show you some useful Nginx server configuration for having a more secure WordPress site.

No PHP scripts in the uploads/ directory

The uploads directory located within the wp-content folder usually stores everything you and your users upload to your WordPress site. Pictures, videos, temporary files — you name it. A problem appears when an attacker decides to gain control of your site. He might be able to somehow get a few PHP scripts into the uploads directory. He can then easily run the scripts by calling the URL address of the file, for example https://lamosty.com/wp-content/uploads/a-hidden-hack.php.

The Good news is that we can at least prevent him from being able to request the file. The following Nginx location directiveinspects the incoming request and with regular expressions jujitsu detects whether it is pointing to a file ending in the .php. If it is, deny all. Nginx module deny limits access to certain client (= visitor) addresses — all of them in our case.

location ~* /(?:uploads|files)/.*.php$ {
    deny all;
}

Hide sensitive files

Not all files residing in your site’s main WordPress directory are PHP scripts executed by your web server. Some of them contain valuable information such as passwords, database SQL queries, backups and others. Why should a random visitor have access to these files? It’s none of his or her business!

The following location directive uses regular expressions to match these files and return “No Response”, closing the connection. Exactly what we need.

location ~* .(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(.php)?|xtmpl)$|^(..*|Entries.*|Repository|Root|Tag|Template)$|.php_
{
        return 444;
}

No other CGI scripts

CGI or Common Gateway Interface is the standard method to generate dynamic content on the web. If you are running Nginx web server, chances are you are already using a CGI — FastCGI (a present-day variation of CGI) — to render your WordPress site. Malicious attackers might want to execute or mask their viruses as CGI scripts of different languages likePython. You know what to do, don’t you.

location ~* .(pl|cgi|py|sh|lua)$ {
        return 444;
}

Restrict WordPress pain points

Several files located in the WordPress folder could possibly aid an attacker to obtain more information about our WordPress installation like its version. We might also accidentally expose the site database settings when we erroneously change the wp-config.php file. What is more, swarms of spammers are trying to put comments on our articles every day nowadays. My typical tactic is to use Disqus Comment System. However, it needs to do one more thing: deny access to the standard WordPress comment system. Otherwise, spammers would be still able to comment. While the comments wouldn’t show under the articles, they would be still stored in the database, unnecessary taking space and doing mess.

Solution? I’m glad you asked: deny them all!

location ~ /(.|wp-config.php|wp-comments-post.php|readme.html|license.txt) {
    deny all;
}

Stop image hotlinking

Let’s say you have an image uploaded on your site. Its URL is http://my-site.com/wp-content/uploads/image.png. What if somebody decides to put this image on her or his site?


Any time a visitor loads his site, the image would be requested from your site, not his. This would eat your precious bandwidth and server CPU and RAM resources. We definitely need to protect against this (except if you are Imgur or any other image hosting service). The following Nginx config will do it:

location ~ .(gif|png|jpe?g)$ {
     valid_referers none blocked mywebsite.com *.mywebsite.com;
     if ($invalid_referer) {
        return   403;
    }
}

Put your site on the valid_referers line — the only sites enabled to request the images.

Sign in to leave a comment