一、 CVE-2013-4547_Nginx 文件名逻辑漏洞
影响版本:Nginx 0.8.41 ~ 1.4.3 / 1.5.0 ~ 1.5.7
漏洞原理
这个漏洞其实和代码执行没有太大关系,其主要原因是错误地解析了请求的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]`,就设置其为`SCRIPT_FILENAME`的值发送给fastcgi。
fastcgi根据`SCRIPT_FILENAME`的值进行解析,最后造成了解析漏洞。
所以,我们只需要上传一个空格结尾的文件,即可使PHP解析之。
再举个例子,比如很多网站限制了允许访问后台的IP:
```
location /admin/ {
allow 127.0.0.1;
deny all;
}
```
我们可以请求如下URI:`/test[0x20]/../admin/index.php`,这个URI不会匹配上location后面的`/admin/`,也就绕过了其中的IP验证;但最后请求的是`/test[0x20]/../admin/index.php`文件,也就是`/admin/index.php`,成功访问到后台。(这个前提是需要有一个目录叫“test ”:这是Linux系统的特点,如果有一个不存在的目录,则即使跳转到上一层,也会爆文件不存在的错误,Windows下没有这个限制)
漏洞复现
靶场:192.168.4.10_ubuntu
#docker-compose up -d
环境启动后,访问`http://your-ip:8080/`即可看到一个上传页面。
这个环境是黑名单验证,我们无法上传php后缀的文件,需要利用CVE-2013-4547。我们上传一个“test1.png ”,注意后面的空格:
访问`http://your-ip:8080/uploadfiles/tset1.gif[0x20][0x00].php`,即可发现PHP已被解析:
二、 CVE-2017-7529_Nginx越界读取缓存漏洞
漏洞原理
Nginx在反向代理站点的时候,通常会将一些文件进行缓存,特别是静态文件。缓存的部分存储在文件中,每个缓存文件包括“文件头”+“HTTP返回包头”+“HTTP返回包体”。如果二次请求命中了该缓存文件,则Nginx会直接将该文件中的“HTTP返回包体”返回给用户。
如果我的请求中包含Range头,Nginx将会根据我指定的start和end位置,返回指定长度的内容。而如果我构造了两个负的位置,如(-600, -9223372036854774591),将可能读取到负位置的数据。如果这次请求又命中了缓存文件,则可能就可以读取到缓存文件中位于“HTTP返回包体”前的“文件头”、“HTTP返回包头”等内容。
复现漏洞
#docker-compose up -d
访问`http://your-ip:8080/`,即可查看到Nginx默认页面,这个页面实际上是反向代理的8081端口的内容。
调用`python3 poc.py http://your-ip:8080/`,读取返回结果:
可见,越界读取到了位于“HTTP返回包体”前的“文件头”、“HTTP返回包头”等内容。
如果读取有误,请调整poc.py中的偏移地址(605)。
三、 Nginx 配置错误导致漏洞
靶场搭建
#docker-compose up -d
运行成功后,Nginx将会监听8080/8081/8082三个端口,分别对应三种漏洞。
Mistake 1. CRLF注入漏洞
Nginx会将`$uri`进行解码,导致传入%0a%0d即可引入换行符,造成CRLF注入漏洞。
错误的配置文件示例(原本的目的是为了让http的请求跳转到https上):
```
location / {
return 302 https://$host$uri;
}
```
Payload: `http://your-ip:8080/%0a%0dSet-Cookie:%20a=1`,可注入Set-Cookie头。
利用《[Bottle HTTP 头注入漏洞探究](https://www.leavesongs.com/PENETRATION/bottle-crlf-cve-2016-9964.html)》中的技巧,即可构造一个XSS漏洞:
CRLF是”回车 + 换行”(\r\n)的简称。在HTTP协议中,HTTP Header与HTTP Body是用两个CRLF分隔的,浏览器就是根据这两个CRLF来取出HTTP 内容并显示出来。所以,一旦我们能够控制HTTP 消息头中的字符,注入一些恶意的换行,这样我们就能注入一些会话Cookie或者HTML代码,所以CRLF Injection又叫HTTP Response Splitting,简称HRS。
CRLF是比XSS危害更大的安全问题,对于CRLF最简单的利用方式是注入两个\r\n,之后在写入XSS代码,来构造一个xss。
Mistake 2. 目录穿越漏洞
Nginx在配置别名(Alias)的时候,如果忘记加`/`,将造成一个目录穿越漏洞。
错误的配置文件示例(原本的目的是为了让用户访问到/home/目录下的文件):
```
location /files {
alias /home/;
}
```
Payload: `http://your-ip:8081/files../` ,成功穿越到根目录:
Mistake 3. add_header被覆盖
Nginx配置文件子块(server、location、if)中的`add_header`,将会覆盖父块中的`add_header`添加的HTTP头,造成一些安全隐患。
如下列代码,整站(父块中)添加了CSP头:
```
add_header Content-Security-Policy "default-src 'self'";
add_header X-Frame-Options DENY;
location = /test1 {
rewrite ^(.*)$ /xss.html break;
}
location = /test2 {
add_header X-Content-Type-Options nosniff;
rewrite ^(.*)$ /xss.html break;
}
```
但`/test2`的location中又添加了`X-Content-Type-Options`头,导致父块中的`add_header`全部失效:
XSS可被触发,IE浏览器:
四、 Nginx 解析漏洞复现
影响版本信息:
- Nginx 1.x 最新版
- PHP 7.x最新版
由此可知,该漏洞与Nginx、php版本无关,属于用户配置不当造成的解析漏洞。
漏洞搭建
#docker-compose up -d
访问`http://your-ip/uploadfiles/nginx.png`和`http://your-ip/uploadfiles/nginx.png/.php`即可查看效果。
正常显示:
增加`/.php`后缀,被解析成PHP文件:
访问`http://your-ip/index.php`可以测试上传功能,上传代码不存在漏洞,但利用解析漏洞即可getshell:
正常上传图片码
解析漏洞