本节将详细的解释一下文件解析相关内容,作为我的专栏《WEB安全原理和多种防御方法解读》中的一节。
本文所涉及的文件解析主要指的是WEB领域的文件解析。当访问一个网站或者某个网站特定的页面,实际上是在向网站后台请求对某个文件进行访问,如图1是对于百度首页的访问:
图1
可以看到虽然没有指定具体的文件名,但是在在网站开发中,首页往往不需要指定文件名,但是在后台通常会默认路由到对于index.html等文件的访问。可以看到网站的后台会对前台映射对应的文件进行解析,有的会接受前台穿过来的参数按需响应,这就是最基本的文件解析过程。
文件解析之漏洞原理
对于文件解析漏洞的定义往往指的就是,WEB后台在对于文件解析过程中存在的设计以及实现缺陷的统称。通俗点讲就是非脚本文件被意外按照脚本的语法进行解析。现代的web软件开发中,文件解析的工作是WEB服务器的功能,因此文件解析漏洞往往集中在一些WEB服务器中,包括apache,nginx,微软的IIS等。历史上这些流行的WEB服务器均出现了多次的文件解析漏洞,如下:
apache
对于apache服务器来说,曾经出现过将1.php.xxx的按照php语法进行解析,主要原因在apache解析策略从右至左,对于无法识别的后缀会忽略,寻找下一个后缀。
Nginx
对Nginx服务器来说1.jpg%00.php文件曾经被当做Php进行解析。初步看好像没有问题,但是在寻找该文件的时候,%00即ASCII的0值,会截断文件名,因此最终解析的文件是1.jpg。
IIS
对于IIS服务器来说,曾经出现过.php文件夹下的文件都被当做Php进行解析。也曾出现过1.asp;.xxx作为asp进行解析,主要原因是IIS不解析分号后面的内容。
思考一下上述漏洞的成因,多数因为程序员的设计缺陷,比如取文件后缀方法不对。上述有的漏洞被分配了CVE的编号,有的则没有。对于没有分配CVE的漏洞,很多的问题会被忽视,也意味着对应的资产存在着风险。
文件解析之漏洞举例
文件解析功能属于底层的功能,主要由WEB服务器承担,因此这些漏洞多数存在于WEB服务器之中,历史上漏洞的数量并不是很多。但是这种漏洞一旦出现,影响的范围将非常的广。同时由于漏洞解析漏洞通常情况下不会直接造成验证的影响,一般是和文件上传,目录穿越,文件包含等漏洞进行配合形成较为严重的危害。下面介绍一个存在CVE编号的两个漏洞
CVE-2013-4547
该漏洞是nginx服务器早期的一个文件解析绕过个漏洞,影响的是PHP服务。当解析HTTP请求中的文件路径时候,存在着绕过情况,导致可以通过带构造有0值的文件路径实现对于指定文件按照php的语法进行解析,如下图2 NVD中的介绍:
图2
由于该漏洞是Nginx服务器漏洞,属于基础性服务软件,因此可以说影响所有使用Nginx托管PHP服务的网站。由于该漏洞产生的后果是能够按照Php解析任意文件。因此存在着诸多的手段构造非PHP后缀名文件,例如SQL注入,文件上传等,和该漏洞配合则可以获取webshell。因此从该漏洞从影响面,Nginx的流程程度,以及可能潜在的后果来看,这是一个非常严重的漏洞。下面根据公开的POC以及Nginx修复的patch进一步的分析该漏洞。其中exp(该漏洞的利用程序)如图3所示:
图3
图中POC可以看到想要利用该漏洞,第一步是先上传一个1.gif 的文件,文件上传是非敏感文件后缀,因此是比较容易的,当然也可以通过SQL注入写文件等方式。第二步是构造一个特殊的路径,路径的关键是存在这一个0值,使得1.gif 被当做php格式文件解析。只要1.gif 存在一句话木马,则可以获取webshell.
对比漏洞patch内容,如下图4:
图4
对比补丁来看,可能很难发现其根本原因在什么地方,需要结合其他部分的解读。首先该函数的名称叫做
ngx_http_parse_request_line
,由函数名可以看出该函数的作用是解析HTTP的请求行,类似图5所示:
图5
HTTP的请求行是三段式,使用空格进行间隔,因此nginx在解析的时候也是按照空格区分HTTP的方法,URI部分以及HTTP版本部分。由于文本字符的复杂性,可以看到
ngx_http_parse_request_line
在进行URL解析的时候使用了如下枚举表示每个解析步骤状态(可以查看nginx_http_parse.c文件):
enum{
sw_start =0,
sw_method,
sw_spaces_before_uri,
sw_schema,
sw_schema_slash,
sw_schema_slash_slash,
sw_host_start,
sw_host,
sw_host_end,
sw_host_ip_literal,
sw_port,
sw_host_http_09,
sw_after_slash_in_uri,
sw_check_uri,
sw_check_uri_http_09,
sw_uri,
sw_http_09,
sw_http_H,
sw_http_HT,
sw_http_HTT,
sw_http_HTTP,
sw_first_major_digit,
sw_major_digit,
sw_first_minor_digit,
sw_minor_digit,
sw_spaces_after_digit,
sw_almost_done
} state;
其中sw_check_uri表示检查URI中的特殊字符状态,sw_check_uri_http_09表示检查HTTP版本信息状态。正常情况下URI中如果出现空格是要求编码的,就是为了使得URI中的空格不和request line中的空格产生歧义,但是上述的POC空格没有使用%20进行编码,直接采用了20的ASCII值,因此在遇到空格的时候,会进入HTTP版本检查状态的时候,即sw_check_uri_http_09,如图6:
图6
此时的ch值为0值,因此进入default分支,在下一轮的循环会进入sw_check_uri中,如图7:
图7
此时ch的值是点,因此会进入取文件后缀的流程,即该文件会被当做php文件进行解析。可以看到在修复之前,通过空格加0值实现了绕过。在图4中的修复,使得指针前移,则进入图7中的流程时,ch的值为0值,解析报错,实现对于漏洞的修复。事实上可以看到,nginx是考虑到0值截断的情况,如果没有空格,则URI解析是失败的。但是没有考虑到空格作为HTTP request line分隔符和0值组合之后的情况。这个时候可能存在疑问,漏洞的关键点是空格的歧义,那么空格和其他特殊字符的组合能够利用成功呢。虽然可以进入到PHP解析的流程,但是在后续利用的时候存在不利之处。因为0值在C语言中表示字符串的结束,在真正利用时候取的是0值之前的字符,因此上传的时候可以传输非php后缀文件。
同时也可以看到sw_check_uri_http_09的分值组合是非常的庞大,导致不可能设计那么多的测试用例进行覆盖,这些是目前测试领域的难题,即很难去穷尽复杂状态机所有的状态。
CVE-2017-15715
该漏洞是Apache httpd服务器的2.4.0至2.4.29版本中的一个文件解析漏洞。正常情况下,httpd服务器解析php文件的时候,只会把.php后缀的文件按照php的语法进行解析,但是利用该漏洞,可以构造非php文件后缀,使其按照PHP的语法进行解析,如下图8 NVD中的介绍:
图8
该漏洞的POC如下图9:
图9
图9可以看到1.php%0a的后缀不是php文件,最终被当成php文件解析,因此从这个层面来讲是存在解析的问题的。正是由于解析上存在着漏洞,因此可以通过上传1.php%0a这个文件,在上传阶段可以绕过一些黑名单的限制(通常黑名单不允许上传.php文件后缀)。即在上传阶段绕过黑名单的限制,又在解析阶段利用了解析的漏洞。图10为该漏洞修补patch:
图10
图10可以看到主要的修复是新增了AP_REG_DOLLAR_ENDONLY 变量,该变量注释写的很清楚,即匹配字符串的结尾,需要明确的是不包括\n换行符。options是进行正则匹配时候的控制符,可以看到修复之后options默认值是不匹配换行符的。前面的POC以及修复的patch,都是围绕着换行符在讨论,主要的原因在于,httpd服务器把哪些文件作为Php解析是在配置文件中定义的,该版本的默认配置如下:
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
.php$本意是想.php结尾的文件按照php格式进行解析。但是在正则匹配中,美元符的作用如下图11:
而apach的http服务器在没有修复之前,options中是默认设置multiline属性的,因此可以匹配换行符,这也是前面1.php%0a能够解析成功的原因。而图10中的修复正是通过改变options中的默认值,使其不能匹配到换行符。
文件解析之潜在危害
前面从原理和示例两份方面针对目录解析进行了简单阐述,目录解析会导致哪些后果呢?单纯的文件解析应该来说只会让不是某种类型后缀的文件按照某种文件类型进行解析,看似直接的影响不是很大。但是从前面的POC来看,配合文件上传,文件解析是可以直接获取webshell的。包括文章开篇所提到的不具备CVE编号的漏洞,都可以配合文件上传加以利用获取webshell。
本文为CSDN村中少年原创文章,未经允许不得转载,博主链接这里。
版权归原作者 村中少年 所有, 如有侵权,请联系我们删除。