目录
注释:分析在每关开头。
第 1 关
客户端 JavaScript检验(通常为检测文件拓展名)
判断方法:在浏览加载文件,但还未点击上传按钮时便弹出对话框,内容如:只允许上传 .jpg / .jpeg / .png
后缀名的文件,而此时并未发送数据包。
绕过办法:1.利用BurpSuite之类的代理工具进行抓包。
2.修改webshell后缀类型为允许上传类型。
3.抓包来拦截将其后缀名改为对应服务器可以解析的后缀名。
第 2 关
服务器MIME检测:即检测Content-Type的内容。
绕过方法:修改类型为允许上传的类型即可。
其余步骤同 第 1 关
源码:
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.'文件夹不存在,请手工创建!';
}
}
分析:上传文件类型必须是 image/jpeg 或 image/png 或 image/gif
第 3 关
服务器文件名拓展名检测(检测根文件 extension 相关的内容)
基于黑名单检测:黑名单的安全性比白名单的安全性低很多,攻击手法自然也比白名单多。一般由个专门的
blacklist,里面包含常见的危险脚本文件。
绕过办法:1.文件大小写让绕过(Php ,PhP pHp,等)
2.黑白名单绕过(php,php2,php3,php5,phtml,asp,aspx,ascx,ashx,cer,asa,jsp,
jspx)cdx,\x00hh\x46php
3.特殊文件名绕过
1)修改数据包里的文件名为 test.php 或 test.asp_(下划线是空格)由于这种命名格式在
windows系统里是不允许的,所以在绕过上传之后windows系统会自动去掉.点和空格。Linux和
Unix中没有这个特性。
2)::$DATA(php在windows的时候如果文件名+"::DATA"会把::DATA之后的数据当作文件流处
理,不会检测后缀名,且保持"::DATA"之前的文件名,其目的就是不检查后缀名)
4.0x00截断绕过(5.2 C语言中将 \0 当作字符串的结尾)
5. .htaccess文件攻击(结合黑名单攻击)
6. 解析绕过
源码过滤部分:
if (isset($_POST['submit'])) {
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); //收尾去空
第 4 关![](https://i-blog.csdnimg.cn/blog_migrate/1d98ca135ceea807b79fe3960826052d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/602693654ab4dddecdb124602feed0d6.png)
、
第 5 关
同第 4 关
第 6 关![](https://i-blog.csdnimg.cn/blog_migrate/c5c2c915c992e8e7b18a9cfd4bf1b79b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d7a6cb52db6d212eddec861dac370e36.png)
![](https://i-blog.csdnimg.cn/blog_migrate/873b9b7e9a6ff3bf67acd3d1a2bc71c0.png)
源码:
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",".ini");
$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 . '文件夹不存在,请手工创建!';
}
第 7 关
同第 3 关
第 8 关
同第 4 关
第 9 关![](https://i-blog.csdnimg.cn/blog_migrate/4dd9d360665fcb8e0cedf5ed0111b275.png)
源码:
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",".ini");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$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 . '文件夹不存在,请手工创建!';
}
过滤:特殊文件名,大小写,点及空格,随机产生新文件名。
第 10 关
同第 4 关
第 11 关
源码:
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$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");
$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 . '文件夹不存在,请手工创建!';
}
}
分析:复写绕过或者在php中添加任一 $deny_ext 数组中其他元素
第 12 关
文件上传 %00 截断
前提:php版本<5.3.4
0x00截断绕过:文件名后缀就一个%00字节,可以截断某些函数对文件名的判断。在许多语言函数中,处理字符串
的函数中0x00被认为是终止符。
例如:网站上传函数处理 XXX.php%00.jpg 时,首先后缀名是合法的jpg格式,可以上传,在保存文件时,遇
到%00字符丢弃后面的jpg,文件后缀最终保存的后缀名为xxx.php.
第 13 关![](https://i-blog.csdnimg.cn/blog_migrate/5e6d8de7da07bdb40aa72f2e7a46c9c2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f9e462abc492d4496620c7a3b25fee52.png)
![](https://i-blog.csdnimg.cn/blog_migrate/01a7188dca2bc833032e1149af446ad2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/84db207829a9bde3aa44a7222b811b9f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/ebaa81c61d64f35a451af1a7fda9dfa7.png)
第 14 关
服务端文件内容拓展检测
如果文件内容检测设置的比较严格,那么上传攻击将变得非常困难。也可以说他是在代码层检测的最后一关。
如果它被突破了,就算代码层的漏洞,也可以结合解析漏洞进行攻击。
1)文件幻数检测 jpg(JFIF) gif(GIF89a) png(%PNG)
2)文件相关信息检测(文件头加一些图片信息中间夹杂攻击代码)
3)文件加载检测(调用API或函数进行文件加载检测 PHP的gd库)
源码:
$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';
}
分析:通过检验前两个字节,用前两个字节内容进行指定运算,通过得到的结果判断文件类型,即 255216-jpg,
13780-png,7173-gif。
注入:通过截取图片文件的前两个字节拼接到欲上传文件的开头即可绕过该过滤。
或直接把上传内容插入到一个小图片中(太大的图容易出问题)
制作图片马
其余 .png, gif 文件同上
第 15 关
同第 14 关
第 16 关![](https://i-blog.csdnimg.cn/blog_migrate/8e918e20ee96f4d17da9981a429084e8.png)
![](https://i-blog.csdnimg.cn/blog_migrate/aa4fd6eb29fe034031e8b66d632e02a7.png)
其余同第 14 关
第 17 关
二次渲染
原理:在我们上传文件后,网站会对图片进行二次处理(格式、尺寸要求等),服务器会把里面的内容进行替换更新,处理完成后,根据我们原有的图片生成一个新的图片并放到网站对应的标签进行显示。
绕过:
1、配合文件包含漏洞:
将一句话木马插入到网站二次处理后的图片中,也就是把一句话插入图片在二次渲染后会保留的那部分数
据里,确保不会在二次处理时删除掉。这样二次渲染后的图片中就存在了一句话,在配合文件包含漏洞获取
webshell。
2、可以配合条件竞争:
这里二次渲染的逻辑存在漏洞,先将文件上传,之后再判断,符合就保存,不符合删除,可利用条件竞争
来进行爆破上传
下载图片 16 进制查看器:Downloads | mh-nexus
对比图片马上传前后差别找到前后无变化的部分,把木马写入其中即可。
参照:upload-labs之pass 16详细分析 - 先知社区 (aliyun.com)
第 18 关
文件上传之竞争条件
在服务器删除我们上传的非法文件之前,访问这个文件,从而生成另一个木马文件,用这个木马文件getshell
文件上传过程
用户上传文件,服务器获取文件,然后保存临时文件,然后使用移动函数(比如php中的move_uploaded_file() ),才会将文件移动到站点的根目录下面
竞争条件原理
网站允许上传任意文件,然后检测文件中若有webshell,就删除文件;若不是指定类型文件,那么就使用unlink删除文件
在删除之前访问上传的php文件,从而执行上传文件中的php代码
(竞争条件攻击)
审计代码,发现这关是先允许上传任意文件,,然后用白名单对比检查上传的文件,,如果上传的文件后缀不被白名单包含,,则直接删除
方法:写一个php脚本(被访问时会创建另一个脚本,这个如果创建成功,不会被删除),,用burpsuite抓包,,多线程去一直上传,,再抓个访问包,,多线程一直访问,同时进行,总有一刻会在文件被删除之前访问到脚本,,创建shell成功
源码:
$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 = '上传出错!';
}
}
第 19 关![](https://i-blog.csdnimg.cn/blog_migrate/0c502102584c80980cc16aa47500418d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/beff4f5f5baed3c03c94300c3c15e94d.png)
猜测:可能是源码的问题。
或者
第 20 关![](https://i-blog.csdnimg.cn/blog_migrate/501879ed9a1311ae89dc01bf82511a5f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3fa4761e12e8f03f3de35f01fab63aac.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0155c6dd56717731040b247bd2acb7b4.png)
第 21 关![](https://i-blog.csdnimg.cn/blog_migrate/187d88cc66a51b833fc01c555fb93e38.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0ba1b2905b6d63c6e0952db2b012177e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/70699f5c3320afbf0e8241c3b505692f.png)
注:后面的关也可以考虑使用图片马。