一般都是在网页上写一段javascript脚本,校验上传文件的后缀名,有白名单形式也有黑名单形式。
查看源代码可以看到有如下代码对上传文件类型进行了限制:
我们可以看到对上传文件类型进行了限制。
1.我们直接删除代码中onsubmit事件中关于文件上传时验证上传文件的相关代码即可。
或者可以不加载所有js,还可以将html源码copy一份到本地,然后对相应代码进行修改,本地提交即可。
2.burp改包,由于是js验证,我们可以先将文件重命名为js允许的后缀名,在用burp发送数据包时候改成我们想要的后缀。
即可上传成功:
if (file_exists(UPLOAD_PATH)) { $deny_ext = array('.asp','.aspx','.php','.jsp'); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //收尾去空 if(!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file,$img_path)) {
$is_upload = true; } else {
$msg = '上传出错!'; } } else {
$msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!'; } } else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }
这里做了黑名单处理,我们可以通过特殊可解析后缀进行绕过。
之前在4中总结过,这里不再赘述,可以使用php3,phtml等绕过。
if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //收尾去空 if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true; } else {
$msg = '上传出错!'; } } else {
$msg = '此文件不允许上传!'; } } else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }}?>
我们发现黑名单限制了很多后缀名,但是没有限制.htaccess
.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置.通过htaccess文件,可以实现:网页301重定向、自定义404页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
我们需要上传一个.htaccess文件,内容为:
SetHandler application/x-httpd-php
这样所有的文件都会解析为php,接下来上传图片马即可
if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //首尾去空 if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true; } else {
$msg = '上传出错!'; } } else {
$msg = '此文件类型不允许上传!'; } } else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }}
后缀名改为PHP即可
if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess"); $file_name = $_FILES['upload_file']['name']; $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file,$img_path)) {
$is_upload = true; } else {
$msg = '上传出错!'; } } else {
$msg = '此文件不允许上传'; } } else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }
黑名单没有对文件中的空格进行处理,可在后缀名中加空格绕过。
if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess"); $file_name = trim($_FILES['upload_file']['name']); $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //首尾去空 if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true; } else {
$msg = '上传出错!'; } } else {
$msg = '此文件类型不允许上传!'; } } else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }
windows会对文件中的点进行自动去除,所以可以在文件末尾加点绕过,不再赘述
同windows特性,可在后缀名中加” ::$DATA”绕过,不再赘述
if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //首尾去空 if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true; } else {
$msg = '上传出错!'; } } else {
$msg = '此文件类型不允许上传!'; } } else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }}
这里对文件名进行了处理,删除了文件名末尾的点,并且把处理过的文件名拼接到路径中。
这里我们可以构造文件名1.PHP. . (点+空格+点),经过处理后,文件名变成1.PHP.,即可绕过。
$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = str_ireplace($deny_ext,"", $file_name);
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
这里我们可以看到将文件名替换为空,我们可以采用双写绕过:1.pphphp
if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) {
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
$temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']; if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true; } else {
$msg = '上传出错!'; } } else {
$msg = '文件类型不正确,请重新上传!'; } } else {
$msg = UPLOAD_PATH.'文件夹不存在,请手工创建!'; }
这里检查Content-type,我们burp抓包修改即可绕过:
if(isset($_POST['submit'])){ $ext_arr = array('jpg','png','gif'); $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1); if(in_array($file_ext,$ext_arr)){
$temp_file = $_FILES['upload_file']['tmp_name']; $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext; if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true; } else {
$msg = '上传出错!'; } } else{
$msg = "只允许上传.jpg|.png|.gif类型文件!"; }}
$img_path直接拼接,因此可以利用%00截断绕过
然后直接访问/upload/1.php即可
if(isset($_POST['submit'])){ $ext_arr = array('jpg','png','gif'); $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1); if(in_array($file_ext,$ext_arr)){
$temp_file = $_FILES['upload_file']['tmp_name']; $img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext; if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true; } else {
$msg = "上传失败"; } } else {
$msg = "只允许上传.jpg|.png|.gif类型文件!"; }}?>
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...)
(... 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:
上传成功。
参考链接:
https://blog.csdn.net/Kevinhanser/article/details/81613003
https://secgeek.net/bookfresh-vulnerability/
https://xz.aliyun.com/t/2435
上传环境源码:https://github.com/c0ny1/upload-labs
更多推荐
内网横向渗透的常用姿势
渗透测试之提权方式总结
渗透测试之linux系统提权总结
国内SRC漏洞挖掘经验和自用技巧
任意文件上传漏洞 getshell 教程