upload-labs(文件上传)总结
March 20, 2019 WEB安全 访问: 27 次
由于个人原因,需要重新看一个web的基本漏洞,所以抽时间重新过一遍
pass-01
首先上传一个php文件,发现提示
该文件不允许上传,请上传.jpg|.png|.gif类型的文件,当前文件类型为:.php
查看源代码发现检测文件类型的是js代码:
<script type="text/javascript">
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;
}
}
</script>
要绕过js代码的方法很简单,js验证实在发送到服务器端之前而验证的,那么我们就可以在此之前做点手脚
首先我们将一句话木马写进去一个php文件,把后缀改成“.jpg”,然后上传文件,用BurpSuite抓住这个数据包
把这个数据包发送到Repeater模块,在这里将文件名muma.jpg改成muma.php,然后go(发送数据包)
发现已经成功的传到了服务器端
pass-02
同样先上传一个php文件,发现页面返回:
提示:文件类型不正确,请重新上传!
在http数据包中,判断文件类型的是Content-Type字段的值
同样抓包,修改Content-Type为image/jpeg
成功上传到服务器上去
pass-03
上传php文件提示:
提示:不允许上传.asp,.aspx,.php,.jsp后缀文件!
发现这一关是利用了黑名单限制,那么我们试一下php的别名,如php2、php3、php5、phtml、pht等
一开始我上传了一个php3的文件,虽然成功上传上去了,但是去访问的时候没有解析成php
查资料发现需要修改httpd.conf:(把前面的#去掉)
AddType application/x-httpd-php .php .phtml .php3 .php4 .php5 .php2
然后再次访问刚刚上传的php3文件,发现成功解析
(上传后的文件路径页面上有返回)
pass-04
根据提示我们可以看出,这一关的黑名单已经限制的很全了,几乎包含了所有php类似的后缀,但是没有限制“.htaccess”
htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。
也就是说,我们将需要的配置写进一个".htaccess"文件里,然后上传到服务器
在这里我们可以在".htaccess"写进去:
<FilesMatch "jpeg">
SetHandler application/x-httpd-php
</FilesMatch>
这三句话的意思就是把本目录下的jpeg文件当做php来解析
新建一个内容为下面的jpeg文件:
<?php phpinfo();?>
上传到服务器上之后访问这个文件,可以看到该文件成功的被当做php文件来解析了
pass-05
本关黑名单把".htaccess"也给限制了。
经过尝试发现大小写可以绕过
可以将php文件名后缀改成Php、pHp、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 . '文件夹不存在,请手工创建!';
}
}
发现没有去除文件名前后的空格,我们可以在文件名字后面加一个空格,绕过黑名单检测
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 . '文件夹不存在,请手工创建!';
}
}
通过查看源码发现,本关少了去除文件名最后的点的操作,要想利用到这一点,我们必须知道windows操作系统的一个特性
在windows操作系统中,会自动去掉后缀名中的“.”(可以尝试一下)
在文件名后面加上一个点,成功上传文件
pass-08
本关还是通过利用windows操作系统的一个特性
在文件名后面加上"::$DATA",成功上传文件
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 . '文件夹不存在,请手工创建!';
}
}
通过查看源码,按照源码上对文件名的操作我们可以做出相对应的文件名,经过测试我们可以在文件名后面加上“. .”(点+空格+点)
pass-10
查看提示发现,本关会去除这些字符,那么就想到了双写绕过
本pass会从文件名中去除.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|.htaccess字符!
pass-11
提示上传路径可控,那么我们就可以考虑一下00截断,在实验的机器php版本不符合,所以没有成功上传上去。
pass-12
同pass-11,GET改成了POST
pass-13
要求上传一个图片马,提示上说只检测前两个字节,那么我们可以伪造一下文件头
常用文件头:
(1) .JPEG;.JPE;.JPG,”JPGGraphic File”
(2) .gif,”GIF 89A”
(3) .zip,”Zip Compressed”
(4) .doc;.xls;.xlt;.ppt;.apr,”MS Compound Document v1 or Lotus Approach APRfile”
pass-14
查看提示:
本pass使用getimagesize()检查是否为图片文件!
直接利用图片马直接就可以过,制作图片马的方法:
将随意的一个图片和一个一句话木马结合在一起;
1.jpg
1.php
在Windows的cmd中执行命令:copy 1.jpg/b + 1.php /a shell.jpg
pass-15
用pass-14的方法就可以上传
pass-16
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 = '上传出错!';
}
}
流程是先把文件上传到服务器上,然后再判断是不是符合类型,如果不符合,那么用unlink函数删除该文件,如果符号,用rename函数修改文件名
那么我们可以利用条件竞争来在unlink之前,访问shell
shell.php
<?php
system("whoami");
?>d
pass-18
原理用pass-17
pass-19
提示文件名可以控制,我们可以利用文件名加点来绕过检测
pass-20
审计代码后发现,如果我们输入的是一个数组的话,那么就不会分割我们的文件名,而是直接操作这个数组,根据代码我们可以传入:
$file[0] = wxm.php
$file[2] = jpg
我们没有定义$file[1],所以count($file)等于2,那么$file[count($file)-1]就为空,最后文件名就是$file[0]