前言
继续学习upload-labs
本篇是Pass 12-16
两张summary
Pass-12 Get%00
截断
源码
$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类型文件!";
}
}
看了看
- 定义一个白名单,只允许三种文件类型
- substr()函数返回字符的一部分,strrpos(string,find,start)函数查找字符串中最后一次出现的位置,这里是将后缀名提取出来赋值给file_ext
- img_path是直接拼接
我们可以抓包修改get的参数,然后通过file_ext无效,这样就可以上传PHP文件
%00
截断的概念和原理:
- 在URL中
%00
表示ASCII码中的0,而0作为特殊字符保留,表示字符结束 - 当url中出现
%00
时就会认为读取已结束,而忽略后面上传的文件或图片,只上传截断前的文件或图片 - 要求:php版本小于5.3.4,php的magic_quotes_gpc为OFF状态
将路径改为path=“upload/1.php%00”,那么拼接之后,文件上传时就变成了“upload/1.php%1.jpg”,这时上传便将1.php上传进去,而1.jpg则被截断
Pass-13 Post%00
截断
源码
$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
还是利用00截断
但是POST不会像GET对%00进行自动解码
需要在二进制中进行修改
将70 68 70后面的2b改为00
Pass-14 图片马绕过
这题开始不一样了
源码
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 = "上传出错!";
}
}
}
看了看
- rb是读取二进制文件
- 后面的fread函数只读两字节,也就是说只对文件头进行了检测
- unpack(format,data)函数是规定在解包数据时所使用的格式,这里是文件头按照c格式解包
- intval() 函数用于获取变量的整数值
制作图片马
将一句话木马1.php和普通图片1.jpg合并
得到shell.jpg
copy 1.jpg /b + 1.php /a shell.jpg
上传文件
但直接访问图片并不能把图片当做PHP解析
还需要利用文件包含漏洞
www/upload-labs/upload目录下建立一个php文件
<?php
/*
本页面存在文件包含漏洞,用于测试图片马是否能正常运行!
*/
header("Content-Type:text/html;charset=utf-8");
$file = $_GET['file'];
if(isset($file)){
include $file;
}else{
show_source(__file__);
}
成了
Pass-15 图片马绕过
源码
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函数获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息
仍然可以图片马绕过
Pass-16 图片马绕过
源码
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 = "上传出错!";
}
}
}
用到php_exif模块来判断文件类型
仍然可以图片马绕过
结语
主要是
%00
截断- 图片马绕过