Categories
Security

How an NGINX Config Error can cause a Security Breach

If you’re not familiar with NGINX, it is a very popular bit of software powering millions of web servers. In a nut shell, it is designed to be very efficient and is used on a lot of high traffic websites, such as Twitch, WordPress, and DropBox.

It’s not particularly difficult to install and configure, but I suppose it requires a bit more attention compared to Apache.

As I have recently learned, a slight misconfiguration can cause a security breach if you are not careful. This is to do with HTTP Basic Authorisation configuration within NGINX, and how NGINX prioritises ‘location’ segments within configuration files.

One of the reasons NGINX is so fast is that unlike Apache, it does not support the use of .htaccess files. As NGINX is not having to scan each folder on the web server for the presence of htaccess files, it gains a speed advantage. Normally, on an Apache web server, if you want to enable HTTP Basic Authentication so that users are required to enter a username/password for certain directories, you can use .htaccess files. This is not an option with NGINX, so it has to go into the main configuration file on the web server.

Example Config File

 location / {
 try_files $uri $uri/ /index.php?q=$uri&$args;
 }

 location /secretarea {

        auth_basic "Administrator Login";
	auth_basic_user_file /home/secureuser/.htpasswd;
 
 }

 location ~* \.php$ {
	# With php-fpm unix sockets
	fastcgi_pass phpfpm;
	include         fastcgi_params;
	fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
	fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
 }

Looking at the above config file, you can see that the main directory (/) is open access and does not require authentication. You may also assume that /secretarea is password protected (and you would be right, to an extent).

If you were to use this configuration, and then visit https://www.example-domain-name.com/secretarea/, you would be prompted for a password, as expected.

However, if you were to visit https://www.example-domain-name.com/secretarea/phpfile.php, you will be granted access straight away without being prompted for a password. This can cause a bit of a problem as it may not be immediately obvious that you have a problem.

The reason this occurs is because NGINX chooses one location block (based on a series of rules), and only one location block will win. When you’re visiting the PHP file directly, the location block at the bottom of the config file is taking precedence and therefore bypassing the location block requiring authorisation.

How to mitigate this?

To mitigate this, we first need to understand how NGINX prioritises location blocks.

Here is an extract written by Martin Redmond from a helpful Stack Overflow article:

location  = / {
  # matches the query / only.
  [ configuration A ] 
}
location  / {
  # matches any query, since all queries begin with /, but regular
  # expressions and any longer conventional blocks will be
  # matched first.
  [ configuration B ] 
}
location /documents/ {
  # matches any query beginning with /documents/ and continues searching,
  # so regular expressions will be checked. This will be matched only if
  # regular expressions don't find a match.
  [ configuration C ] 
}
location ^~ /images/ {
  # matches any query beginning with /images/ and halts searching,
  # so regular expressions will not be checked.
  [ configuration D ] 
}
location ~* \.(gif|jpg|jpeg)$ {
  # matches any request ending in gif, jpg, or jpeg. However, all
  # requests to the /images/ directory will be handled by
  # Configuration D.   
  [ configuration E ] 
}

The reason the mistake occurred in my example is because regular expression location blocks are matched first, whereas ‘configuration c’ style location blocks (as in our example) would have been de-prioritised.

To mitigate this, we can nest a location block within a location block. Or, in other words, include the PHP location block in our /secretarea block too, as well as it being a separate/independent block at the bottom of the config file for the main part of the website.

 location / {
 try_files $uri $uri/ /index.php?q=$uri&$args;
 }

 location /secretarea {

 location ~* \.php$ {
	# With php-fpm unix sockets
	fastcgi_pass phpfpm;
	include         fastcgi_params;
	fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
	fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
 }

        auth_basic "Administrator Login";
	auth_basic_user_file /home/secureuser/.htpasswd;
 
 }

 location ~* \.php$ {
	# With php-fpm unix sockets
	fastcgi_pass phpfpm;
	include         fastcgi_params;
	fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
	fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
 }

As NGINX will first identify the PHP regular expression block nested in our ‘secretarea’ location block first, it will take precedence over the non-nested block at the bottom of the configuration file, and therefore the authentication settings will be inherited from the parent block and apply to our PHP files too. Quite an easy mistake to make!

Categories
Security

The ethics of hacking

So this blog is fairly new, and my first capture the flag exercise was published the other day. Fortunately, the CTF seems to have been fairly successful, and I have had a number of different questions and feedback provided by various people.

When I first published this blog, I wondered whether I would observe an increased number of cyber attack attempts to my server, due to the type of audience that would be visiting the website.

Interestingly, I’ve already found a number of different IP addresses performing scans/hacking attempts on my server, that have also downloaded my Capture the Flag exercise in full. These scans looks different to the usual noise you see in server logs.

I am sure (and hope) that the majority of the users who download my CTF exercises use their skills for good reasons, potentially leading to or improving their careers in white-hat cyber security.

I strongly encourage anyone learning these skills to use them wisely, and for legitimate purposes only. There’s not a lot I can do if you choose otherwise, but scanning and attempting to brute force a server from your domestic internet connection without any attempt at anonymity is not particularly the most intelligent thing I’ve seen.

To everyone else playing by the rules, thank you, and good luck with my CTF – I look forward to hearing your feedback.