首页技术博客 服务器运维 正文

文件解析漏洞总结-Nginx

2018-06-17 1395 0条评论

之前符文浩在博客中发布了WINDOWS在IIS下如何禁止解析漏洞,http://blog.fuwenhao.com/post/29.html

而今天符文浩给大家带来在LINUX的NGINX环境下是如何禁止解析漏洞的教程哦!

与Apache相比,Nginx算是后起之秀,但大有赶超之势。百度一番,又谷歌一番,最终只找到了三个已公开的、关于Nginx的解析漏洞,记录如下。

Nginx中php配置错误导致的解析漏洞

利用方式:

  /test.jpg/test.php12

测试:

首先准备文件test.jpg,内容为:

  <?php phpinfo() ?>12

在浏览器中访问 http://127.0.0.1/test.jpg 显示图片解析错误。在浏览器中访问 http://127.0.0.1/test.jpg/test.php ,显示:“Access denied.” 。这就有意思了,test.jpg是文件不是目录,test.php更是根本就不存在的文件,访问/test.jpg/test.php没有报404,而是显示“Access denied.” 。

Nginx拿到文件路径(更专业的说法是URI)/test.jpg/test.php后,一看后缀是.php,便认为该文件是php文件,转交给php去处理。php一看/test.jpg/test.php不存在,便删去最后的/test.php,又看/test.jpg存在,便把/test.jpg当成要执行的文件了,又因为后缀为.jpg,php认为这不是php文件,于是返回“Access denied.”。

这其中涉及到php的一个选项:cgi.fix_pathinfo,该值默认为1,表示开启。开启这一选项有什么用呢?看名字就知道是对文件路径进行“修理”。何谓“修理”?举个例子,当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”,以此类推。

该选项在配置文件php.ini中。若是关闭该选项,访问 http://127.0.0.1/test.jpg/test.php 只会返回找不到文件。但关闭该选项很可能会导致一些其他错误,所以一般是开启的。

目前我们还没能成功执行代码,因为新版本的php引入了“security.limit_extensions”,限制了可执行文件的后缀,默认只允许执行.php文件。来做进一步测试。找到php5-fpm配置文件php-fpm.conf,若不知道在哪,可用如下命令搜索:

  sudo find / -name php-fpm.conf12

我的测试环境中,该文件位于/etc/php5/fpm/php-fpm.conf。修改该文件中的“security.limit_extensions”,添加上.jpg,添加后如下所示:

  security.limit_extensions = .php .jpg12

这样,php便认为.jpg也是合法的php文件后缀了,再在浏览器中访问 http://127.0.0.1/test.jpg/test.php ,看到php被成功执行,如下图所示:

3322.jpg

http://127.0.0.1/test.jpg/test.xxx/test.php 也是可以执行的。

上面的测试均在Nginx1.4.6中进行。这一漏洞是由于Nginx中php配置不当而造成的,与Nginx版本无关,但在高版本的php中,由于“security.limit_extensions”的引入,使得该漏洞难以被成功利用。

为何是Nginx中的php才会有这一问题呢?因为Nginx只要一看URL中路径名以.php结尾,便不管该文件是否存在,直接交给php处理。而如Apache等,会先看该文件是否存在,若存在则再决定该如何处理。cgi.fix_pathinfo是php具有的,若在php前便已正确判断了文件是否存在,cgi.fix_pathinfo便派不上用场了,这一问题自然也就不存在了。(2017.08.15:IIS在这一点和Nginx是一样的,同样存在这一问题)

做个小实验,分别访问两个不存在的文件123123.xxx和123123.php,虽然都返回404,但一看页面,也该知这两个文件的处理流程是不同的。

下图是访问123123.xxx的结果,404由Nginx给出:

333.jpg


下图是访问123123.php的结果,404页面和上图不同:

123123.jpg

http://127.0.0.1/test.jpg%00.php ,返回“400 Bad Request”,代码未执行,测试失败。实在是安不好又找不到这么老的Nginx,遂放弃测试。

%00截断似乎是一个大类,什么时候有空专门研究下。

CVE-2013-4547

CVE-2013-4547是一个还算新的漏洞,影响范围也比较大:

  0.8.41~1.4.3, 1.5 <= 1.5.712

顺便一提,截止本文写作时,Nginx的最新版本是1.13.4 。

这一漏洞的原理是非法字符空格和截止符(\0)会导致Nginx解析URI时的有限状态机混乱,危害是允许攻击者通过一个非编码空格绕过后缀名限制。是什么意思呢?举个例子,假设服务器上存在文件:“file.aaa ”,注意文件名的最后一个字符是空格。则可以通过访问:

http://127.0.0.1/file.aaa \0.bbb12

让Nginx认为文件“file.aaa ”的后缀为“.bbb”。

来测试下,这次测试在Nginx/1.0.15中进行。首先准备一张图片,命名为“test.html ”,注意,文件名含有空格。然后在浏览器中访问该文件,会得到一个404,因为浏览器自动将空格编码为%20,服务器中不存在文件“test.html%20”。

测试目标是要让Nginx认为该文件是图片文件并正确地在浏览器中显示出来。我们想要的是未经编码的空格和截止符(\0),怎么办呢?使用Burp Suite抓取浏览器发出的请求包,修改为我们想要的样子,原本的URL是:http://192.168.56.101/test.htmlAAAphp ,将第一个“A”改成“20”(空格符号的ASCII码),将第二个“A”改成“00”(截止符),将第三个“A”改成“2e”(“.”的ASCII码),如下图所示:

3啊.jpg


http://192.168.56.101/test.jpg…php ,将jpg后的第一个“.”改为20,第二个“.”改为00,如下图所示:

sshh.jpg


好吧,又是这个。打开Nginx的错误日志,在其中也可以看到:

  FastCGI sent in stderr: "Access to the script '/usr/local/nginx/html/test.jpg ' has been denied (see security.limit_extensions)" while reading response header from upstream, client: 192.168.56.102, server: localhost, request: "GET /test.jpg .php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "192.168.56.101"12

这说明Nginx在接收到这一请求后,确实把文件“test.jpg ”当做php文件交给php去执行了,只是php看到该文件后缀为“.jpg ”而拒绝执行。这样,便验证了Nginx确实存在该漏洞。

但不知为何,不管我怎样设置,php都不肯把“test.jpg ”当做php文件执行。看来“security.limit_extensions”威力强大,一招破万法。

CVE-2013-4547还可以用于绕过访问限制,虽然和文件解析漏洞无关,但也记录在这里。

首先在网站根目录下新建一个目录,命名为protected,在目录protected中新建文件s.html,内容随意。然后在Nginx的配置文件中写上:

  location /protected/ {
    deny all;
  }123

以禁止该目录的访问。接着在网站根目录下新建一个目录,名为“test ”,目录名的最后一个字符是空格,该目录用于触发漏洞。最后来进行验证,直接访问:

  http://127.0.0.1/protected/s.html12

返回“403 Forbidden”。利用漏洞访问:

  http://127.0.0.1/test /../protected/s.html12

成功访问到文件s.html。注意上示URL中的空格,不要将空格编码。

为成功利用漏洞,我们在测试中准备了名字以空格结尾的文件和目录,这是因为在linux中,文件名是可以以空格结尾的。若不准备这样的文件,漏洞可以成功触发,但结果却是404,找不到类似“test.jpg ”这样的文件。而在Windows中,文件名不能以空格结尾,所以Windows程序遇到文件名“test.jpg ”会自动去掉最后的空格,等同于访问“test.jpg”,基于这样的原因,这一漏洞在Windows中会很容易利用。

附:编译安装Nginx

为验证漏洞,需要安装Nginx。为安装有漏洞的版本,不使用apt-get,而是编译安装。我使用的操作系统是Ubuntu14.04,安装了nginx-1.0.15,需要安装以下依赖:

  sudo apt-get install libpcre3 libpcre3-dev
  sudo apt-get install zlib1g.dev
  sudo apt-get install libssl-dev1234

还要安装php:

  sudo apt-get install php5-fpm12

后来发现,在新安装的Ubuntu14.04中,不先update直接用:

  sudo apt-get install nginx12

安装的Nginx的版本是1.4.6,也不是很新。还想要安装更老版本的Nginx(<= 0.8.37)结果总是编译失败,只好放弃。

要开启Nginx对php的支持,去掉配置文件中关于php的注释并重启Nginx即可:

  location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    #   # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
    #
    #   # With php5-cgi alone:
    #   fastcgi_pass 127.0.0.1:9000;
    #   # With php5-fpm:
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
  }1234567891011

配置时还遇到许多问题,但只要翻阅错误日志,知道是什么问题,便可对症下药,一一解决。若不知道问题是什么,只看到个400、500,这样子是很难解决问题的。


文章版权及转载声明

本文作者:符文浩 网址:http://blog.fuwenhao.com/post/89.html 发布于 2018-06-17
文章转载或复制请以超链接形式并注明出处。

发表评论

快捷回复:

评论列表 (暂无评论,1395人围观)参与讨论

还没有评论,来说两句吧...

取消
微信二维码
微信二维码
支付宝二维码