目录
1 文件解析漏洞概述
1.1 概述
- 定义:解析漏洞主要是一些特殊文件被IIS、Apache、Nginx等服务在某种情况下解释成脚本文件格式并得以执行而产生的漏洞。
- 相关文章分布:
Nginx相关的文件解析漏洞参考本文;
Apache相关的文件解析漏洞参考《中间件文件解析漏洞基础知识及实验——Apache》;
IIS相关的文件解析漏洞参考《中间件文件解析漏洞基础知识及实验——IIS》。
1.2 Nginx 解析漏洞
1.2.1 空字节解析漏洞
- 概述:该漏洞影响版本为:0.5*, 0.6*, 0.7 <= 0.7.65, 0.8 <= 0.8.37,版本较老。
- 原因:在使用PHP-FastCGI执行php的时候,URL里面在遇到%00空字节时与FastCGI处理不一致,导致可以在非PHP文件中嵌入PHP代码,然后通过访问xxx.jpg%00.php来执行其中的代码。
1.2.2 文件名逻辑漏洞 CVE-2013-4547
- 概述:该漏洞影响版本为: Nginx 0.8.41 ~ 1.4.3 / 1.5.0 ~ 1.5.7,范围较广。
- 原因:这个漏洞其实和代码执行没有太大关系,其主要原因是错误地解析了请求的URI,错误地获取到用户请求的文件名,导致出现权限绕过、代码执行的连带影响。
- 漏洞产生过程:
- Nginx匹配到.php结尾的请求,就发送给fastcgi进行解析,常见的代码写法如下。
- 正常情况下(关闭pathinfo的情况下),只有.php后缀的文件才会被发送给fastcgi解析。而存在CVE-2013-4547的情况下,我们请求
1.gif[0x20][0x00].php
,这个URI可以匹配上正则 .php$,可以进入这个Location块;但进入后,由于fastcgi在查找文件时被\0截断,Nginx却错误地认为请求的文件是1.gif[0x20],就设置其为SCRIPT_FILENAME的值发送给fastcgi。 - fastcgi根据SCRIPT_FILENAME的值进行解析,最后造成了解析漏洞。
- 所以,我们只需要上传一个空格结尾的文件,然后在访问文件时诱导其以PHP解析。
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;
}
1.2.3 CGI-PHP 解析漏洞
- 概述:该漏洞常见于IIS7.0、IIS7.5、Nginx <8.03等中间件,当浏览器采用
1.jpg/.php
的方式访问1.jpg文件时,jpg文件会以PHP程序执行。 - 原因:该漏洞的产生原因与中间件无关,主要是PHP配置上CGI.fix_pathinfo参数值默认为1,将其设置为0可以避免这个漏洞。
- cgi.fix_pathinfo参数作用:看名字就知道是对文件路径进行“修理”。何谓“修理”?举个例子,当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”,以此类推。
2 实验
2.1 实验目的
- 加深对Nginx几种解析漏洞的理解;
- 掌握漏洞的检验及利用方法。
2.2 实验环境
- 在虚拟机安装CentOS系统,并完成图形化设置,可以参考文章《CentOS7虚拟机安装及界面图形化》。
- 部署Vulhub靶场环境。参考文章《CentOS上部署Vulhub靶场》。
- 需要不同靶场环境时,在官网查询相关靶场路径,进入对应路径进行实验即可。
2.3 实验一:空字符解析漏洞
- 暂时没有找到Nginx空字符漏洞环境,无法进行实验,仅简要描述该漏洞攻击的方式,以后有机会时间再练习。
- 步骤一,以图片马的方式提交文件以绕过。
- 步骤二,访问所上传的文件时,在文件后加上
%00.php
让服务器以PHP形式执行该文件,如IP+info.jpg%00.php
。
2.4 实验二:文件名逻辑漏洞
2.4.1 启用实验环境
- 参考Vulhub官网关于该漏洞的使用介绍,使用命令
cd /usr/CVE/vulhub/nginx/CVE-2013-4547
进入靶场安装目录(根据自己安装的位置灵活调整)。 - 使用命令
docker-compose up -d
启动靶场。
- 使用命令
docker ps -a
查询启动的容器。可以看到所启动的容器是采用8080端口来访问的。
2.4.2 踩坑排雷过程
- 上传文件名为info.php,内容代码为
<?php phpinfo();?>
。 - 真实机打开BurpSuite,在代理界面打开自带浏览器,访问靶机8080端口,URL为
192.168.1.10:8080
。
- 开启拦截功能,在网页中选中文件并点击提交按钮,可以看到BurpSuite成功拦截到请求,将该请求发送到Repeater模块。
- 将BurpSuite切换到repeater模块界面,将刚刚发送过来的请求点击send,可以看到响应为上传文件失败。
- 将文件名后缀修改为
.jpg
,点击send,发现响应中说move_uploaded_file函数执行出错了,结合之前《文件截断绕过攻击实验》中对该函数的了解,其出错可能是路径出了问题或是写入权限出了问题,但是在该实验中其实是SELinux设置的问题,相关解决方案参考文章《CentOS7部署Vulhub靶场后,在启动漏洞容器时弹出SELinux警告,致使网站无法正常执行文件上传功能》。
- 经过上面文章设置之后,接着继续实验。
- 再次将请求发送到repeater模块,将文件名修改为jpg后缀,并点击发送。可以看到右侧文件成功上传,说明靶场环境搭建成功。
2.4.3 实验步骤
- 将上述请求的后缀名后面再加一个空格,并点击发送。可以看到文件成功上传,且后缀带有空格。
- 使用火狐浏览器访问刚刚上传的文件,可以看到文件是存在的,但是由于不是图片格式所以显示不了。
- 本来想使用BurpSuite拦截该请求,不知道为什么拦不到,只能先复制上面浏览器访问时的URL,然后在repeater模块中新建一页,右键点击"Paste URL as request"。
- 点击后出现以下请求,点击发送收到响应。可以看到响应正常并回显了文件的内容,但是由于后缀名格式问题并没有执行。
- 在请求的文件后缀加上
..php
,注意最前面是一个空格,点击发送手动响应如下,没有找打对应的文件。
- 将请求切换到十六进制模式,修改第一个点对应的值变为空字符,原理类似空字符截断,发送后可以看到响应中执行了文件代码。
2.5 实验三:CGI-PHP 解析漏洞
2.5.1 启用实验环境
- 参考Vulhub官网关于该漏洞的使用介绍,使用命令
cd /usr/CVE/vulhub/nginx/nginx_parsing_vulnerability
进入靶场安装目录(根据自己安装的位置灵活调整)。 - 使用命令
docker-compose up -d
启动靶场。 - 使用命令
docker ps -a
查询启动的容器。
2.5.2 实验步骤
- 真实机打开浏览器,输入靶机IP访问靶场。
- 使用命令
http://192.168.1.10/uploadfiles/nginx.png
访问靶机网站下的文件,可以看到图片正常显示。
- 使用命令
http://192.168.1.10/uploadfiles/nginx.png/.php
访问靶机网站下的文件,可以看到文件中的PHP代码被成功执行,由此也可知该图片为图片马。
2.5.3 防御
将php.ini文件中的cgi.fix_pathinfo的值设置为0,并将该行代码签名的分号去掉,保存并重启phpstudy。
3 总结
- 文件上传漏洞第一个条件是文件成功上传且没能过滤掉恶意代码;第二个条件是让代码执行。
- 对于第一个条件,存在着前端JS检测绕过、服务端MIME类型绕过、服务端后缀名绕过、文件内容绕过等,其根本目的是要上传文件。
- 对于第二个条件,当中间件为Nginx时:
(1)优先考虑绕过后缀名时采用恶意代码能够执行的后缀,这样文件能直接执行;
(2)其次,当Nginx版本较老时,比如老于小于0.8.37,考虑利用空字节解析漏洞执行该文件;
(3)最后,考虑利用CVE-2013-4547和CGI-PHP解析漏洞来执行该文件。