upload-labs 1-10
Pass-1 前端JS验证绕过
第一关我们直接上传我们的一句话木马试试:
发现它不让上传除了.jpg|.png|.gif
之外后缀的文件。
我们可以查看网页源代码:
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;
}
}
发现这个网页的验证是在前端进行验证的。那我们可以想办法把这个验证去掉。
我们使用Burp来拦截这个网页请求并且把前端JS去除。
在Proxy
的Options
里把Response Modification
的Remove JavaStript from validation
给勾选上,这样就可以把网页中JS的验证表单给去除,前端就无法对我们的文件名进行验证。
做完这一步我们重新对页面进行加载,再次尝试上传我们的一句话木马:可以看到我们的一句话木马文件上传成功了。
我们使用蚁剑进行连接:
连接成功!
Pass-2 Content-Type绕过
第二关我们一样直接上传我们的一句话木马,发现一样是上传不了。
这一关是在后端进行验证,也就是说在靶机里进行验证。我们研究第二关的核心代码可以发现:它是对我们上传的http请求中的Content-Type
进行验证,只要满足image/jpeg|image/png|image/gif
中一个就行。
$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.'文件夹不存在,请手工创建!';
}
}
我们用Burp拦截上传的http请求:将Content-Type
的application/octet-stream
改成image/jpeg|image/png|image/gif
中的一个。
可以看到我们的一句话木马文件上传成功了。
我们使用蚁剑进行连接:可以成功连接!
可以成功连接!
Pass-3 .phtml绕过
做这个实验前我们要先改一下Apache
的配置文件:phpStudy\Apache\conf\httpd.conf
,将#AddType application/x-httpd-php .php .phtml
的#
删掉后重启一下服务。
这句话的意思是将后缀名是.phtml
的文件当成.php
执行。
不同的软件这个配置也不一样,常见的替换后缀名还有.php2|.php3|.php4|.php5|
,如果对方服务器开启了这个配置,可以多试几种不同的可替代.php
的后缀名。
改完配置之后我们一样直接上传我们的一句话木马,发现一样是上传失败。我们看看核心代码:
$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 . '文件夹不存在,请手工创建!';
}
}
它是在后端验证上传文件的后缀名的,只要是.asp|.aspx|.php|.jsp
的后缀名就不能上传,我们就可以用到替换.php
文件的后缀名。我们把一句话木马的后缀名改成.phtml
。
再次上传:可以看到我们的一句话木马文件上传成功了。
我们用蚁剑连接一下:
成功连接!
Pass4 .htaccess绕过
这一关和上一关很像,就是黑名单中的对象增加了:将一些可以替代.asp|.aspx|.php|.jsp
的文件名也加入了黑名单中。
我们看看核心代码:
$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 . '文件夹不存在,请手工创建!';
}
}
但是.htaccess
没有被加入黑名单中,.htaccess
是提供了针对目录改变配置的方法。我们就可以利用这个漏洞进行绕过。
首先我们先传入一个.htaccess
,里面的内容是:
<FilesMatch "aa.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
这段代码的意思是将名为aa.jpg
的文件当作.php
进行处理。
我们再将一句话木马的名字改成aa.jpg
进行上传。
可以看到两个文件都已经成功上传到靶机里了。
我们用蚁剑进行连接:
连接成功!
Pass5 大小写绕过
这一关作者把.htaccess
也加入黑名单了,我们来研究一下这一关的核心代码:
$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 . '文件夹不存在,请手工创建!';
}
}
发现这一关没有强制将后缀名转换成小写。那我们就可以用大写的后缀名进行绕过,将一句话木马的后缀名.php
改成.PHP
。
我们将改了后缀名的文件上传:可以看到我们的一句话木马文件上传成功了。
再用蚁剑进行连接。
连接成功!
Pass6 加空格染过
我们直接看这一关的核心代码:
$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 . '文件夹不存在,请手工创建!';
}
}
发现这一关虽然强制将后缀名转成小写,但是没有删除后缀名里的空格。
在windows系统里我们无论在一个文件的后缀名后加多少个空格,最后电脑都会自动忽略。这一关就可以利用windows系统的这一关特性进行绕过。
我们利用Burp来进行抓包,并且在我们上传的一句话木马的文件名后加上一个空格。
可以看到我们的一句话木马文件上传成功了。
用蚁剑来连接一下:
连接成功!
Pass7 .绕过
这一关我们也是直接来看核心代码:
$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 . '文件夹不存在,请手工创建!';
}
}
发现这一关没有对后缀名中的.
进行过滤。
在windows系统中,在后缀名后加.
系统会自己删掉这个.
。我们就可以利用windows系统这个特性进行绕过。
我们用Burp抓包,并且在我们上传的一句话木马的文件名后面加.
。
可以看到我们的一句话木马文件上传成功了。
我们用蚁剑连接一下:
连接成功!
Pass8 ::$DATA绕过
我们先看看这一关的核心代码:
$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
进行过滤。
在window系统中如果在文件名+::$DATA
会把::$DATA
之后的数据当成文件流处理,,且保持::$DATA
之前的文件名我们可以利用windows系统的这个特性进行绕过。
我们用Brup进行抓包,并且在我们上传的一句话木马的文件名后加上::$DATA
。
可以看到我们的一句话木马文件上传成功了。
我们用蚁剑来连接一下:
连接成功!
Pass9 . .绕过
我们先来看看这一关核心代码:
$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 . '文件夹不存在,请手工创建!';
}
}
我们可以发现这个代码会先删除我们文件名末尾的点再删除文件的首尾空格。我们可以利用这一点,再文件名末尾加上. .
,这样,再进行了删除操作后还会有一个.
剩下。
我们用Brup进行抓包,并且在我们上传的一句话木马的文件名后加上. .
。
可以看到我们的一句话木马文件上传成功了。
我们用蚁剑来连接一下:
连接成功!
Pass10 双写绕过
我们先来看看这一关的核心代码:
$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 . '文件夹不存在,请手工创建!';
}
}
我们可以发现这一关会把文件名中的在黑名单中的字符串删除,那我们就可以进行双写绕过,我们可以将.php
改成.pphphp
后进行上传。
可以看到我们的一句话木马文件上传成功了。
我们用蚁剑连接一下:
连接成功!