Nginx is currently the most used Web server in the world. Here are some common Nginx configurations that will make your website vulnerable to attacks.

The following most common misconfigurations are often exploited by attackers

  • Missing root directory
  • Unsafe variable usage
  • Original backend response read
  • merge_slashes is set to off

Missing root location

server {
    root /etc/nginx;

    location /hello.txt {
            try_files $uri $uri/ =404;
            proxy_pass http://127.0.0.1:8080/;
    }
}

The root folder of Nginx specified in the root directive. In the above example, the root folder /etc/nginx means that we can access the files in that folder. The above configuration does not have a location of / (location / {...}), only /hello.txt. Therefore, the root directive will be set globally, which means that the request / will take you to the local path /etc/nginx

A simple request GET /nginx.conf will show that it is stored in /etc/nginx/nginx.conf. If the root is set to /etc, then a GET request /nginx/nginx.conf will show Configuration file. In some cases, other configuration files, access logs, and even encrypted credentials for HTTP basic authentication can be accessed

The most common root directory:
image.png

Off-By-Slash

server {
    listen 80 default_server;

    server_name _;

    location /static {
            alias /usr/share/nginx/static/;
    }

    location /api {
            proxy_pass http://apiserver/v1/;
    }
}

For the off-by-slash misconfiguration, due to the lack of slashes, it may move up one step on the path. The trailing slashes missing in the location instruction, alias can read the source code of the web application. What is less known is that this also applies to other commands such as proxy_pass

Break down how and why it happened:

location /api {
    proxy_pass http://apiserver /v1/;
}

Use the Nginx server running the following configuration to access server at. It may be assumed that you can only access the path under http://apiserver/v1/

http://server /api /user -> http://apiserver /v1/ /user

When http://server/api/user is requested, Nginx will first normalize the URL. Then it will check if the prefix /api matches the URL, in which case it will do so. Then remove the prefix from the URL so that /user retains the path. Then add this path to the proxy_passURL to generate the final URL http://apiserver/v1//user. Note that there is a double slash in the URL because the location directive does not end with a slash, and the proxy_pass URL path ends with a slash. Most web servers will standardize http://apiserver/v1//user to http://apiserver/v1/user, which means that even if there is such a misconfiguration, everything will work as expected and may Will be ignored

This misconfiguration can be exploited by request, http://server/api../ This will cause Nginx request http://apiserver/v1/../ to be normalized to http://apiserver/ The possible impact of this depends on what can be achieved when using this misconfiguration. For example, it may cause the Apache server status to be exposed along with the URL http://server/api../server-status, or it may make accessible paths that are not intended for public access

One sign of this misconfiguration of the Nginx server is that when the slash in the URL is removed, the server still returns the same response. For example, if two http://server/api/user and http://server/apiuser return the same response, the server may be vulnerable. This will result in the following request being sent:

http://server/api/user -> http://apiserver/v1//user
http://server/apiuser -> http://apiserver/v1/user

Unsafe variable use

Some frameworks, scripts, and Nginx configurations insecurely use variables stored by Nginx. This may cause problems such as XSS, bypassing HttpOnly protection, information leakage, etc., and in some cases even RCE

SCRIPT_NAME

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass 127.0.0.1:9000;
}

The main problem is that Nginx will send any URL to the PHP interpreter, even if the file does not exist.

If the PHP script tries to define a base URL based on, XSS SCRIPT_NAME will happen

<?php
if(basename($_SERVER['SCRIPT_NAME']) ==
basename($_SERVER['SCRIPT_FILENAME']))
   echo dirname($_SERVER['SCRIPT_NAME']);

?>
GET /index.php/<script>alert(1)</script>/index.php
SCRIPT_NAME = /index.php/<script>alert(1)</script>/index.php

Using $uri will cause CRLF injection:
Another misconfiguration related to Nginx variables is to use $uri or $document_uri instead of $request_uri. $uri and $document_uri contain the normalized URI, and normalizationNginx contains the URL that decodes the URI. Volema found that $uri is commonly used when creating redirects in Nginx configuration, which can lead to CRLF injection

An example of a vulnerable Nginx configuration is as follows:

location / {
  return 302 https://example.com$uri;
}

The newline characters for HTTP requests are \r (carriage return) and \n (line feed). URL encoding newline characters will produce the following character representation %0d%0a. When these characters are included in the request, such as http://localhost/%0d%0aDetectify:%20clrf misconfigured server, the server will respond with a new header named, Detectify because the $uri variable contains the URL decoded Newline character

HTTP/1.1 302 Moved Temporarily
Server: nginx/1.19.3
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: https://example.com/
Detectify: clrf

Any variable

In some cases, user-supplied data can be treated as Nginx variables. It is not clear why this happens, but as shown in H1 report, this situation is not uncommon or easy to test. If we search for the error message, we can see that it is found in SSI Filter Module , Which shows that this is caused by SSI

One way to test this is to set the quote header value:

curl -H 'Referer: bar' http://localhost/foo$http_referer | grep'foobar'

We scanned this misconfiguration and found several instances where users can print Nginx variable values. The number of vulnerable instances discovered has dropped, which may indicate that it has been patched

Original backend response read

Using Nginx's proxy_pass, it is possible to intercept errors and HTTP headers created by the backend. This is useful if you want to hide internal error messages and headers so they are handled by Nginx. If the backend answers one, Nginx will automatically provide a custom error page. But what if Nginx doesn't understand that this is an HTTP response?

If the client sends an invalid HTTP request to Nginx, the request will be forwarded to the backend as is, and the backend will respond with its original content. Then, Nginx will not be able to understand the invalid HTTP response and forward it to the client. Imagine a uWSGI application like this:

def application(environ, start_response):
   start_response('500 Error', [('Content-Type',
'text/html'),('Secret-Header','secret-info')])
   return [b"Secret info, should not be visible!"]

And use the following instructions in Nginx:

http {
   error_page 500 /html/error.html;
   proxy_intercept_errors on;
   proxy_hide_header Secret-Header;
}

If the response status of the backend is greater than 300, proxy_intercept_errors will provide a custom response. In the uWSGI application above, we will send a 500 Error response that will be intercepted by Nginx

proxy_hide_header is almost self-explanatory; it will hide any specified HTTP headers from the client

If we send a normal GET request, Nginx will return:

HTTP/1.1 500 Internal Server Error
Server: nginx/1.10.3
Content-Type: text/html
Content-Length: 34
Connection: close

But if we send an invalid HTTP request, such as:

GET /? XTTP/1.1
Host: 127.0.0.1
Connection: close

We will get the following response:

XTTP/1.1 500 Error
Content-Type: text/html
Secret-Header: secret-info
Secret info, should not be visible!

merge_slashes is set to close

The merge_slashes default, the slashes command is a mechanism to compress two or more slashes into one, so setting it to "on" /// will become /. If Nginx is used as a reverse proxy and the application being proxied is susceptible to local file inclusion, the use of extra slashes in the request may leave room to exploit it.

Likes(0)

Comment list count 0 Comments

No Comments