标签:后缀名 idt time tag check lin char status iss
GitHub地址:https://github.com/Tj1ngwe1/upload-labs
PHP $_FILES函数详解: (https://www.cnblogs.com/laijinquan/p/8682282.html)https://www.cnblogs.com/laijinquan/p/8682282.html
前端js过滤文件后缀名,页面禁用js即可
Content-Type 实体头部用于指示资源的MIME类型
media type ,在响应中,Content-Type标头告诉客户端实际返回的内容的内容类型。
常见Content-Type https://www.cnblogs.com/klb561/p/10090540.html 源码:
1 $is_upload = false; 2 $msg = null; 3 if (isset($_POST[‘submit‘])) { 4 if (file_exists(UPLOAD_PATH)) { 5 if (($_FILES[‘upload_file‘][‘type‘] == ‘image/jpeg‘) || ($_FILES[‘upload_file‘][‘type‘] == ‘image/png‘) || ($_FILES[‘upload_file‘][‘type‘] == ‘image/gif‘)) { 6 $temp_file = $_FILES[‘upload_file‘][‘tmp_name‘]; 7 $img_path = UPLOAD_PATH . ‘/‘ . $_FILES[‘upload_file‘][‘name‘] 8 if (move_uploaded_file($temp_file, $img_path)) { 9 $is_upload = true; 10 } else { 11 $msg = ‘上传出错!‘; 12 } 13 } else { 14 $msg = ‘文件类型不正确,请重新上传!‘; 15 } 16 } else { 17 $msg = UPLOAD_PATH.‘文件夹不存在,请手工创建!‘; 18 } 19 }
抓包,发现Content-Type为application/...
改为图片格式image/png即绕过服务器端验证
提示:不允许上传.asp,.aspx,.php,.jsp后缀文件! 未知的风险太多,黑名单过滤的结果无法预测!
源码的过滤不可绕过
上传如php2,php3、php4、php5这些后缀的文件,但可能无法解析, 需要配置文件中有 AddType application/x-httpd-php .php .phtml .phps .php5 .pht
也可以上传如cer文件
黑名单未限制.htaccess,且.htaccess有效
.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置.通过htaccess文件,可以实现:网页301重定向、自定义404页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能
https://blog.csdn.net/qq_45555226/article/details/104846799 - 上传.htaccess文件,内容为 SetHandler application/x-httpd-php
- 再上传php5等文件
禁止上传如上这么多文件类型,依然是黑名单,但未限制 .htaccess
上传内容为SetHandler application/x-httpd-php
的文件,任意会解析成php类型,在上传无文件后缀的shell即可
前提是配置文件有效
关于.user.ini https://segmentfault.com/a/1190000011552335?utm_source=tag-newest
创建一个名为.user.ini的文件内容为
`auto_prepend_file=1.gif`
创建一句话木马命名为1.gif
题目提示已经有readme.php文件
将1.gif和.user.ini文件上传,访问readme.php时会自动包含1.gif文件(这里上传的文件路径未改变)
效果如图:
查看源码会发现未过滤大小写
木马改名为1.PhP即可上传
bp抓包文件尾加俩空格
原理: windows会对文件中的点进行自动去除,所以可以在文件末尾加点绕过
bp抓包改文件名为1.php.
代码过滤不严格 抓包改文件名为1.php. .可以绕过
源码中采用黑名单,str_ireplace()不区分大小写替换掉黑名单中存在的后缀
1 $is_upload = false; 2 $msg = null; 3 if (isset($_POST[‘submit‘])) { 4 if (file_exists(UPLOAD_PATH)) { 5 $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","ini"); 6 ? 7 $file_name = trim($_FILES[‘upload_file‘][‘name‘]); 8 $file_name = str_ireplace($deny_ext,"", $file_name); 9 $temp_file = $_FILES[‘upload_file‘][‘tmp_name‘]; 10 $img_path = UPLOAD_PATH.‘/‘.$file_name; 11 if (move_uploaded_file($temp_file, $img_path)) { 12 $is_upload = true; 13 } else { 14 $msg = ‘上传出错!‘; 15 } 16 } else { 17 $msg = UPLOAD_PATH . ‘文件夹不存在,请手工创建!‘; 18 } 19 }
重命名shell为 1.pphphp 即可绕过
php版本要小于5.3.4,5.3.4及以上已经修复该问题
magic_quotes_gpc需要为OFF状态
用法: https://www.fujieace.com/penetration-test/file-upload-00.html
抓包发现上传路径
改shell名为1.jpg
抓包修改save_path = ../upload/1.php%00
抓包改上传路径
检查前两个字节看是否是图片类型
function getReailFileType($filename){ $file = fopen($filename, "rb"); $bin = fread($file, 2); //只读2字节 fclose($file); $strInfo = @unpack("C2chars", $bin); $typeCode = intval($strInfo[‘chars1‘].$strInfo[‘chars2‘]); $fileType = ‘‘; switch($typeCode){ case 255216: $fileType = ‘jpg‘; break; case 13780: $fileType = ‘png‘; break; case 7173: $fileType = ‘gif‘; break; default: $fileType = ‘unknown‘; } return $fileType; }
直接用bat生成图片马,直接上传
getimagesize() : http://c.biancheng.net/view/6259.html
使用getimagesize()检查图片
绕过方法同上,制作图片马即可
exif_imagetype() : https://www.php.net/manual/zh/function.exif-imagetype.php
绕过方法同上
图片上传后,服务端会重新进行渲染,木马可能会遭到破坏
绕过思路是对比原图片与上传后的图片,看看哪部分没有变
备份链接:https://files.cnblogs.com/files/l0nmar/upload-labs%E4%B9%8Bpass.rar
unlink:删除文件 https://www.w3school.com.cn/php/func_filesystem_unlink.asp
PHP strrpos() 函数:https://www.w3school.com.cn/php/func_string_strrpos.asp
strrpos() 函数查找字符串在另一字符串中最后一次出现的位置. 对大小写敏感.
PHP move_uploaded_file() 函数 :https://www.w3school.com.cn/php/func_filesystem_move_uploaded_file.asp
move_uploaded_file(file,newloc)
file-必需-规定要移动的文件。
newloc-必需-规定文件的新位置。
审计源码可以发现 , `move_uploaded_file($temp_file, $upload_file)`
$is_upload = false; $msg = null; ? 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 = ‘上传出错!‘; } }
利用思路: 在删除$upload_file之前进行访问shell
开始爆破后不停刷新页面,手速够快是可以刷出来phpinfo(),可以开两个爆破,一个请求页面,一个上传竞争
源码如下:
//index.php $is_upload = false; $msg = null; if (isset($_POST[‘submit‘])) { require_once("./myupload.php"); $imgFileName =time(); $u = new MyUpload($_FILES[‘upload_file‘][‘name‘], $_FILES[‘upload_file‘][‘tmp_name‘], $_FILES[‘upload_file‘][‘size‘],$imgFileName); $status_code = $u->upload(UPLOAD_PATH); switch ($status_code) { case 1: $is_upload = true; $img_path = $u->cls_upload_dir . $u->cls_file_rename_to; break; case 2: $msg = ‘文件已经被上传,但没有重命名。‘; break; case -1: $msg = ‘这个文件不能上传到服务器的临时文件存储目录。‘; break; case -2: $msg = ‘上传失败,上传目录不可写。‘; break; case -3: $msg = ‘上传失败,无法上传该类型文件。‘; break; case -4: $msg = ‘上传失败,上传的文件过大。‘; break; case -5: $msg = ‘上传失败,服务器已经存在相同名称文件。‘; break; case -6: $msg = ‘文件无法上传,文件不能复制到目标目录。‘; break; default: $msg = ‘未知错误!‘; break; } } ? //myupload.php class MyUpload{ ...... ...... ...... var $cls_arr_ext_accepted = array( ".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt", ".html", ".xml", ".tiff", ".jpeg", ".png" ); ? ...... ...... ...... function upload( $dir ){ $ret = $this->isUploadedFile(); //is_uploaded_file() 函数检查指定的文件是否是通过 HTTP POST 上传的。如果文件是通过 HTTP POST 上传的,该函数返回 TRUE。 if( $ret != 1 ){ return $this->resultUpload( $ret ); } ? $ret = $this->setDir( $dir ); if( $ret != 1 ){ return $this->resultUpload( $ret ); } ? $ret = $this->checkExtension(); //检查扩展名 if( $ret != 1 ){ return $this->resultUpload( $ret ); } ? $ret = $this->checkSize(); //检查大小 if( $ret != 1 ){ return $this->resultUpload( $ret ); } // if flag to check if the file exists is set to 1 if( $this->cls_file_exists == 1 ){ $ret = $this->checkFileExists(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } } ? // if we are here, we are ready to move the file to destination ? $ret = $this->move(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } ? // check if we need to rename the file ? if( $this->cls_rename_file == 1 ){ $ret = $this->renameFile(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } } // if we are here, everything worked as planned :) ? return $this->resultUpload( "SUCCESS" ); } ...... ...... ...... };
对文件进行了大小,扩展名等等检查,最后重命名
条件竞争会存在不重命名的情况
原理不太清楚...
文末加点windows下会自动忽略
源码中用phpinfo()获取文件名
加点Windows下自动忽略会使其获得的文件路径为空,从而通过验证
源码如下:
``` $is_upload = false; $msg = null; if(!empty($_FILES[‘upload_file‘])){ //检查MIME $allow_type = array(‘image/jpeg‘,‘image/png‘,‘image/gif‘); if(!in_array($_FILES[‘upload_file‘][‘type‘],$allow_type)){ $msg = "禁止上传该类型文件!"; }else{ //检查文件名,文件名为空就按默认的保存,否则就按上传的 $file = empty($_POST[‘save_name‘]) ? $_FILES[‘upload_file‘][‘name‘] : $_POST[‘save_name‘]; if (!is_array($file)) { $file = explode(‘.‘, strtolower($file)); }// 如果不是数组就用explode()分割为数组,以 .分割 ? $ext = end($file); //取最后一个数组元素进行白名单验证 $allow_suffix = array(‘jpg‘,‘png‘,‘gif‘); if (!in_array($ext, $allow_suffix)) { $msg = "禁止上传该后缀文件!"; }else{ $file_name = reset($file) . ‘.‘ . $file[count($file) - 1]; // 文件重新命名为数组元素第一个元素拼接数组元素量减一的元素 $temp_file = $_FILES[‘upload_file‘][‘tmp_name‘]; $img_path = UPLOAD_PATH . ‘/‘ .$file_name; if (move_uploaded_file($temp_file, $img_path)) { $msg = "文件上传成功!"; $is_upload = true; } else { $msg = "文件上传失败!"; } } } }else{ $msg = "请选择要上传的文件!"; } ```
先修改MIME绕过
再构造数组第一个元素为1.php,第三个为jpg
拼接为1.php+空=1.php
标签:后缀名 idt time tag check lin char status iss
原文地址:https://www.cnblogs.com/l0nmar/p/12804174.html