Upload-labs 测试笔记

By:Mirror王宇阳

2019年11月~

文件上传解析学习

环境要求

若要自己亲自搭建环境,请按照以下配置环境,方可正常运行每个Pass。

配置 项 配置 描述
操作系统 Window or Linux 推荐使用Windows,除了Pass-19必须在linux下,其余Pass都可以在Windows上运行
PHP版本 推荐5.2.17 其他版本可能会导致部分Pass无法突破
PHP组件 php_gd2,php_exif 部分Pass依赖这两个组件
中间件 设置Apache以moudel方式连接

技术摘录

  • 判断文件长传点

Pass-01

[源码]

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;
}
}

[分析]

Pass-01是在客户端使用js对文件进行校验,完全可以绕过。

[思路]

使用障眼法,将PHP文件修改图像格式后直接上传;使用burp拦截该数据包,修改文件格式(后缀名)

Pass-02

[源码]

$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.'文件夹不存在,请手工创建!';
}
}

[分析]

服务端的源码对接受的文件MIME进行检测,判断是否符合图像格式;但MIME校验的缺陷是严重的,用户完全可以随意修改MIME的参数值,但完全不影响文件格式的正常解析。

[思路]

正常上传一个PHP文件,Burp拦截数据包,修改数据包中的MIME格式类型为图像格式的MIME。

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 . '文件夹不存在,请手工创建!';
}
}

[分析]

源码检测进行文件名后缀检测,由此确定文件类型;无法使用burp拦截改包的方式;由于采用的黑名单方式,只隔离了asp、aspx、php、jsp等文件的后缀;由于php的特性,可以上传php5等文件后缀也是可以按照PHP文件被解析的

[思路]

上传“11.php5”文件,直接绕过黑名单。

[ps:获取上传目录和文件名]

由于文件上传后的文件位置是位置的,且文件名是采用随机数进行的二次重命名;故此我们可以根据返回的图像打开图像位置获取文件的具体路径。成功上传一个php(php5)文件后就会返回一个图像,打开图像的URL地址就是PHP文件的地址,例:../upload-labs-master/upload/202003141844327950.php5这个取决于Apache的配置问题(需要修改Apache的配置,让Apache支持解析例如php3之类的文件为PHP文件)

Pass-04

[源码]

$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");
$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 = '此文件不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}

[分析]

一看数组deny_ext那么多的黑名单;之前的特殊解析方式(混淆解析)也可存在可能,关键还是取决于apache的配置安全

[.htaccess知识]

.htaccess文件(分布式配置文件)提供了针对目录改变配置的方法;特定的文档目录中放置一个包含一个或多个指令的文件,以作用于此目录及其所有子目录;(是Apache环境下的一种配置行为)

设置.htaccess将当前目录的所有文件以php文件解析$#$

Pass-05

[源码]

$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 = 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 = '此文件类型不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}

[分析]

这里把.htaccess也拉入了黑名单,细细的看代码发现少了之前源代码中的一行"大小写转写";代码缺陷瞬间暴露,将文件名进行大小写混淆即可。

[思路]

上传muma.Php文件

Pass-06

[源码]

$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 = $_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 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 = '此文件不允许上传';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}

[分析]

从源码看来,对黑名单的建设是相当的完善了,同时也添加了小写转变检测的代码段,之前的大小写混淆、特殊解析混淆、.htaccess等方法在这里都被封杀了;但是按照惯例,既然是黑名单,我们的绕过思路就依旧是围绕在黑名单的缺陷上,同时围绕代码缺陷找到漏洞.

[思路]

通过对源码的剖析,发现没有对截取的文件后缀进行去空处理;这里提示:在操作系统中文件后缀是自动屏蔽删除后缀名的,但是在代码处理中空符号存在且可被处理.

在上传WebShell中直接提交".php"文件即可,使用Burp拦截数据包,修改数据包中的文件后缀(添加一个空符号)

Pass-07

[源码]

$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_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 . '文件夹不存在,请手工创建!';
}
}

[分析]

文件后缀被全部拉入黑名单,统一转小写检测,字符串去空;但是回归突破的宗旨,查缺陷!围绕黑名单发现没有被拉入且可以绕过检测的文件后缀方式进行枚举

[思路]

这里的思路是利用Win文件存储的特性,自动屏蔽后缀名的尾部.符号;正常上传php文件,burp拦截数据包就该文件后缀为.php.,成功绕过php的检测,在win、linux系统上自动消除尾部符号正常保存为。.php文件;(不选择其他特殊符号结尾的原因:在文件后缀修改上,其他特殊符号都会被正常存储,只有符号点会被消除)

Pass-08

[源码]

$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 = 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 = '此文件类型不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}

[分析]

这里没有对::$DATA绕过进行安全检测

[思路] -> ::$DATA绕过

NTFS文件系统的存储数据流的一个属性DATA时,当我访问a.php::DATA时,就是请求a.php本身的数据。

提交.php文件,Burp拦截数据包修改为.php::$DATA放包;正常以./././xxxx.php访问该文件即可

Pass-09

[源码]

$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 . '文件夹不存在,请手工创建!';
}
}

[分析]

这里否决了之前的所有绕过方案,不过依旧按照黑名单的绕过原则,通过名单缺陷和代码逻辑缺陷发现:删除逻辑(删除尾部的点、删除收尾的空字符、删除::$DATA) 这里的删除逻辑可以利用“双写”的方式来做突破

[思路]

通过Burp将文件名字符串修改为.php. .,代码逻辑会删除尾部的点和空字符,最后会将.php.提交进行黑名单校验

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","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess"); $file_name = trim($_FILES['upload_file']['name']);
$file_name = str_ireplace($deny_ext,"", $file_name);
$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 = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}

[分析]

依旧是黑名单机制,这里发现一个关键的代码逻辑,符合黑名单的字符全部替换为空字符;故此无法在使用之前那些什么后缀名混淆的方法没有用了,因为只要有符合黑名单中的字符全部替换为空

[思路]

burp拦截将文件名修改为双写.phphpp,交给代码进行校验,校验代码进行一次校验并替换敏感词为空字符,再上传。

Pass-11

[源码]

$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类型文件!";
}
}

[分析]

这里不再是黑名单机制,反之采用了“白名单”机制

[思路]

使用%00字节截断方式绕过-->.php%00

Pass-12

[源码]

$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类型文件!";
}
}

[分析]

[思路]

00字节截断,php5.3+版本不再支持

Pass-13

[源码]

**************客户端校验****************
function getReailFileType($filename){
$file = fopen($filename, "rb");
$bin = fread($file, 2); //只读2字节
fclose($file);
$strInfo = @unpack("C2chars", $bin);
// unpack() 函数从二进制字符串对数据进行解包。
$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 = "上传出错!";
}
}
}

[分析]

这里只允许上传图片文件,图片马走起;js脚本通过读文件的前2个字节判断文件类型

[思路]

这里需要利用文件包含来进行图片马的解析

Pass-14

[源码]

function isImage($filename){
$types = '.jpeg|.png|.gif';
if(file_exists($filename)){
//file_exists() 检测文件是否存在
$info = getimagesize($filename);
// getimagesize() 获取图像大小及相关信息,成功返回一个数组 // [宽度,高度,type(返回数值),…………]
$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()函数获取图像的信息(返回的数组第三个元素)进行校验类型;

[思路]

图片马

Pass-15

[源码]

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模块进行判断文件类型; exif_imagetype()获取图片类型

[思路]

图片马

Pass-16

[源码]

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])){
// 获得上传文件的基本信息,文件名,类型,大小,临时文件路径
$filename = $_FILES['upload_file']['name'];
$filetype = $_FILES['upload_file']['type'];
$tmpname = $_FILES['upload_file']['tmp_name']; $target_path=UPLOAD_PATH.'/'.basename($filename); // 获得上传文件的扩展名
$fileext= substr(strrchr($filename,"."),1); //判断文件后缀与类型,合法才进行上传操作
if(($fileext == "jpg") && ($filetype=="image/jpeg")){
if(move_uploaded_file($tmpname,$target_path)){
//使用上传的图片生成新的图片
$im = imagecreatefromjpeg($target_path); if($im == false){
$msg = "该文件不是jpg格式的图片!";
@unlink($target_path);
}else{
//给新图片指定文件名
srand(time());
$newfilename = strval(rand()).".jpg";
//显示二次渲染后的图片(使用用户上传图片生成的新图片)
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagejpeg($im,$img_path);
@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的图片文件!";
}
}

[分析]

这是一道大题,综合判断后缀名、content-type、利用imagecreatefromgif等多种方式来验证是否为图片;更关键的是在判断是图片后还会进行第二次图片渲染,图片的十六进制内容会发生很多变化。送上一个很好的分析文章(思路)

Pass-17

[源码]

$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 = '上传出错!';
}
}

[分析]

条件竞争绕过(参考文章)

Pass-19

CVE-2015-2348 move_uploaded_file() 00截断

Pass-20

Pass-20参考文章


笔者注

Upload-labs是在去年接触并做了部分Pass,近期整理资料发现了这份没有完成的稿子,于是闲暇之余所有Pass整理汇总(部分Pass由于环境的约束和时间不适没有测试,转载了前辈的文章)

Upload-labs考查了绝大多数目前主流的文件上传方法和解析,在测试学习的过程中更可以学会避开文件上传的风险。

防御文件上传的方法离不开:

  • 前端限制:利用Js代码限制上传的文件类型,但这是不可靠且不可不用的方法,前端的一切防御都可以经过数据抓包进行绕过

  • 检查扩展名:后端检查MIME的意义并不大,但可以对文件的扩展名进行检测(绕过方法也是多种),这里建议首先将PHP升级到5.4以上的版本规避00字节绕过、按照安全的配置要求配置Apache(同时也是建议Nginx);对扩展名进行完整的截取检查比对黑名单(或采用白名单机制也可以,具体需求具体设计,当然了,白名单是更加安全);记住是严格的后缀名检查!!!

  • 检查解析漏洞:检查是否存在解析漏洞,如果存在解析漏洞绕过白/黑名单是轻而易举的;笔者从各处收集了一些解析漏洞的文章,供参考:

  • 分析文件头内容来检查文件类型:这类方法不是检查文件后缀那般的简单,而是对文件内容进行检查;利用各类文件特定类型都会有不一样的标志位和开头;可利用php的exif_imagetype()函数(也可以自己编写)

  • 其他防御策略非常的多,笔者暂未深入研究安全防御的策略建立

Upload-labs 测试笔记的更多相关文章

  1. SUCTF 2019 Upload labs 2 踩坑记录

    SUCTF 2019 Upload labs 2 踩坑记录 题目地址 : https://github.com/team-su/SUCTF-2019/tree/master/Web/Upload La ...

  2. RGMII_PHY测试笔记1 基于开发板MiS603-X25

    RGMII_PHY测试笔记1 基于开发板MiS603-X25 作者:汤金元 日期:20150817 公司:南京米联电子科技有限公司 博客:http://blog.chinaaet.com/detail ...

  3. 【转载】Scrapy安装及demo测试笔记

    Scrapy安装及demo测试笔记 原创 2016年09月01日 16:34:00 标签: scrapy / python   Scrapy安装及demo测试笔记 一.环境搭建 1. 安装scrapy ...

  4. Linux内存带宽的一些测试笔记

    Linux内存带宽的一些测试笔记 首页 所有文章 2014年10月 GNU/Linux系统  2014-10-21 13:20  GNU/LINUX系统 内存带宽 1k 字  669 次 最近要测一下 ...

  5. MySQL数据库Inception工具学习与测试 笔记

    MySQL语句的审核,在业界都已经基本被认同了,实际上也是对MySQL语句写法的统一化,标准化,而之前的人工审核,针对标准这个问题其实是很吃力的,标准越多,DBA越累,开发也越累. 那么在这个都追求自 ...

  6. Linux内存带宽的一些测试笔记【转】

    转自:https://blog.csdn.net/subfate/article/details/40343497 版权声明:本文为迟思堂主人李迟原创文章,版权所有.可随便任意使用(包括学习研究商用) ...

  7. Brup Suite 渗透测试笔记(七)

    继续接上次笔记: 1.Burp Intruder的payload类型的子模块(Character blocks)使用一种给出的输入字符,根据指定的设置产生指定大小的字符块,表现形式为生成指定长度的字符 ...

  8. Brup Suite 渗透测试笔记(五)

    之前章节记到Burp Intruder功能区,接上次笔记 一.首先说再展开说说Brup Intruder功能, 1.标识符枚举Web应用程序经常使用标识符来引用用户账户,资产数据信息. 2.提取有用的 ...

  9. metasploit渗透测试笔记(内网渗透篇)

    x01 reverse the shell File 通常做法是使用msfpayload生成一个backdoor.exe然后上传到目标机器执行.本地监听即可获得meterpreter shell. r ...

随机推荐

  1. 接口测试 requests的身份认证方式

    requests提供多种身份认证方式,包括基本身份认证.netrc 认证.摘要式身份认证.OAuth 1 认证.OAuth 2 与 OpenID 连接认证.自定义认证.这些认证方式的应用场景是什么呢? ...

  2. eclipse中maven项目failonmissingwebxml错误的修复(转)

    在使用eclipse创建maven项目的时候,有时候会出现这个问题: web.xml is missing and 'failOnMissingWebXml' is set to true我遇到这个问 ...

  3. WordPress 安装主题、插件时问题解决办法

    --当能够在外网访问到自己的博客时,很多人都会很兴奋吧!如果环境是自己配置的,而不是用的集成环境肯定也会有点小小的成就感. --但是在我兴奋的时候遇到了个小麻烦,下载插件提示我输入FTP信任凭据,输了 ...

  4. Mac开发环境部署

    1. 安装 Xcode command line tools xcode-select --install 2. 安装 Homebrew 安装 Homebrew 之前,必须先安装 Xcode Comm ...

  5. Java入门教程九(封装继承多态)

    封装 封装就是将对象的属性和方法相结合,通过方法将对象的属性和实现细节保护起来,实现对象的属性隐藏.做法就是:修改属性的可见性来限制对属性的访问,并为每个属性创建一对取值(getter)方法和赋值(s ...

  6. Golang/Python/PHP带你彻底学会gRPC

    目录 一.gRPC是什么? 二.Protocol Buffers是什么? 三.需求:开发健身房服务 四.最佳实践 Golang 1. 安装protoc工具 2. 安装protoc-gen-go 3. ...

  7. MySQL基础篇(05):逻辑架构图解和InnoDB存储引擎详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.MySQL逻辑架构 1.逻辑架构图 基于下面的逻辑架构图,可以大致熟悉MySQL各个架构组件之间的协同工作关系. 很经典的C/S架构风格, ...

  8. Linux命令学习神器!命令看不懂直接给你解释!

    大家都知道,Linux 系统有非常多的命令,而且每个命令又有非常多的用法,想要全部记住所有命令的所有用法,恐怕是一件不可能完成的任务. 一般情况下,我们学习一个命令时,要么直接百度去搜索它的用法,要么 ...

  9. C#开发BIMFACE系列30 服务端API之模型对比1:发起模型对比

    系列目录     [已更新最新开发文章,点击查看详细] 在实际项目中,由于需求变更经常需要对模型文件进行修改.为了便于用户了解模型在修改前后发生的变化,BIMFACE提供了模型在线对比功能,可以利用在 ...

  10. 吐槽苹果开放接口のappleid登陆

    这里吐槽一下苹果的开发文档,一切源于前段时间,公司的产品app(某知名资讯app)要接入苹果登陆(ios13发布以来,apple就流氓要求新上线的app,如果有第三方登陆的话,必须要接入appleid ...