购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.5 任意文件上传

文件上传功能普遍存在于我们使用的We b应用中,如头像、视频等都需要用户通过上传文件达到与服务器交互的目的。尽管这在很大程度上丰富了用户体验,但如果对用户上传的文件没有加以控制,就可能造成不堪设想的后果。

任意文件上传漏洞是指由于文件上传功能的实现代码没有严格限制用户上传的文件后缀以及文件类型,导致攻击者能够向某个可通过We b访问的目录上传恶意文件,该文件被脚本解析器执行后,就会在远程服务器上执行恶意脚本。

1.5.1 客户端校验

当客户端选中要上传的文件并点击上传时,如果没有向服务端发送任何数据信息,就对本地文件进行检测,判断是否是允许上传的文件类型,那么这种方式就称为客户端本地JavaScript检测。

1.检测方法

首先我们开启Burp Suite,对上传的动作进行抓包,如图1-116所示。

图1-116 选取文件后开启代理准备抓包

点击“上传”后发现文件被拦截,但是Burp Suite没有反应,这说明我们并没有和远程服务器进行交互,如图1-117所示。

图1-117 文件被拦截后并没有抓到包

由此可以判断,我们的文件其实是被浏览器端的JavaScript脚本拦截了。

2.绕过方法

这种拦截方式本质上形同虚设,因为对于一般人来说,可能根本不会去上传恶意的脚本,但对于了解黑客技术的人,这样的拦截根本起不到任何作用。

首先我们可以将恶意脚本的后缀名改成被允许的类型,例如.jpg、.png等,上传时开启抓包,将上传动作的HTTP包拦截下来,如图1-118所示。

图1-118 拦截到的上传包

在抓到包的此刻,我们已经绕过了前端JavaScript的检测,剩下的就是将包中“shell.jpg”的后缀名改为.php并发送,如图1-119所示。

图1-119 恶意脚本上传成功

1.5.2 服务端校验

在进行服务端校验之前,我们要明确黑白名单的意义和区别。简单来说,黑名单就是后端上传代码逻辑规定用户不能上传某种类型的文件,除此之外其他任意类型文件皆可上传,例如当用户准备上传PHP恶意脚本的时候,程序给出的反馈是“不允许上传.php文件”。反之,白名单的后端上传代码逻辑是规定用户只能上传某种类型的文件,其他任意类型的文件都不可上传,比如准备上传.php恶意脚本的时候,程序的反馈会变成“只允许上传.jpg文件”。判断程序使用了哪种限制方式,我们就可以更快作出应对策略。

1.黑名单绕过

下面介绍几种黑名单绕过方式。

大小写绕过利用了代码过滤不严谨,忽略了大小写,同时解析脚本时对文件名大小写不敏感的漏洞。例如我们上传shell.php文件和上传shell.php文件达到的效果是相同的。当shell.php上传不成功时,我们可以考虑上传shell.php来绕过,如图1-120~图1-122所示。

图1-120 正常上传.php文件失败

图1-121 使用大小写绕过后保存成功

图1-122 成功解析

有些开发者在检测上传文件的后缀名时,在最后会添加去除空格等特殊字符的操作,我们可以利用该特点进行黑名单绕过,如图1-123所示。

图1-123 在检测完后缀名后进行去空格操作

我们在上传的时候可以上传shell.php(注意最后有一个空格),这样就可以绕过黑名单,达到任意文件上传的目的,如图1-124所示。

图1-124 上传成功

可以看到,表面上保存的文件名也是带空格的,但是实际访问时自行去掉了空格,如图1-125所示。

图1-125 成功解析

我们上传文件的最终目的是将可解析的脚本上传到服务器上,但是有时候开发人员设置的限制非常严格,.php文件很难保存到网站目录的位置,因此我们可以考虑其他可解析的格式,通过上传这些可解析格式的文件达到获取WebShell的目的。

通常来说,一些中间件的默认配置项就设定了一些可解析的格式,如.phtml、.phps、.pht、.php2、.php3、.php4、.php5等。我们使用常见的.phtml举例,如图1-126、图1-127所示。

图1-126 成功上传shell.phtml

图1-127 成功解析

双写后缀绕过主要是利用了这个特点:有些程序的逻辑是在检测到非法后缀名后没有中断上传,而是使用了删除非法后缀名并依然将其保存在服务器上。如图1-128所示,程序如果检测到后缀名在黑名单数组中,就将其替换成空,但依旧将替换后的文件保存在服务器中。

图1-128 将检测到的非法后缀名替换成空

我们可以利用这个特点,构造“shell.pphphp”。因为替换只发生了一次,这样文件名被替换后就变成了“shell.php”,正好符合我们的预期,如图1-129所示。

图1-129 文件依然保存为shell.php

2.白名单绕过

下面介绍几种白名单绕过方式。

00截断就是在HTTP包的后缀名处加入00字符(不是空格),在文件被保存时00后面的内容就会被截断并丢弃,从而使得保存的文件名并不是我们真正上传的文件名,达到获取WebShell的目的。

00字符指的是ASCII码为00的字符,它并非空格,而是一个不可见字符,它可以有很多种编码形式,如十六进制形式0x00、URL编码形式%00等。在利用时我们用哪一种形式,主要取决于要截断的文件名在什么位置。

如果上传的文件名在URL上,我们就要用到%00,因为URL在解析时会自动解码一次,而%00经过解码后就变成了00字符,正好可以达到我们想要的效果。这种情况不太常见,读者了解即可,如图1-130所示。

图1-130 在URL上进行00截断

我们直接访问upload下的shell.php即可,后面的内容实际上已经被截断了,效果如图1-131所示。

图1-131 成功获取WebShell

如果上传的文件在POST数据的地方,我们就需要使用00的形式。最方便的做法是在Burp Suite截取的包中找到要截断的地方并打上%00,选择Convert selection→URL→URL-decode,如图1-132所示。

图1-132 对%00进行手动URL解码

解码后上传即可,最终就达到了截断的效果,如图1-133所示。

图1-133 成功截断

下面介绍Apache解析漏洞的方法。Apache是通过从右到左开始判断文件扩展名来解析文件,如果文件扩展名不被识别,就再往左判断。比如cimer.php.owf.rar,对于.owf和.rar这两种后缀,Apache不可识别,Apache会把cimer.php.owf.rar解析成.php。

Apache 2.2.11版本的解析漏洞如图1-134所示。上传*.php.cimer后缀的文件,将其成功解析为*.php文件,并且可以被“菜刀”等WebShell管理工具连接,获得网站权限。

下面介绍IIS6.0解析漏洞的方法。目录解析/xx.asp/xx.jpg,在网站中建立a.asp文件夹,其目录内任何扩展名的文件都被IIS当作.asp文件来解析并执行,如图1-135~图1-137所示。

图1-134 cimer.php.owf.rar被解析为.php文件

图1-135 建立一个名为a.asp的文件夹

图1-136 在该文件夹下创建test.txt

图1-137 test.txt被当作.asp脚本执行

文件解析xx.asp;.jpg,在IIS6.0下,分号后面的内容不会被解析,如cimer.asp;.jpg会被当作cimer.asp,如图1-138、图1-139所示。

图1-138 代码没有被直接显示

图1-139 蚁剑连接成功

我们可以巧妙利用.htaccess和.user.ini绕过限制。.htaccess是一个纯文本文件,里面存放着Apache服务器配置相关的指令,主要的作用有:URL重写、自定义错误页面、MIME类型配置以及访问权限控制等。主要体现在伪静态的应用、图片防盗链、自定义404错误页面、阻止/允许特定IP/IP段、目录浏览与主页、禁止访问指定文件类型、文件密码保护等方面。用途范围主要针对当前目录。

在文件上传时,如果实在无法绕过对.php后缀名的限制,可以尝试上传.htaccess配置文件,使其他后缀名的文件被当作.php文件解析。

首先创建一个.htaccess文件,如果系统提示不能创建没有名字的文件,可以打开cmd,通过echo命令创建,具体如图1-140所示。

图1-140 创建.htaccess文件

文件内容如图1-141所示。

图1-141 .htaccess文件内容

将文件上传后,在同目录下再上传一个图片马,如图1-142~图1-144所示。

图1-142 上传.htaccess文件

图1-143 上传后缀为.jpg的WebShell

图1-144 .jpg文件被当作.php解析

.user.ini文件的利用方式与.htaccess大致相同,但相对而言还是有一定区别的。如果说.htaccess可以理解为临时的Apache配置文件,那么.user.ini就可以看作临时的php.ini配置文件。而两者之间最大的不同就是这两个配置文件所能控制的内容不同。

.htaccess文件通过控制解析其他类型文件的方式,达到获取WebShell的目的,很显然这个特点是php.ini不具备的。我们可以换一个思路,在php.ini中有两个配置参数auto_append_file和auto_prepend_file,两者本质上区别不大,一个是在运行.php文件之前包含指定文件,一个是在运行.php文件之后包含指定文件,我们可以利用这个特点来获取WebShell。但这个方法有一个比较多余的限制,就是在当前目录下必须有一个.php文件,哪怕是空的。如果不存在.php文件,将无法进行包含操作。

首先我们创建.user.ini文件,如图1-145所示。

图1-145 .user.ini文件内容

然后上传.user.ini和shell.jpg,如图1-146、图1-147所示。

图1-146 上传.user.ini文件

图1-147 上传后缀为.jpg的WebShell

这样我们去访问同目录下的.php文件时(如readme.php、index.php等),就会自动包含shell.jpg的内容,从而获取WebShell,如图1-148所示。

图1-148 成功获取WebShell

3.MIME类型绕过

MIME类型检测是服务端对客户端上传文件的Content-Type类型进行检测,如果是白名单所允许的,则可以正常上传,否则上传失败,如图1-149、图1-150所示。

图1-149 修改MIME类型

图1-150 上传成功

4.文件内容检测绕过

一般文件内容检测使用getimagesize()函数进行,判断文件是否是一个有效的图片文件,如果是,则允许上传,否则不允许上传。

上传一个没有gif文件头的.gif文件进行测试,如图1-151所示。

图1-151 上传没有gif文件头的.gif文件

上传出错,由此推测服务端可能对上传的文件内容进行了检测。用Burp Suite进行代理,然后选择图片马进行上传,如图1-152、图1-153所示。

图1-152 上传带有gif文件头的图片马

图1-153 上传成功

将文件名改回PHP_pass.gif.php,然后重新上传,如图1-154、图1-155所示。

图1-154 上传带有gif文件头的.php文件

图1-155 上传成功

上传成功,且蚁剑可以连接,如图1-156、图1-157所示。

图1-156 图片马没有被当作图片解析

图1-157 “菜刀”连接成功

1.5.3 任意文件上传进阶

1.条件竞争

条件竞争是指基于网站允许上传任意文件,检查上传文件是否包含WebShell,如果包含则删除该文件,并且如果文件不是指定类型,那么使用unlink指令删除文件。上传的文件在程序运行过程中在服务器上短暂保存了一下,无论程序执行得多快,理论上如果不停地访问和上传,总会有访问成功的时候。我们可以这样规定上传的文件内容,如图1-158所示。

图1-158 上传的文件内容

程序的逻辑很简单,运行时会在同目录下生成一个名字为shell.php的WebShell。首先抓取上传该文件的HTTP包,如图1-159所示。

图1-159 抓取上传包

再抓取一个访问包,如图1-160所示。

图1-160 抓取访问包

将以上两个报文都发送至intruder模块。在报文的URL中加上?a=1,并将a设置为变量,用于不断发送,如图1-161所示。

访问包同理,如图1-162所示。

图1-161 添加多余变量

图1-162 访问包添加多余变量

选择类型为Numbers的字典,数量为10000,如图1-163所示。

图1-163 设置字典

开启攻击,当访问包出现200状态码时,表示成功写入,如图1-164所示。

图1-164 成功写入

尝试访问生成的info.php,漏洞利用成功。

2.php-gd渲染绕过

php-gd渲染是后端调用了PHP的GD库,提取了文件中的图片数据,然后重新渲染,这样图片中插入的恶意代码可能会被删掉。经过测试发现,不论直接修改文件头制作的图片马,还是利用copy命令制作的图片马,都无法避免其中的木马语句被过滤掉。该漏洞是把一句话木马插入图片数据,这样经过渲染后的数据还是会被保留下来。利用该漏洞需要注意以下两点。

● 不是每张图片都可以利用,在不超出长传限制的范围内图片越大越好。

● 需要先上传一张图片,上传成功后再从网页下载,经过处理后再次上传,不可以直接处理并上传。

具体看下面的示例。

首先我们准备好一张图片,手机拍摄的照片就可以,要注意不要暴露自己的经纬度信息。然后将图片正常上传,如图1-165所示。

图1-165 正常上传图片

将该图片下载到本地后使用GitHub上的脚本处理一下,如图1-166所示。脚本地址为https://github.com/Medicean/VulApps/blob/master/c/cmseasy/1/jpg_payload.php。

图1-166 处理下载的图片

处理结束后上传图片,利用文件包含漏洞即可,如图1-167所示。

图1-167 成功利用 X6ONkzOvM53o+FvwtAD/VnTpNlzQKQmdsj8w04gNo/ZzTfVrIYycuYpIS6xCkCnW

点击中间区域
呼出菜单
上一章
目录
下一章
×

打开