TP漏洞之文件上传总结

js检查

一般都是在网页上写一段javascript脚本,校验上传文件的后缀名,有白名单形式也有黑名单形式。

查看源代码可以看到有如下代码对上传文件类型进行了限制:

我们可以看到对上传文件类型进行了限制。

绕过方法

  1. 我们直接删除代码中onsubmit事件中关于文件上传时验证上传文件的相关代码即可。

或者可以不加载所有js,还可以将html源码copy一份到本地,然后对相应代码进行修改,本地提交即可。

  1. burp改包,由于是js验证,我们可以先将文件重命名为js允许的后缀名,在用burp发送数据包时候改成我们想要的后缀。

即可上传成功

黑名单

特殊可解析后缀

这里做了黑名单处理,我们可以通过特殊可解析后缀进行绕过。

绕过方法

之前在https://www.jianshu.com/p/1ccbab572974中总结过,这里不再赘述,可以使用php3,phtml等绕过。

上传.htaccess

我们发现黑名单限制了很多后缀名,但是没有限制.htaccess .htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置.通过htaccess文件,可以实现:网页301重定向、自定义404页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。

绕过方法

我们需要上传一个.htaccess文件,内容为:

这样所有的文件都会解析为php,接下来上传图片马即可

后缀大小写绕过

我们发现对.htaccess也进行了检测,但是没有对大小写进行统一。

绕过方法

后缀名改为PHP即可

空格绕过

黑名单没有对文件中的空格进行处理,可在后缀名中加空格绕过。

绕过方法

点绕过

windows会对文件中的点进行自动去除,所以可以在文件末尾加点绕过,不再赘述

::$DATA绕过

同windows特性,可在后缀名中加” ::$DATA”绕过,不再赘述

路径拼接绕过

这里对文件名进行了处理,删除了文件名末尾的点,并且把处理过的文件名拼接到路径中

绕过方法

这里我们可以构造文件名1.PHP. . (点+空格+点),经过处理后,文件名变成1.PHP.,即可绕过。

双写绕过

绕过方法

这里我们可以看到将文件名替换为空,我们可以采用双写绕过:1.pphphp

白名单

绕过方法

这里检查Content-type,我们burp抓包修改即可绕过:

%00 截断

$img_path直接拼接,因此可以利用%00截断绕过

绕过方法

然后直接访问/upload/1.php即可

00截断(post)

save_path是通过post传进来的,还是利用00截断,但这次需要在二进制中进行修改,因为post不会像get对%00进行自动解码。

绕过方法

接下来访问1.php即可

文件内容检查

文件幻数检测

主要是检测文件内容开始处的文件幻数,比如图片类型的文件幻数如下, 要绕过jpg 文件幻数检测就要在文件开头写上下图的值:

Value = FF D8 FF E0 00 10 4A 46 49 46

要绕过gif 文件幻数检测就要在文件开头写上下图的值

Value = 47 49 46 38 39 61 要绕过png 文件幻数检测就要在文件开头写上下面的值

Value = 89 50 4E 47

然后在文件幻数后面加上自己的一句话木马代码就行了

文件相关信息检测

图像文件相关信息检测常用的就是getimagesize()函数

只需要把文件头部分伪造好就ok 了,就是在幻数的基础上还加了一些文件信息

有点像下面的结构

GIF89a (...some binary data for image...) <?php phpinfo(); ?> (... skipping the rest of binary data ...)

本次环境中的文件头检测,getimagesize,php_exif都可以用图片马绕过:

copy normal.jpg /b + shell.php /a webshell.jpg

文件加载检测

一般是调用API 或函数去进行文件加载测试,常见的是图像渲染测试,甚至是进行二次渲染(过滤效果几乎最强)。对渲染/加载测试的攻击方式是代码注入绕过,对二次渲染的攻击方式是攻击文件加载器自身。

对渲染/加载测试攻击- 代码注入绕过

可以用图像处理软件对一张图片进行代码注入

用winhex 看数据可以分析出这类工具的原理是

在不破坏文件本身的渲染情况下找一个空白区进行填充代码,一般会是图片的注释区

对于渲染测试基本上都能绕过,毕竟本身的文件结构是完整的

二次渲染

imagecreatefromjpeg二次渲染它相当于是把原本属于图像数据的部分抓了出来,再用自己的API 或函数进行重新渲染在这个过程中非图像数据的部分直接就隔离开了

if (isset($_POST['submit'])){    // 获得上传文件的基本信息,文件名,类型,大小,临时文件路径    $filename = $_FILES['upload_file']['name'];    $filetype = $_FILES['upload_file']['type'];    $tmpname = $_FILES['upload_file']['tmp_name'];    $target_path=UPLOAD_PATH.basename($filename);    // 获得上传文件的扩展名    $fileext= substr(strrchr($filename,"."),1);    //判断文件后缀与类型,合法才进行上传操作    if(($fileext == "jpg") && ($filetype=="image/jpeg")){        if(move_uploaded_file($tmpname,$target_path))        {            //使用上传的图片生成新的图片            $im = imagecreatefromjpeg($target_path);            if($im == false){                $msg = "该文件不是jpg格式的图片!";                @unlink($target_path);            }else{                //给新图片指定文件名                srand(time());                $newfilename = strval(rand()).".jpg";                $newimagepath = UPLOAD_PATH.$newfilename;                imagejpeg($im,$newimagepath);                //显示二次渲染后的图片(使用用户上传图片生成的新图片)                $img_path = UPLOAD_PATH.$newfilename;                @unlink($target_path);                $is_upload = true;            }        } else {            $msg = "上传出错!";        }    }else if(($fileext == "png") && ($filetype=="image/png")){        if(move_uploaded_file($tmpname,$target_path))        {            //使用上传的图片生成新的图片            $im = imagecreatefrompng($target_path);            if($im == false){                $msg = "该文件不是png格式的图片!";                @unlink($target_path);            }else{                 //给新图片指定文件名                srand(time());                $newfilename = strval(rand()).".png";                $newimagepath = UPLOAD_PATH.$newfilename;                imagepng($im,$newimagepath);                //显示二次渲染后的图片(使用用户上传图片生成的新图片)                $img_path = UPLOAD_PATH.$newfilename;                @unlink($target_path);                $is_upload = true;                           }        } else {            $msg = "上传出错!";        }    }else if(($fileext == "gif") && ($filetype=="image/gif")){        if(move_uploaded_file($tmpname,$target_path))        {            //使用上传的图片生成新的图片            $im = imagecreatefromgif($target_path);            if($im == false){                $msg = "该文件不是gif格式的图片!";                @unlink($target_path);            }else{                //给新图片指定文件名                srand(time());                $newfilename = strval(rand()).".gif";                $newimagepath = UPLOAD_PATH.$newfilename;                imagegif($im,$newimagepath);                //显示二次渲染后的图片(使用用户上传图片生成的新图片)                $img_path = UPLOAD_PATH.$newfilename;                @unlink($target_path);                $is_upload = true;            }        } else {            $msg = "上传出错!";        }    }else{        $msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!";    }}

本关综合判断了后缀名、content-type,以及利用imagecreatefromgif判断是否为gif图片,最后再做了一次二次渲染。

绕过方法

得去找图片经过GD库转化后没有改变的部分,再将未改变的部分修改为相应的php代码。

条件竞争

if(isset($_POST['submit'])){    $ext_arr = array('jpg','png','gif');    $file_name = $_FILES['upload_file']['name'];    $temp_file = $_FILES['upload_file']['tmp_name'];    $file_ext = substr($file_name,strrpos($file_name,".")+1);    $upload_file = UPLOAD_PATH . '/' . $file_name;    if(move_uploaded_file($temp_file, $upload_file)){        if(in_array($file_ext,$ext_arr)){             $img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;             rename($upload_file, $img_path);             $is_upload = true;        }else{            $msg = "只允许上传.jpg|.png|.gif类型文件!";            unlink($upload_file);        }    }else{        $msg = '上传出错!';    }}

这里先将文件上传到服务器,然后通过rename修改名称,再通过unlink删除文件,因此可以通过条件竞争的方式在unlink之前,访问webshell。

绕过方法

然后不断访问webshell:

上传成功。

本文分享自微信公众号 - 风帆(wdswhf)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏孤独的S

教你如何用python批量下载B站的视频

一开始,我本来是想要做一个将视频转换为字符串的视频的,首先就得找一个视频做素材,紧接我就逛逛B站,找我想要的视频,然后发现B站并没有下载的按钮,于是乎我就想,...

39830
来自专栏算法与编程之美

安全|Dvwa渗透测试网站搭建

DVWA(Damn Vulnerable Web Application)是一个用来进行安全脆弱性鉴定的PHP/MySQL Web应用,旨在为安全专业人员测试自...

12000
来自专栏前端自习课

【JS】376- Axios 使用指南

1、 利用npm安装npm install axios --save 2、 利用bower安装bower install axios --save 3、 直接利...

9320
来自专栏后端技术漫谈

[SpringBoot]快速配置多数据源(整合MyBatis)

由于业务需求,需要同时在SpringBoot中配置两套数据源(连接两个数据库),要求能做到service层在调用各数据库表的mapper时能够自动切换数据源,也...

9830
来自专栏Devops专栏

Django 2.1.7 通过dwebsocket实现websocket

上面已经安装好了dwebsocket库,那么如何使用呢? 使用的方法有两种情况,如下:

14900
来自专栏FreeBuf

利用PHP的字符串解析特性Bypass

我们知道PHP将查询字符串(在URL或正文中)转换为内部$GET或的关联数组$POST。例如:/?foo=bar变成Array([foo] => "bar")。...

8700
来自专栏网站漏洞修补

渗透测试该如何全面检测网站漏洞

昨天给大家普及到了渗透测试中执行命令漏洞的检测方法,今天抽出时间由我们Sine安全的渗透工程师来讲下遇到文件包含漏洞以及模板注入漏洞的检测方法和防御手段,本文仅...

16570
来自专栏FreeBuf

AuthCov:Web认证覆盖扫描工具

AuthCov使用Chrome headless browser(无头浏览器)爬取你的Web应用程序,同时以预定义用户身份进行登录。在爬取阶段它会拦截并记录AP...

9700
来自专栏网络攻防实战知识交流

部分CTF writeup

9500
来自专栏WalkingCloud

CentOS7上安装NextCloud个人网盘

个人网盘(私有云盘),常用的开源框架包括ownCloud,Seafile,Nextcloud

53100

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励