Nginx漏洞
Nginx能做到正向代理、反向代理、负载均衡、HTTP服务器等,强大的功能不言而喻,但也伴随着使用 上的风险,深入理解Nginx的漏洞有助于创建安全的业务系统。
Nginx解析漏洞
漏洞原理
Nginx的解析漏洞的出现和Nginx的版本没有关系,漏洞的产生是由于php配置问题导致的。 影响的范围:全版本 Nginx拿到文件路径(URI)/test.jpg/shell.php后,一看后缀是.php,便认为该文件是php文件,转交给 php去处理。php一看/test.jpg/shell.php不存在,便删去最后的/shell.php,又看/test.jpg存在,便 把/test.jpg当成要执行的文件了.
相关的配置:
# php.ini
cgi.fix_pathinfo=https://img-home.csdnimg.cn/images/20230724024https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=1&pos_id=7fnvOTFL59.png?origin_url=https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=1&pos_id=7fnvOTFL&pos_id=7fnvOTFL
# php-fpm.conf
security.limit_extensions = .php .jpg
cgi.fix_pathinfo=https://img-home.csdnimg.cn/images/20230724024https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL59.png?origin_url=https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL&pos_id=7fnvOTFL
开启这一选项有什么用呢?看名字就知道是对文件路径进行“修理”。何谓“修理”?举个例子,当php遇到 文件路径“/aaa.xxx/bbb.yyy/ccc.zzz”时,若“/aaa.xxx/bbb.yyy/ccc.zzz”不存在,则会去掉最后的 “/ccc.zzz”,然后判断“/aaa.xxx/bbb.yyy”是否存在,若存在,则把“/aaa.xxx/bbb.yyy”当做文件 “/aaa.xxx/bbb.yyy/ccc.zzz”,若“/aaa.xxx/bbb.yyy”仍不存在,则继续去掉“/bbb.yyy”,以此类推。
security.limit_extensions = .php .jpg
可执行的后缀,通常是因为需要PHP去执行一些静态文件,才会这样做配置,但是这样做了之后,就危险了。
漏洞复现
这里还是利用vulhub来进行复现,进入目录:vulhub/nginx/nginx_parsing_vulnerability
执行:
docker-compose up -d
访问浏览器:
默认情况下在上传文件目录下有一个图片码,我们可以访问来试试:
根据上面的介绍,我们可以在后面加上一个php后缀:
说明这个地方是存在漏洞的。
接下来直接上传一句话木马试一试:
没法上传,查看源码:
<?php
if (!empty($_FILES)):
// Check for errors
if($_FILES['file_upload']['error'] > 0){die('An error ocurred when uploading.');
}
if(!getimagesize($_FILES['file_upload']['tmp_name'])){die('Please ensure you are uploading an image.');
}
// Check filetype
if(stripos($_FILES['file_upload']['type'], 'image/') !== 0){die('Unsupported filetype uploaded.');
}
// Check filesize
if($_FILES['file_upload']['size'] > 500000){die('File uploaded exceeds maximum upload size.');
}
// Check filesize
if(!is_uploaded_file($_FILES['file_upload']['tmp_name'])) {die('File is not uploaded file');
}
$ext = pathinfo($_FILES['file_upload']['name'], PATHINFO_EXTENSION);
if (!in_array($ext, ['gif', 'png', 'jpg', 'jpeg'])) {die('Unsupported filetype uploaded.');
}
$new_name = __DIR__ . '/uploadfiles/' . md5($_FILES['file_upload']['name'])
. ".{$ext}";
if(!move_uploaded_file($_FILES['file_upload']['tmp_name'], $new_name)){die('Error uploading file - check destination is writeable.');
}
die('File uploaded successfully: ' . $new_name);
通过看源码,我们发现只能上传图片了,这个时候我们想到直接上传图片码:
漏洞防御
主要是两个配置文件中配置不当造成的。
https://img-home.csdnimg.cn/images/20230724024https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL59.png?origin_url=https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL&pos_id=7fnvOTFL. 修改配置文件vim 对应php.ini
将cgi.fix_pathinfo=https://img-home.csdnimg.cn/images/20230724024https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL59.png?origin_url=https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL&pos_id=7fnvOTFL,设置为0
2.修改配置文件vim 对应php-fpm.conf
将security.limit_extensions=,设置为: security.limit_extensions=.php,只允许php文件解析
Nginx 文件名逻辑漏洞(CVE-20https://img-home.csdnimg.cn/images/20230724024https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL59.png?origin_url=https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL&pos_id=7fnvOTFL3-4547)
漏洞原理
该漏洞影响版本:Nginx 0.8.4https://img-home.csdnimg.cn/images/20230724024https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL59.png?origin_url=https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL&pos_id=7fnvOTFL ~ https://img-home.csdnimg.cn/images/20230724024https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL59.png?origin_url=https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL&pos_id=7fnvOTFL.4.3 / https://img-home.csdnimg.cn/images/20230724024https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL59.png?origin_url=https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL&pos_id=7fnvOTFL.5.0 ~ https://img-home.csdnimg.cn/images/20230724024https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL59.png?origin_url=https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL&pos_id=7fnvOTFL.5.7
该漏洞利用了Nginx错误的解析了URL地址,导致可以绕过服务端限制,从而解析PHP文件,造成命令执 行的危害。根据nginx.conf文件中location中的定义,以.php结尾的文件都解析为php。
location ~ \.php$ {include fastcgi_params;fastcgi_pass https://img-home.csdnimg.cn/images/20230724024https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=1&pos_id=7fnvOTFL59.png?origin_url=https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=1&pos_id=7fnvOTFL&pos_id=7fnvOTFL27.0.0.https://img-home.csdnimg.cn/images/20230724024https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=1&pos_id=7fnvOTFL59.png?origin_url=https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=1&pos_id=7fnvOTFL&pos_id=7fnvOTFL:9000;fastcgi_index index.php;fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;fastcgi_param DOCUMENT_ROOT /var/www/html;
}
若我们访问的文件名为shell.gif[0x20][0x00].php,该文件名以.php结尾可以被FastCGI接收,FastCGI在 读取文件名时被00截断,导致读取的文件名为shell.gif[0x20],配合security.limit_extensions为空即可 利用成功。
为什么security.limit_extensions需要为空?
这样就可以解析任意文件了。
漏洞复现
进入文件夹:vulhub/nginx/CVE-20https://img-home.csdnimg.cn/images/20230724024https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL59.png?origin_url=https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL&pos_id=7fnvOTFL3-4547
执行:
docker-compose up -d
这个地方上传不了php后缀了,不用尝试了。
直接上传图片码:shell.gif,成功访问:
但是这个地方需要我们上传shell.gif[0x20] ,就是文件名后面需要加一个空额,不然后面找不到文件
windows不需要,因为windows会默认去除空格
放行即可。
现在想办法拿到shell,结合之前分析的,我们直接访问:
http://ip:8080/uploadfiles/shell.gifaa.php
然后抓包将两个a,一个修改为20,一个修改为00:
放到repeater模块进行测试:
发现可行,然后放包:
拿到探针:
这里解释一下为什么需要有空格:
经过查阅资料发现nginx在对url的解析过程中,当路径中存在’.’或url存在’\0’会有如下处理:
#!cpp
case sw_check_uri: ……case '.': r->complex_uri = https://img-home.csdnimg.cn/images/20230724024https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL59.png?origin_url=https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL&pos_id=7fnvOTFL; //此作为flag会判断使用
ngx_http_parse_complex_uri方法,对路径修复state = sw_uri; break;
casesw_check_uri: ……case '\0': //当遇到\0是,将会判断为非法字符return NGX_HTTP_PARSE_INVALID_REQUEST;
但如果nginx发现URI中存在空格会跳到如下代码:
上面代码执行完后state='sw_check_uri’然后继续处理URI中的剩余部分,这说明了如果空格和零截断符 相邻的话nginx就不会检测到零截断并放回错误了,这是一个逻辑漏洞,所以通过这种方式我们就可以在 URI中开心的使用零截断的,这就是CVE-20https://img-home.csdnimg.cn/images/20230724024https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL59.png?origin_url=https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL&pos_id=7fnvOTFL3-4547
注意,[0x20]是空格,[0x00]是\0,这两个字符都不需要编码。
在这里我们需要思考一下:
真正的利用场景? 执行系统命令? 反弹shell?
漏洞防御
https://img-home.csdnimg.cn/images/20230724024https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL59.png?origin_url=https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL&pos_id=7fnvOTFL.升级版本来的最直接
2.修改配置
Nginx 配置错误导致漏洞
漏洞原理
主要是配置不当造成的
影响范围:所有版本
漏洞复现
进入目录:vulhub/nginx/insecure-configuration
执行:
docker-compose up -d
运行成功后,Nginx将会监听8080/808https://img-home.csdnimg.cn/images/20230724024https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL59.png?origin_url=https%3A%2F%2Fimg-home.csdnimg.cn%2Fimages%2F20230724024159.png%3Forigin_url%3D1%26pos_id%3D7fnvOTFL&pos_id=7fnvOTFL/8082三个端口,分别对应三种漏洞。
CRLF注入漏洞
这个漏洞我没有想到好的利用方式,姑且认为这个地方确实存在这个漏洞吧。 Nginx会将$uri进行解码,导致传入%0a%0d即可引入换行符,造成CRLF注入漏洞。错误的配置文件示例(原本的目的是为了让http的请求跳转到https上):
然后直接访问:http://ip:8080/%0a%0dSet-Cookie:%20name=hsj
也可以注入xss:http://ip:8080/%0d%0aSet-Cookie:%20age=18%0d%0a%0d%0a
οnerrοr=alert(/xss/)>
只是这个要看浏览器。Chrome就不行。
目录穿越漏洞
Nginx在配置别名(Alias)的时候,如果忘记加/,将造成一个目录穿越漏洞。 错误的配置文件示例(原本的目的是为了让用户访问到/home/目录下的文件):
直接访问:
相当于直接穿越出了根目录。
add_header被覆盖
Nginx配置文件子块(server、location、if)中的add_header,将会覆盖父块中的add_header添加的 HTTP头,造成一些安全隐患。
/test2的location中又添加了X-Content-Type-Options头,导致父块中的add_header全部失效。 我们访问根:
我们看到在test2中引入了app.js
访问:
漏洞防御
注意配置即可。