upload-labs靶场下载地址
https://gitcode.net/mirrors/tj1ngwe1/upload-labs?utm_source=csdn_github_accelerator
需要新建一个upload文件夹,该靶场在php5.2.17版本下(除特殊说明的情况下)。
Pass-01(前端验证绕过)
先上传一个php文件看一下回显
然后上传一个正常文件,发现回显正常。查看了一下网页源代码,发现上传文件检查是通过前端进行验证的,那么有很多种方法继续绕过。
源码分析
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;
}
}
getElementsBy()
方法可以返回指定名称的对象的集合。
substring(起始索引,结束索引)
返回字符串的子字符串。
lastIndexOf()
方法可返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索。
方法一
直接禁用js就可以上传了,以火狐浏览器为例,按f12,在‘调试器’面板最右边有个设置按钮,禁用js。
然后把写好的php文件再次上传,发现没有提示文件错误。
访问http://localhost/upload-labs-master/upload/1.php
,显示成功上传
不过实战中直接禁用js插件会导致一些页面无法正常显示,这种只能打打靶场就行了。
方法二
右键查看网页源代码 — 复制全部代码 — 将代码放在一个txt文件中 — 将后缀改为html — 用编辑器打开 — 找到js代码并删除(删除红框里的代码)
然后在在上面添加一段action
,地址是图片上传的地址,我们在这加上来
然后用浏览器打开这个html文件,直接进行上传操作即可。然后上传一个在原页面上传个正常的图片,按F12,然后随便上传一个图片,在"网络"模块中可以找到上传地址
访问对应所上传的php文件即可。
方法三
新建一个png文件,写入<?php phpinfo();?>
,然后burpsuite工具抓包,直接修改后缀名为.php然后点击Forward即可完成上传
访问上传地址即可。
Pass-02(Content-Type方式绕过)
源码分析
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) { //判断是否点击上传按钮
if (file_exists($UPLOAD_ADDR)) { //判断UPLOAD_PATH文件路径是否存在 UPLOAD_PATH在config.php中定义为"../upload"
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) { //判断上传文件的类型是否为image/jpeg、image/png、image/gif
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) { //将文件上传到指定路径中
$img_path = $UPLOAD_ADDR . $_FILES['upload_file']['name'];
$is_upload = true;
}
} else {
$msg = '文件类型不正确,请重新上传!';
}
} else {
$msg = $UPLOAD_ADDR.'文件夹不存在,请手工创建!';
}
}
攻击方法
这题主要考察对数据包MIME检查。上传一个1.php文件,通过抓包修改文件类型进行绕过。
点Forward放包即可。
Pass-03(黑名单绕过)
源码分析
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$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)) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR. '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR .'/'. $_FILES['upload_file']['name'];
$is_upload = true;
}
} else {
$msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
}
} else {
$msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
}
}
trim(string,charlist) 函数移除字符串两侧的空白字符或其他预定义字符。
deldot()函数,是作者自定义的函数,作用是删除文件名末尾的点。
strrchr(string,char)函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。
strtolower(string) 函数把字符串转换为小写。
str_ireplace(find,replace,string,count) 函数替换字符串中的一些字符(不区分大小写)
in_array(search,array,type) 函数搜索数组中是否存在指定的值。
这里可以知道黑名单array('.asp','.aspx','.php','.jsp')
,但是并没有过滤phtml,php3,php4, php5, pht
,可以通过这些后缀名进行黑名单绕过,但是要在httpd.conf配置文件添加下面这段
AddType application/x-httpd-php .php .phtml .php3 .php5
AddType application/x-httpd-php-source .phps
php版本为5.4.45,而不是5.4.45-nts
参考:https://blog.csdn.net/CSDN_caiqian/article/details/129493643
攻击方法
新建一个以.php5
为后缀的文件,写入一句话木马,直接上传即可。这里需要通过F12网络模式查看文件路径
访问即可。
Pass-04(.htaccess文件绕过)
源码分析
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".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)) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . $_FILES['upload_file']['name'];
$is_upload = true;
}
} else {
$msg = '此文件不允许上传!';
}
} else {
$msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
}
}
黑名单有很多,很显然不能用黑名单绕过了,这里没有禁用.htaccess
,该文件可以把图片解析为php,需要在.htaccess
里写入
<FilesMatch "1.png"> //xxx由自己定义,定义什么则上传相同文件
SetHandler application/x-httpd-php
</FilesMatch>
攻击方法
先上传.htaccess
,再上传1.png
Pass-05(后缀大小写绕过)
源码分析
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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)) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . '/' . $file_name;
$is_upload = true;
}
} else {
$msg = '此文件不允许上传';
}
} else {
$msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
}
}
黑名单把.htaccess
给禁了,对比第4关的源码发现,缺少了$file_ext = strtolower($file_ext);
将字符串转为小写。那么我们可以上传大写的文件后缀,创建1.Php
上传。
攻击方法
新建1.Php
,写入<?php phpinfo();?>
,上传,访问即可。
Pass-06 (文件后缀(空)绕过)
源码分析
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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
if (!in_array($file_ext, $deny_ext)) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . '/' . $file_name;
$is_upload = true;
}
} else {
$msg = '此文件不允许上传';
}
} else {
$msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
}
}
对比第4关,少了$file_ext = trim($file_ext);
去除首位空白字符,既然最后一步没有去空操作,那么我们可以创建一个文件1.php
,通过bp抓包修改文件名后缀包含空字符。
攻击方法
新建1.php
,通过bp抓包
放包即可。
Pass-07 (文件后缀(点)绕过)
源码分析
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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)) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . '/' . $file_name;
$is_upload = true;
}
} else {
$msg = '此文件不允许上传';
}
} else {
$msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
}
}
比较第4关,少了$file_name = deldot($file_name);
删除文件名末尾的点,如1.php.
,由于没有删除末尾的点,传到file_ext
会是最后一个点后面的所以字符,那么就是空,空不在黑名单中,故可绕过。
攻击方法
新建一个1.php
,通过bp抓包修改文件后缀。
放包,访问路径即可。
Pass-08 (文件后缀(::$DATA)绕过)
源码分析
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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)) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . '/' . $file_name;
$is_upload = true;
}
} else {
$msg = '此文件不允许上传';
}
} else {
$msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
}
}
比较第4关,少了$file_ext = str_ireplace('::$DATA', '', $file_ext);
将文件后缀中的::$DATA
字符串替换为空,这里利用了windows特性
在window的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名,他的目的就是不检查后缀名
例如:"phpinfo.php::$DATA"Windows会自动去掉末尾的::$DATA变成"phpinfo.php"
攻击方法
新建一个1.php
,通过bp抓包
放包,访问即可
Pass-09 (构造文件后缀绕过)
源码分析
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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)) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . '/' . $file_name;
$is_upload = true;
}
} else {
$msg = '此文件不允许上传';
}
} else {
$msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
}
}
观察源码,比较第4关没有差别,仔细看下代码,发现没有循环验证,也就是说去除文件名末尾点只删除一次,那么我们是不是可以在后缀加两个点(两个点之间加个空格,因为deldot()函数是从文件名最后面开始判断是否为点,如果是则匹配下一个,如果两个点连在一起,则会一起被删除)进行绕过,显然是可以的。
附deldot()函数代码:
function deldot($s){
for($i = strlen($s)-1;$i>0;$i--){
$c = substr($s,$i,1);
if($i == strlen($s)-1 and $c != '.'){
return $s;
}
if($c != '.'){
return substr($s,0,$i+1);
}
}
}
攻击方法
新建一个1.php
,通过bp抓包
放包,访问即可
这里除了构造1.php. .
还有1.phP. .
、1.php. . .
都差不多。
Pass-10 (双写文件后缀绕过)
源码分析
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","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);
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $file_name)) {
$img_path = $UPLOAD_ADDR . '/' .$file_name;
$is_upload = true;
}
} else {
$msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
}
}
这里少了很多函数,不过这一关主要考察双写绕过,关键函数在$file_name = str_ireplace($deny_ext,"", $file_name);
在file_name中查找deny_ext中的值,若找到则替换为空,很显然我们若构造1.pphphp
,这会把中间的php给替换掉,则剩下的字符自动拼接成php,即可进行绕过。
攻击方法
新建一个1.pphphp
,上传,然后访问地址即可。
Pass-11 (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类型文件!";
}
}
strrpos($_FILES['upload_file']['name'],".")函数查找文件名中最后一个点号(.)的位置。
substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1) 是使用 substr() 函数,从文件名中截取最后一个点号之后(不包括点号)的所有字符,即得到文件的扩展名。
date("YmdHis") 是获取当前日期和时间的格式化字符串,即时间戳
rand(10, 99) 是生成一个介于 10 和 99 之间的随机整数。
这里可以看到上传路径是可控变量,$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
,这里通过get传参给save_path赋值,但是我们可以通过抓包进行修改。在url中%00表示ascll码中的0 ,0x00是十六进制表示方法,也是ascii码为0的字符,在有些函数处理时,会把这个字符当做结束符。所以我们在save_path参数后面加%00截断后面的字符串,那么上传路径为/upload/1.php
,即可上传成php文件解析。
不过%00截断是旧时产物,需要使用条件
php版本小于5.3.4
php的magic_quotes_gpc为OFF状态
攻击方法
新建一个1.png
,写入<?php phpinfo();?>
,然后上传抓包。
放包,访问即可。
Pass-12 (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类型文件!";
}
}
这里唯一的不同就是save_path参数是使用post传参的形式,那么我们改成post传参即可。但有一点说明,gei传参会自动解码url编码后的字符,但是post传参不会,我们是传参时,需解码。
攻击方法
新建一个1.png
,写入<?php phpinfo();?>
,然后上传抓包。(选中%00右键点击Convert selection选中URL,有URLdecode解码)
这里我用的2022.6.1版的bp,所以解码后是空白的,不过不影响,直接放包即可。
Pass-13 (图片马绕过)
源码分析
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_ADDR."/".rand(10, 99).date("YmdHis").".".$file_type;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
}
else{
$msg = "上传失败";
}
}
}
@unpack("C2chars", $bin) 这行代码用于对二进制数据进行解包(unpack),将其转换为 PHP 的数据类型。
解包格式字符串 "C2chars" 的含义是:
"C" 表示解包为无符号字符(unsigned char)类型。
"2" 表示要解包两次,因为 2 是重复次数。
"chars" 是解包后的结果的键名。
intval($strInfo['chars1'].$strInfo['chars2']) 将解包后的无符号字符转换为整数类型
这里的意思就是上传的文件取内容的前2个字节进行判断,若是png、gif、jpg格式的则上传,否则不上传,那么我们需要使用图片
标签:name,19,upload,labs,ext,file,msg,上传 From: https://www.cnblogs.com/L00kback/p/17547260.html