今天学习了文件上传漏洞的,下面是我结合的网上的一些资源和上课的内容整理的一些学习思路,仅供学习使用。
第一关:(js检查-后缀名)
思路:第一关主要是检查上传webs hell文件后缀名,我们可以利用更改后缀名的方式绕过前端的检查,再通过burp拦截信息,在拦截信息里面更改我们的后缀名然后放出去,利用中国蚁剑连接以此达到控制目标服务器的目的。
这里扩展一下第二种绕过方法,由于这一关主要是通过前端校验文件后缀名的方式来拦截的,比如这一关是通过一个javascript调用checkFile()函数来判断的
我们可以试着到控制台去重新定义这个checkFile()函数,把它定义为空,如下所示:
然后我们再去试着上传我们的php文件
我们再去运行一下,看看是否运行成功
发现写的php代码成功运行
第二关:(仅判断content-type类型)
思路:第二关与第一关类似,还是检测文件的类型,只是检测方式不一样,第一关是检测文件的后缀名,而第二关是检测的一个Content-Type: image/jpeg,如果上传的文件不是其中之一就会提示文件类型不正确,而我们的解决办法还是一样通过burp拦截更改content-type就好了。
第三关:(黑名单绕过)
思路:这一关利用黑名单不允许用户上传.asp、.aspx、.php、.jsp后缀的文件,这一关网上教程说可以把后缀名改为php3,phtml,phps,.pht,但是前提是apache的httpd.conf配置文件中有如下代码:
AddType application/x-httpd-php .php .phtml .phps .php5 .pht
没有上面配置,确实可以上传上去,但是我们去访问的时候,发现被当成了静态资源文件执行,所以是不可取的。技巧:凡是源码里有删除掉什么的,我们都可以试试双写绕过,所以这里我们在webshell.php文件后面加上::$DATA,但是这里直接输会给你删除掉,那么我们试试双写---webshell.php::$D::$DDATAATA,发现成功绕过
::$DATA是Windows的NTFS文件系统中拥有的一个特性,通常被附加到文件扩展名后面
第四关:(.htaccess绕过)
思路:黑名单几乎拒绝了所有有问题的后缀名,除了.htaccess,前提条件(1.mod_rewrite模块开启,2.AllowOverride All),因此先上传一个.htaccess文件,内容如下:SetHandler application/x-httpd-php,这样所有的文件都会当成php来解析。然后再上传一个不带后缀名的webshell文件就可以绕过了,访问那个文件时,后台仍要把该文件当作PHP文件运行。
也可以使用下面的这个.htaccess文件,先上传这个文件,然后再上传那个webshell文件,利用burp拦截,再拦截信息那里把文件名修改为tony就行了,.htaccess文件内容如下:
<FilesMatch "tony">
SetHandler application/x-httpd-php
</FilesMatch>
第五关:(大小写绕过)
思路:相较于第四关,这一关把.htaccess文件也给过滤掉了,但将把文件后缀转换为小写去掉了,因此可以使用大写绕过的方法。因此这一关我们只需把后缀名任意字符改为大写就好了。
第六关:(空格绕过)
思路:这题没有对后缀名进行去空,因此可以在后缀名加空格进行绕过。如:webshell.php 进行绕过,当然还是需要用burp拦截之后才能改。
第七关:点绕过
思路:这一关相比前面的关卡,没有对后缀名末尾的点进行处理,利用Windows的特性可知,会自动去掉后缀名中的点,但我们可以利用burp在后缀名后加点,如:webshell.php.
第八关:(::$DATA绕过)
思路:这一关没有对后缀名中的::$DATA进行过滤。在PHP+Windows的情况下:如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名.且保持"::$DATA"之前的文件名,利用Windows特性,可在后缀名中加"::$DATA"进行绕过,注:还是在burp里改
第九关:(点+空格+点绕过)
思路:至于这一关它先把文件后缀末尾的点去掉了,还把空格去掉。因此我们试着先构造:webshell.php. ,发现不行,那么我们紧接着构造:webshell.php. .,发现成功绕过。代码先是去除文件名前后的空格,再去除文件名最后的点,再通过strchar()来寻找文件名的后缀,但是最后保存文件的时候没有重命名,而使用的原有文件名。
第十关:(双写绕过)
思路:这一关就是通过把黑名单里的文件后缀名替换为空且只替换一次,因此我们只需要换位双写绕过就可以了。
第十一关:(%00截断绕过)
源码如下:%00在acsii码中对应null,但在c语言环境下对应为截断,而大多数环境都是基于C语言架构,例如PHP、apache等
思路: 这一关使用的白名单判断,只允许jpg、png、gif格式的文件上传,那么我们就利用burp拦截给它想要的格式。当是GET接收情况的时候,直接用 %00 就可以了
注:截断条件:php版本小于5.3.4,php的magic_quotes_gpc为OFF状态
发现上传成功然后在访问shell文件地址的时候把shell.php后面截断的链接删除掉就可以访问了,我们再利用中国菜刀或蚁剑连接就可以了。
第十二关(截断绕过):
思路:这一关与上一关的区别在于参数是通过post传递,虽然还是利用%00截断,但是POST不会像GET对%00进行自动解码,所以需要在二进制中进行修改。
按照上一关的操作,把shell.php改为shell.jpg,然后在upload/后面写入shell.php%00,就可以上传文件了。
第十三关:(图片马绕过)
思路:通过读文件的前2个字节判断文件类型,因此直接上传图片马即可,同时要注意的是直接访问我们制作的图片马,是不会把图片马当作动态脚本文件执行的,因为图片马的后缀名为.jpg,所以在解析时,中间件只会把它当作静态资源文件执行,不会把它交给动态脚本解析器,因此还要使用文件包含漏洞。
源码如下:
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;
}
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_type = getReailFileType($temp_file);
if($file_type == 'unknown'){
$msg = "文件未知,上传失败!";
}else{
$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上传出错!";
}
}
}
制作图片马:
copy aa.jpg /b + shell.php /a shell.jpg
再点击文件包含漏洞,如下所示
将图片在新标签页中打开,复制下面的地址
然后到文件包含漏洞的页面构造下面的语句
这样就可以访问我们的图片了,而且用这个链接我们还可以访问我们的服务器
第十四关:(图片马绕过)
思路:这一关与13关步骤类似
第十五关:(图片马绕过)
思路:这里用到php_exif模块来判断文件类型,也就是目标服务器其的中间件有一个扩展程序为打开状态,我们就可以用图片马绕过,方法同pass-13,也可以通过在burp改图片文件头的方式绕过
打开php_exif位置如下:
第十六关:(二次渲染绕过)
思路:这一关主要根据审计代码发现这里不仅判断了文件后缀名、content-type最后还做了二次渲染,把上传文件里与图片信息不相关的信息渲染掉。
$is_upload = false;
$msg = null;
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";
//显示二次渲染后的图片(使用用户上传图片生成的新图片)
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagejpeg($im,$img_path);
@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";
//显示二次渲染后的图片(使用用户上传图片生成的新图片)
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagepng($im,$img_path);
@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";
//显示二次渲染后的图片(使用用户上传图片生成的新图片)
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagegif($im,$img_path);
@unlink($target_path);
$is_upload = true;
}
} else {
$msg = "上传出错!";
}
}else{
$msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!";
}
}
第十七关(条件竞争):
这一关主要利用条件竞争,先上传一个写文件的PHP文件到服务器,上传之后服务器会判断文件后缀是否在白名单里,如果在则重命名,否则删除,因此我们可以上传writeshell.php只需要在它删除之前访问即可,可以利用burp的intruder模块不断上传,然后我们不断的访问刷新该地址即可
writeshell.php代码如下:
<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST["test"])?>');?>
开启代理,然后上传writeshell文件,然后利用burp抓包,步骤如下:
抓包
打开intruder模块,清除标记
修改参数
选择爆破线程数,默认就好
点击右上角start attack,开始爆破,并另开启一个浏览器页面访问writeshell.php,并不断刷新,直到虚拟机目录upload-labs/upload/目录下多出一个shell.php
后续关卡都是一些类似的,只是比较综合,就不展示了
本文参考链接:upload-labs通关记录_迷风小白-CSDN博客_upload-labs