解析漏洞 – 若水斋 https://blog.werner.wiki Try harder Sat, 10 Nov 2018 11:20:26 +0000 zh-Hans hourly 1 https://wordpress.org/?v=6.8.3 https://blog.werner.wiki/wp-content/uploads/2018/11/cropped-ql1-1-32x32.jpg 解析漏洞 – 若水斋 https://blog.werner.wiki 32 32 文件解析漏洞总结-IIS https://blog.werner.wiki/file-resolution-vulnerability-iis/ https://blog.werner.wiki/file-resolution-vulnerability-iis/#respond Thu, 17 Aug 2017 09:47:43 +0000 http://blog.werner.wiki/?p=318 IIS(Internet Information Services)是微软出品的灵活、安全、易于管理的Web服务器。
在总结过ApacheNginx的文件解析漏洞后,现在来总结下IIS的文件解析漏洞。

默认后缀

这其实不是文件解析漏洞,但能达到和文件解析漏洞一样的效果。IIS总是和asp联系在一起。一般而言,asp程序文件的后缀为.asp,但实际上,IIS默认地还会解析其他后缀的文件为asp文件。如下图是我在Windows7中开启IIS7.5对asp支持后处理程序映射的默认设置:

由上图可知,.cer文件和.asp文件的处理程序一样,均为IsapiModule(实际上就是aspnet_isapi.dll),故.cer文件也被当做asp程序执行。经测试,确实是这样。

网上找到的资料说.asa、.cer和.cdx都是默认被IIS6.0当做asp执行的后缀。我在Windows XP SP3 + IIS5.1和Windows Server 2003 + IIS6.0中测试发现,.asa和.cer是被当做asp执行的后缀,.cdx不行。

总结一下,可能被IIS当做asp程序执行的后缀有:

  .asp
  .cer
  .asa
  .cdx

IIS 6.0 文件解析漏洞

这个真的是漏洞,不是什么特性。测试发现,IIS5.1和IIS7.5无此漏洞。

IIS 6.0在处理含有特殊符号的文件路径时会出现逻辑错误,从而造成文件解析漏洞。这一漏洞有两种完全不同的利用方式:

  /test.asp/test.jpg
  test.asp;.jpg

第一种是新建一个名为“test.asp”的目录,该目录中的任何文件都被IIS当做asp程序执行(特殊符号是“/”);第二种是上传名为“test.asp;.jpg”的文件,虽然该文件真正的后缀名是“.jpg”,但由于含有特殊符号“;”,仍会被IIS当做asp程序执行。

漏洞原理见《IIS 文件名解析漏洞扼要分析》。该文链接可能已失效,百度文章标题,可以找到转载版本。原理大抵是IIS 5.x/6.0在从文件路径中读取文件后缀时,遇到一个“.”后,便进入了一种截断状态,在该状态下遇到特殊符号——“/”和“;”,都会进行截断,只保留特殊符号前的部分,即:“.asp”,从而认为文件后缀为“.asp”。

下图是我在Windows Server 2003 + IIS6.0中进行测试确认该漏洞存在的截图:

IIS6.0存在文件解析漏洞

遇到php时文件解析问题

  test.jpg/.php

IIS和Nginx在这一点上是一样的,一看到URL中文件后缀是.php,便无论该文件是否存在,都直接交给php处理,而php又默认开启“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”,以此类推。

若有文件test.jpg,访问时在其后加/.php,便可以让IIS把“test.jpg/.php”交给php,php“修理”文件路径“test.jpg/.php”得到“test.jpg”,该文件存在,便把该文件作为php程序执行了。下图所示,是在 IIS7.5+php5.3+FastCGI 下的测试情况:

成功执行php代码

asp没有“cgi.fix_pathinfo”,所以不存在这一问题。

Windows操作系统文件命名规则

Windows操作系统中,文件名不能以空格或“.”开头,也不能以空格或“.”结尾。当把一个文件命名为以空格或“.”开头或结尾时,会自动地去掉开头和结尾处的空格和“.”。利用此特性,也可能造成“文件解析漏洞”。

此外,Windows操作系统中的文件名是不区分大小写的,xxx.asp和xxx.Asp、xxx.php和xxx.PHp具有同样的效果。

参考资料

]]>
https://blog.werner.wiki/file-resolution-vulnerability-iis/feed/ 0
文件解析漏洞总结-Nginx https://blog.werner.wiki/file-resolution-vulnerability-nginx/ https://blog.werner.wiki/file-resolution-vulnerability-nginx/#comments Sun, 13 Aug 2017 09:42:52 +0000 http://blog.werner.wiki/?p=309 与Apache相比,Nginx算是后起之秀,但大有赶超之势。百度一番,又谷歌一番,最终只找到了三个已公开的、关于Nginx的解析漏洞,记录如下。

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

利用方式:

  /test.jpg/test.php

测试:

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

  <?php phpinfo() ?>

在浏览器中访问 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.conf

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

  security.limit_extensions = .php .jpg

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

php代码被成功执行

由上述原理可知,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给出:

不存在的普通文件

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

不存在的php文件

查看错误日志,找到了:

  FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 127.0.0.1, server: localhost, request: "GET /123123.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "127.0.0.1"

由此可知Nginx确实只看了后缀就直接把123123.php交给php处理了,这一文件不存在也是php做出的判断。

%00截断

影响范围:

  0.5., 0.6., 0.7 <= 0.7.65, 0.8 <= 0.8.37 ?

利用方式:

  /test.jpg%00.php

测试:

服务器为Nginx1.4.6,浏览器中访问 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.7

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

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

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

让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码),如下图所示:

修改请求

修改完毕后Forward该请求,在浏览器中看到:

成功显示图片

我们已经成功地利用了漏洞!但这有什么用呢?我们想要的是代码被执行。

继续测试,准备文件“test.jpg ”,注意文件名的最后一个字符是空格,文件内容为:

  <?php phpinfo() ?>

用Burp Suite抓包并修改,原本的URL是:http://192.168.56.101/test.jpg…php ,将jpg后的第一个“.”改为20,第二个“.”改为00,如下图所示:

修改请求

修改完毕后Forword该请求,在浏览器中看到:

  Access denied.

好吧,又是这个。打开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"

这说明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;
  }

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

  http://127.0.0.1/protected/s.html

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

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

成功访问到文件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-dev

还要安装php:

  sudo apt-get install php5-fpm

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

  sudo apt-get install nginx

安装的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;
  }

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

]]>
https://blog.werner.wiki/file-resolution-vulnerability-nginx/feed/ 1
文件解析漏洞总结-Apache https://blog.werner.wiki/file-resolution-vulnerability-apache/ https://blog.werner.wiki/file-resolution-vulnerability-apache/#respond Wed, 09 Aug 2017 08:52:29 +0000 http://blog.werner.wiki/?p=294 我最为熟悉的便是Apache了,先来研究它的文件解析漏洞。百度许久,又谷歌一番,最终发觉,Apache关于文件解析,似乎只有三种“漏洞”。之所以打引号是因为我觉得这三种“漏洞”都不是Apache的漏洞,只是其特性,而很多程序员不了解这种特性,故而写出有问题的代码,这才给黑客可趁之机,造成漏洞。但大家都称呼这是Apache的文件解析漏洞,我也只好随大流了。

1.多后缀名

先说第一种特性:多后缀名。这是怎么的一种鲜为人知的特性呢?原来是这样的,Apache认为,一个文件可以有多个后缀,如:werner.txt.png.mp3。这一文件,放在Windows里,毫无疑问,就是个mp3文件,Windows只认最后一个“.”及其后面的字符“mp3”,觉得该文件后缀为“.mp3”,这也是大多数操作系统、应用软件的处理方式、是正常人的习惯。而在Apache中,则可能有所不同,如果有必要,Apache会从后(右)往前(左),一一辨别后缀。何时有必要?当Apache不认识某个后缀时,便有必要。如某文件名为:werner.mp3.html.qwe.arex,Apache在处理时,先读取最后一个后缀,为“.arex”,一看,这啥玩意啊,不认识,继续读取下一个后缀“.qwe”,一看,呀,这又是啥,还是不认识,继续读下一个后缀“.html”,一看,哦,这是个超文本标记语言文件,俗称网页文件,这回认识了,也就不继续读下一个后缀了。若是所有后缀都看完了没有一个认识怎么办?此时就会把该文件当做默认类型进行处理了,一般来说,默认类型是text/plain。据说在Apache的配置文件中搜索“DefaultType”就能看到默认类型的明确定义了,但我却不知为何,没有找到。

哪些后缀Apache认识,哪些不认识?有一个名为mime.types的文件,其中记录着Apache认识的后缀。在Ubuntu下,该文件位于/etc/mime.types,在Windows下,该文件位于C:/apache/conf/mime.types(类似这样的,注意Apache的安装路径)。该文件是一个一对多的映射表,定义了某一种文件类型对应的几种后缀。除了该文件,在Apache的配置文件中,还可以用AddCharset语句添加映射,如:

  AddCharset us-ascii   .ascii .us-ascii
  AddCharset ISO-2022-CN .iso2022-cn .cis

mime.types是个很长的文件,大概看了下,Apache认识的后缀比我多多了。节选部分如下所示:

  application/java-archive          jar
  application/m3g                   m3g
  application/java-vm               class
  application/javascript            js
  application/json                  json
  text/html                         html htm shtml
  text/x-diff                       diff patch
  video/x-flv                       flv
  video/x-la-asf                    lsf lsx
  video/x-mng                       mng
  video/x-ms-asf                    asf asx
  video/x-ms-wm                     wm

这一特性会带来什么问题呢?网站往往有上传文件的功能,但一定不想让用户上传程序,因为这很可能会危害网站安全,故而会检查上传文件的后缀名,若是.php,则拒绝上传(假设这是个php站)。此时用户只需上传文件evildoer.php.qwe,若是程序员不了解Apache的这一特性,编写的程序检查后缀时只看“.qwe”,而认为这不是程序文件,允许上传,则用户成功地绕过了上传时的安全检查,上传了php程序文件。该文件的最后一个后缀“.qwe”是Apache不认识的,故而Apache会以倒数第二个后缀“.php”为准,把该文件当做是php文件,解析执行。

这总是奏效的吗?按理来说,由于这是特性而不是漏洞,所以适用于所有版本的Apache。这一奇怪的特性,说不定正是Apache的自豪之处呢。但是,在我的测试中却发现,类似aaa.php.xxx的文件并不会被作为php程序执行,而是被当成文本文件,返回给浏览器,在浏览器中可以看到php源码,而不是执行结果。测试环境是Ubuntu14.04+Apache2.4.7+php5。

这是怎么回事?难道前面几百字都是废话,说的是错的?我们来做个实验。准备一个文件,内容随意,命名为test.jpg.aaa,放置在Apache中,然后在浏览器中访问它,结果如下图所示:

可见浏览器是将该文件作为图片处理的。浏览器为何认为test.jpg.aaa是图片呢?aaa可不是图片文件的后缀。这是因为服务器的响应HTTP头中的Content-Type字段值为image/jpeg,浏览器看到image/jpeg,便知这是图片文件。这说明服务器(此处即Apache)是把test.jpg.aaa当做图片的,也说明,前面分析的Apache的多后缀处理是没有错的。

那么aaa.php.xxx为何没有被作为php代码执行呢?我猜是这样的,当然只是我的猜测,实在是找不到相关资料,只好猜了。Apache看到文件aaa.php.xxx,按照多后缀名的解析规则,认为该文件是php程序文件,把该文件作为php程序文件处理。怎么处理呢?交给php解释器,Apache本身并不懂php。而php解释器却有着和Apache不同的后缀解析规则,可能只认最后一个后缀,故而认为aaa.php.xxx不是php程序文件,拒绝执行。在我的测试环境中,php以模块(module)的模式工作于Apache的领导下。这种模式下php接受到领导Apache分配的任务——aaa.php.xxx,一看,不是php程序文件,没法执行,但也没有报错,而是返回了文件内容本身。php还可以以FASTCGI的模式工作于Apache中,此种模式下php遇到类似aaa.php.xxx这种不是php程序的文件,会触发500错误。

php本身是如何识别文件的呢?我在Apache的模块的配置文件中找到了php5.conf,内容如下:

  <FilesMatch ".+\.ph(p[345]?|t|tml)$">
      SetHandler application/x-httpd-php
  </FilesMatch>
  <FilesMatch ".+\.phps$">
      SetHandler application/x-httpd-php-source
      # Deny access to raw php sources by default
      # To re-enable it's recommended to enable access to the files
      # only in specific virtual host or directory
      Order Deny,Allow
      Deny from all
  </FilesMatch>
  # Deny access to files without filename (e.g. '.php')
  <FilesMatch "^\.ph(p[345]?|t|tml|ps)$">
      Order Deny,Allow
      Deny from all
  </FilesMatch>

  # Running PHP scripts in user directories is disabled by default
  #
  # To re-enable PHP in user directories comment the following lines
  # (from <IfModule ...> to </IfModule>.) Do NOT set it to On as it
  # prevents .htaccess files from disabling it.
  <IfModule mod_userdir.c>
      <Directory /home/*/public_html>
          php_admin_flag engine Off
      </Directory>
  </IfModule>

阅读上示配置文件可知,被当做php程序执行的文件名要符合正则表达式:

    ".+\.ph(p[345]?|t|tml)$"

其中“$”符号在正则中匹配结束,故而可知php本身确实是只看最后一个后缀的。就算Apache把某文件当php程序,php自己不认它,也是无用。

进一步试验,把php5.conf文件中刚刚提到的正则表达式的“$”换成“\.”,即:

  ".+\.ph(p[345]?|t|tml)\."

然后重启Apache使配置文件生效,再在浏览器中访问aaa.php.xxx,这次,aaa.php.xxx果然被当做php程序执行了,在浏览器中,看到的是程序执行结果而不是源码。这也从侧面验证了,我的猜测是正确的。测试完之后,一定要记得改回去。

2.罕见后缀

计算机世界自开天辟地以来,便自由多彩。还记得mime.types文件吗?在该文件中搜索“php”这三个字母,结果如下所示:

  werner@Yasser:~$ cat /etc/mime.types | grep php
  #application/x-httpd-php                      phtml pht php
  #application/x-httpd-php-source               phps
  #application/x-httpd-php3                     php3
  #application/x-httpd-php3-preprocessed        php3p
  #application/x-httpd-php4                     php4
  #application/x-httpd-php5                     php5

还记得正则表达式”.+\.ph(p[345]?|t|tml)$”吗,该正则表达式匹配的不仅仅有php,还有php3、php4、php5、pht和phtml。

好吧,原来不仅php,就连phtml、pht、php3、php4和php5都是Apache和php认可的php程序的文件后缀。我原本只知道“.php”的,真是大开眼界。这就好比,不仅py是Python程序文件的后缀,还有pyc和pyo也都是。写上传过滤规则的程序员是否博学多识,也知道这些知识呢?若是不知道,岂不是又生漏洞。利用这些“罕见”的后缀名,也可能绕过安全检查,干些“坏事”。

我在Ubuntu14.04+Apache2.4.7中进行测试,先准备文件text.php,其内容是经典的Hello World:

  <?php echo 'HELLO WORLD'; ?>

然后在浏览器中打开它,成功显示“HELLO WORLD”。再修改该文件后缀为各种后缀,进行测试。测试结果是,以php、phtml、pht、php3、php4和php5为后缀,能成功看到“HELLO WORLD”;以phps为后缀,会报403错误,Forbidden;以php3p为后缀,会在浏览器中看到源码。

3.妙用.htaccess

.htaccess是Apache的又一特色。一般来说,配置文件的作用范围都是全局的,但Apache提供了一种很方便的、可作用于当前目录及其子目录的配置文件——.htaccess(分布式配置文件)。

要想使.htaccess文件生效,需要两个条件,一是在Apache的配置文件中写上:

  AllowOverride All

若这样写则.htaccess不会生效:

  AllowOverride None

二是Apache要加载mod_Rewrite模块。加载该模块,需要在Apache的配置文件中写上:

  LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so

若是在Ubuntu中,可能还需要执行命令:

  sudo a2enmod rewrite

配置完后需要重启Apache。

需要注意Apache可能有多个配置文件,后加载的配置文件会覆盖先加载的配置文件中的配置。所以在某个配置文件中将AllowOverride设置成All,若是其后加载的某个配置文件中AllowOverride的设置是None,则也是没有用的。一般来说,先加载httpd.conf,再加载conf.d/中的配置文件,最后加载sites-enabled/中的配置文件。

这意味着,.htaccess并不总是有效的。而且不幸的是,在我的测试环境中.htaccess默认无效。好吧,为了测试,我只好将它改为有效。以下讨论均在.htaccess有效的前提下进行。

.htaccess文件可以配置很多事情,如是否开启站点的图片缓存、自定义错误页面、自定义默认文档、设置WWW域名重定向、设置网页重定向、设置图片防盗链和访问权限控制。但我们这里只关心.htaccess文件的一个作用——MIME类型修改。如在.htaccess文件中写入:

  AddType application/x-httpd-php xxx

就成功地使该.htaccess文件所在目录及其子目录中的后缀为.xxx的文件被Apache当做php文件。另一种写法是:

  <FilesMatch "shell.jpg">
    SetHandler application/x-httpd-php
  </FilesMatch>

该语句会让Apache把shell.jpg文件解析为php文件。

下面是一次测试,测试前已经打开Apache对.htaccess文件的支持。在网站根目录中准备如下文件树:

  │
  ├── htaccess_test/
  │   ├── .htaccess
  │   ├── shell.jpg
  │   ├── type.xxx
  │   └── test/
  │       ├── shell.jpg
  │       └── type.xxx
  ├── shell.jpg
  └── type.xxx

其中,文件.htaccess的内容为:

  AddType application/x-httpd-php xxx

  <FilesMatch "shell.jpg">
  SetHandler application/x-httpd-php
  </FilesMatch>

文件shell.jpg和type.xxx的内容相同,均为:

  <?php echo 'HELLO WORLD'; ?>

然后在浏览器中访问各文件,结果如下表所示:

访问路径 访问结果
/type.xxx <?php echo ‘HELLO WORLD’; ?>
/shell.jpg 加载失败的图片
/htaccess_test/type.xxx HELLO WORLD
/htaccess_test/shell.jpg HELLO WORLD
/htaccess_test/test/type.xxx HELLO WORLD
/htaccess_test/test/shell.jpg HELLO WORLD

这一测试结果和预期是相符的。

但是,按照前面的猜测,就算Apache认为type.xxx是php文件,php自己不这么认为,不也是不能执行的吗?这次怎么就能执行了,好生奇怪。但不管怎么说,我们都已经知道,当.htaccess文件有效时,用.htaccess文件可以很好地设置文件后缀的解析方式。

参考资料

]]>
https://blog.werner.wiki/file-resolution-vulnerability-apache/feed/ 0
文件解析漏洞总结-Introduction https://blog.werner.wiki/file-resolution-vulnerability-introduction/ https://blog.werner.wiki/file-resolution-vulnerability-introduction/#respond Mon, 07 Aug 2017 08:50:20 +0000 http://blog.werner.wiki/?p=291 前言

前几天研究FCKeditor的上传漏洞,深深感觉到上传漏洞是和解析漏洞联系在一起的。而我对文件解析漏洞又不甚了解,向来是用到再查,效率极低,故而现在想要认真地学习总结下文件解析漏洞。学习方法便是寻找相关文章,阅读后再自己搭建模拟环境,一一尝试,最后将自己试验结果,记录在博客中。参考到的所有文章在各博文末尾均给出了链接。整个学习过程,最耗时的便是安装各种虚拟机与软件,搭建好环境后,真正的测试,往往只需一瞬间。虽如此,然常言道,耳听为虚,眼见为实,不亲眼看看,我总不免有所疑惑。

什么是文件解析漏洞

计算机如何知道一个文件是什么类型的文件?是文本、图片、音乐还是视频?方法很多,这里只说最简单的一种:看后缀名。后缀名是.txt的文件便是文本文件,是.jpg的便是图片,是.mp3的便是音乐,是.mp4的便是视频。但是后缀名是.png的文件也是图片啊?对,正是这种复杂性,导致了文件解析漏洞的出现。文件后缀千千万,程序编写者难以考虑所有后缀;且新后缀不断出现,老软件难以追随潮流。若计算机老把图片文件当成音乐文件而去播放它,自然即无法看图,又无法听歌,这便是个bug了,若利用这个bug还可以干些事情,bug便不仅仅是bug了,还是漏洞了。

我们知道,今天丰富多彩的Web世界是由各种各样的动态语言支撑的,前端有JavaScript,后端有php、jsp、asp等。在一个Web服务器上,既有脚本语言程序文件,又有文本、图片、视频等等文件。Web服务器要能够准确区分哪些文件是程序、哪些文件不是程序。因为程序文件是要被执行的,所谓执行程序,便是操纵计算机干事情。计算机只知道按命令干事情,并不知道自己干的是好事情还是坏事情。如何区分文件是程序还是非程序?一般来说,还是看后缀名。如index.php便是程序,logo.png便不是程序。网站的设计者可能允许用户随意替换文件logo.png(这是很常见的,如修改用户头像),但绝对不能让用户修改文件index.php分毫。若logo.png真的仅仅是个图片,那么便难以对网站所在的计算机(习惯上称网站所在的计算机为服务器)造成危害,但一旦logo.png被当做程序执行,用户便可以构造上传恶意的logo.png文件,危害服务器。正常情况下这是不可能的事情,只有在有漏洞时这才可能发生,这种漏洞便被称为文件解析漏洞。

总结下,文件解析漏洞是服务器错误地将非程序文件当做程序文件并解释执行从而造成危害的漏洞。

这完全是我按照个人理解做的总结,仅供参考。由上述总结可知,文件解析漏洞的错在服务器,进一步讲是服务器软件,具体地讲,便是Apache、Nginx和IIS这样的Web服务器软件。由于是漏洞,当然和软件及版本都有密切关系,就算是同一软件、同一版本,不同配置,打没打补丁,也可能导致有或没有漏洞。故而文件解析漏洞,在一处存在,在另一处很可能就不存在了。这也正是漏洞引人入胜的地方,犹如神龙,藏头露尾。

系列文章

]]>
https://blog.werner.wiki/file-resolution-vulnerability-introduction/feed/ 0