pass11
查看源码
$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类型文件!";
}
}
strrpos() 函数
查找字符串在另一个字符串中最后一次出现的位置。
0x00和%00截断
%00截断原理
www.xxx.com/qq.jpg
www.xxx.com/qq.php%00.jpg => www.xxx.com/qq.php
0x00是十六进制表示方法,是ascii码为0的字符,在有些函数处理时,会把这个字符当做结束符
get方式直接为%00,post为0x00
这是因为 %00 截断在 GET 中被 url 解码之后是空字符。但是在 POST 中 %00 不会被 url 解码,所以只能通过 burpsuite 修改 为 0x00 (URL decode)进行截断。
注意:
有些时候数据包中必须含有上传文件后的目录情况才可以用。
例如:数据包中存在 path: uploads/,那么攻击者可以通过修改path的值来构造paylod: uploads/aa.php%00
%00(urldecode)
首先解释为什么要进行urldecode操作呢?其原因在于上传的表单中有一个enctype的属性,并且需要enctype=“multipart/form-data” (不对表单中数据进行编码),path大多数都是存放在表单中的,因此需要在数据包中进行urldecode操作使%00变成字符串结束符号。
重点分析
之前的格式为
i m g p a t h = U P L O A D P A T H . ′ / ′ . d a t e ( " Y m d H i s " ) . r a n d ( 1000 , 9999 ) . img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999). imgpath=UPLOADPATH.′/′.date("YmdHis").rand(1000,9999).file_ext;
$img_path = G E T [ ′ s a v e p a t h ′ ] . " / " . r a n d ( 10 , 99 ) . d a t e ( " Y m d H i s " ) . " . " . _GET['save_path']."/".rand(10, 99).date("YmdHis").".". GET[′savepath′]."/".rand(10,99).date("YmdHis").".".file_ext;
img_path由get方式的save_path传入,导致文件名是可以控制的
使用%00截断,使用burp抓包进行修改
在burp repeater里面查看地址
pass12
查看源码
$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类型文件!";
}
}
与十一关不同的是img_path路径使用的post传参方式,尝试0x00截断方式
在upload后面输入webshell.php%00,选中%00,右击改变为url decode,因为post传参不会像get一样自动对0x00进行解码
pass13
function getReailFileType($filename){
#fopen打开文件
$file = fopen($filename, "rb");
#fread:读取file的前两节
$bin = fread($file, 2); //只读2字节
#fclose关闭文件
fclose($file);
#unpack:从二进制字符串对数据进行解包
$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 = "上传出错!";
}
}
}
分析里面一些关键函数
fopen:打开文件或url
fopen(filename,mode,include_path,context)
intval()
函数用于获取变量的整数值。
intval() 函数通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。
int intval ( mixed $var [, int $base = 10 ] )
方法一:
新建一个txt文件,改名为info.jpg,内容为GIF98A<?php phpinfo(); ?>
上传文件,在新窗口中打开,复制名称
点击 文件包含 超链接
<?php
/*
本页面存在文件包含漏洞,用于测试图片马是否能正常运行!
*/
header("Content-Type:text/html;charset=utf-8");
$file = $_GET['file'];
if(isset($file)){
include $file;
}else{
show_source(__file__);
}
?>
使用file函数,但是却报错了
将include.php复制到upload文件夹下,再输入名字
方法二:
要求只能上传jpg、png、gif格式,检查文件头,所以我们将webshell.php与z1.jpg合并
利用命令copy /b 1.jpg +1.php 2.jpg得到,其中1.jpg为载体文件,1.php为包含木马的文件,2.jpg为得到的文件
利用文件包含显示
pass14
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
getimagesize()函数用于获取图像大小及相关信息,成功返回一个数组,失败则返回FALSE并产生一条E_WARNING级的错误信息。
语法格式
数组getimagesize(字符串$ filename [,数组&$ imageinfo])
getimagesize()函数将确定任何GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM或WBMP图像文件的大小并返回图像的尺寸以及文件类型及图片高度与宽度。
mage_type_to_extension
根据指定的图像类型返回对应的后缀名。
语法
字符串image_type_to_extension(int $ imagetype [,bool $ include_dot = TRUE])
根据给定的常量IMAGETYPE_XXX返回后缀名。
同pass13