黑盒测试
1.php
上传失败,只允许上传如下格式,看来这次采用白名单了
前端没有js脚本
改Content-Type: image/png
,上传失败
没有头绪,看看提示吧,说上传路径可控?
果然url栏写着路径,但是不知道有什么用
源码分析
$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类型文件!";
}
}
1.strrpos() 函数查找字符串在另一字符串中最后一次出现的位置。
- 源码中是查找
.
在文件名中最后出现的位置
2.substr() 函数 返回其中一部分的字符串。
-
substr(string,start,length)
:start为开始截取部分
3.将后缀名给$file_ext
4.如果$file_ext
在白名单内,就上传到规定的路径,文件命名为上传路径+10-99+年月日时分秒+$file_ext
看着无懈可击,有没有突破路径呢?
百度了一下,这道题要用00截断
%00截断
绕过原理
move_uploaded_file函数的底层实现类似于C语言,遇到0x00会截断,把后面部分删掉
截断条件:
1、php版本小于5.3.4,(现在php版本都8了)
2、php.ini的magic_quotes_gpc为OFF状态
注意
POST和GET不一样
%00 截断在 GET 中被 url 解码之后是空字符。
但是在 POST 中 %00 不会自动被 url 解码,用bp先对%00进行解码
这也是为什么上传后没有截断,因为是post上传
白盒测试
因为重命名是上传路径+10-99+年月日时分秒+$file_ext
在上传路径处进行修改
上传1.php
,burpsuite进行修改
表面上重命名成了:1.php%EF%BF%BD/6120210806180147.gif
保存的时候由于截断,变成了1.php
连接成功
pass-12 黑名单-%00截断-post黑盒测试
同样只允许上传图片类型
抓包发现文件路径变成post上传了
进行修改,同时将%00先解码
文件名表面上是123.php%EF%BF%BD/3020210806184837.jpg
但是由于截断作用,实际上是123.php
连接成功
源码分析
$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上传,和pass-11没什么区别
pass-13白名单-文件包含漏洞-上传图片马-读文件前两个字节黑盒测试
看看要求:
意思是说这个系统有文件包含漏洞,让我们上传三种格式的图片马并连接成功
做图片马
此外,在文件头加GIF89A也能绕过,目前还不清楚原理
/etc/shadow
爆出绝对路径
上传,连接shell
php版本要高一点,5.3以上,不然报错很难受
源码分析
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.fopen( )函数以二进制只读的方式打开文件
2.fread() 函数读取文件,只读两个字节,赋值给$bin
3.关闭文件
4.unpack() 函数是将二进制解包成其他形式,unpack("C2chars", $bin)
是输出为两个无符号字符型
5.intval() 函数将两个字符转成10进制(默认)
6.比较10进制数来确定文件后缀$file_type
7.重命名为10-99+年月日时分秒+$file_type
因为存在文件包含漏洞,所以做一个图片马可以轻松绕过
pass-14 白名单-文件包含漏洞-上传图片马-getimagesize( )黑盒测试
上传GIF成功绕过,连接成功
但是jpg和和png文件包含时报错
源码分析
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 = "上传出错!";
}
}
}
1.getimagesize( )函数将测定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 图像文件的大小并返回图像的尺寸以及文件类型和一个可以用于普通 HTML 文件中 IMG
标记中的 height/width 文本字符串。
比如上传的gif文件(只加了个文件头GIF89A)
0=>2573;
1=>16188;
2=>1;
3=>width="2573" height="16188";
channels=>3;
mime=>image/gif;
上传的png图像
0=>473;
1=>406;
2=>3;
3=>width="473" height="406";
bits=>8;
mime=>image/png;
上传的jpg图像
0=>1920;
1=>1080;
2=>2;
3=>width="1920" height="1080";
bits=>8;
channels=>3;
mime=>image/jpeg;
2.image_type_to_extension根据指定的图像类型返回对应的后缀名。
- 1 = GIF
- 2 = JPG
- 3 = PNG
- 4 = SWF
3.stripos() 函数查找字符串在另一字符串中第一次出现的位置(不区分大小写),此处是查找后缀名在白名单中的位置
4.如果在白名单中,就保留扩展名,进行重命名:10-99+年月日时分秒+扩展名上传
pass-15 白名单-文件包含漏洞-上传图片马-exif_imagetype()黑盒测试
和pass-14,pass-13没什么不同,均绕过
源码分析
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 = "上传出错!";
}
}
}
1.使用exif_imagetype( )函数判断一个图像的类型
- exif_imagetype() 读取一个图像的第一个字节并检查其签名。
- 如果发现了恰当的签名则返回一个对应的常量,否则返回
false
。 - 返回值和 getimagesize() 返回的数组中的索引 2 的值是一样的,但本函数快得多。
- 返回值是整型1,2,3等,不是IMAGETYPE_GIF,IMAGETYPE_JPEG