绕过的思考
web应用程序往往允许客户端上传文件,但是程序员如果不对上传的文件进行验证和限制就会导致文件上传漏洞。检测上传的文件有俩方面,客户端检测和服务器端检测。
客户端绕过
客户端是通过js代码来实现对文件的检测。那么攻击者就可以控制js代码来绕过或者修改http请求绕过。
控制js代码
一段前端代码
<form action="" method="post" enctype="multipart/form-data" onsubmit="return checkfilesuffix()">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>
function checkfilesuffix()
{
var file=document.getElementsByName('file')[0]['value'];
if(file==""||file==null)
{
alert("请添加上传文件");
return false;
}
else
{
var whitelist=new Array(".jpg",".png",".gif");
var file_suffix=file.substring(file.lastIndexOf("."));
if(whitelist.indexOf(file_suffix) == -1)
{
alert("该文件不允许上传");
return false;
}
}
}
当选择完上传文件之后,会提交From表单。From表单触发onsubmit事件,onsubmit事件会调用checkfile函数。可以直接将From表单里的onsubmit事件删除,即可绕过。
bp修改请求数据包
bp抓到传输的数据包修改filename文件的扩展名,同时修改Content-Length(Content-Length表示实体正文的长度)。 比如:Content-Length长度是200,filename是"xss.jpg";filename修改为"1.php",Content-Length长度就应该变为198,如果不修改那么文件上传就可能会失败。
服务器端绕过
前端验证毕竟简单,所以后端验证显得尤为重要。服务器端验证主要包括以下几种:
MIME检测
MIME类型用来设定某种扩展名文件的打开方式,当具有该扩展名的文件被访问时浏览器会自动使用指定的应用程序打开。如GIF图片MIME类型为image/gif,CSS文件MIME类型为text/css。在HTTP中对应的是Content-Type。 上传PHP文件时,HTTP请求里的Content-type字段对应的就是MIME类型,修改Content-type字段即可绕过MIME类型的检测。 MIME验证代码
<?php
header("Content-type: text/html;charset=utf-8");
error_reporting(0);
define("UPLOAD_PATH", dirname(__FILE__) . "/upload/");
define("UPLOAD_URL_PATH", str_replace($_SERVER['DOCUMENT_ROOT'], "", UPLOAD_PATH));
if (!file_exists(UPLOAD_PATH)) {
mkdir(UPLOAD_PATH, 0755);
}
if (!empty($_POST['submit'])) {
if (!in_array($_FILES['file']['type'], ["image/jpeg", "image/png", "image/gif", "image/jpg"])) {
echo "<script>alert('文件类型不正确')</script>";
} else {
$name = basename($_FILES['file']['name']);
if (move_uploaded_file($_FILES['file']['tmp_name'], UPLOAD_PATH . $name)) {
echo "<script>alert('上传成功')</script>";
echo "上传文件相对路径<br>" . UPLOAD_URL_PATH . $name;
} else {
echo "<script>alert('上传失败')</script>";
}
}
}
?>
00截断
php环境00截断的条件
- php版本小于5.3.29
- magic_quotes_gpc = Off
在读取字符串时遇到%00可以截断字符串。ctf不同的00截断题目有不同的解法。ctfhub 00截断,这道题的WP。 PHP pathinfo函数
<form action=?road=/var/www/html/upload/ method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>
if (!empty($_POST['submit'])) {
$name = basename($_FILES['file']['name']);
$info = pathinfo($name);
$ext = $info['extension'];
$whitelist = array("jpg", "png", "gif");
if (in_array($ext, $whitelist)) {
$des = $_GET['road'] . "/" . rand(10, 99) . date("YmdHis") . "." . $ext;
if (move_uploaded_file($_FILES['file']['tmp_name'], $des))
{
echo "<script>alert('上传成功')</script>";
} else {
echo "<script>alert('上传失败')</script>";
}
} else {
echo "文件类型不匹配";
}
}
双写后缀
先看一段php代码,这段代码很明显是查看$namel里面存不存在黑名单里的内容,如果存在就把它替换为“”。绕过策略很简单构造pphphp的后缀文件即可。
$name = basename($_FILES['file']['name']);
$blacklist = array("php", "php5", "php4", "php3", "phtml", "pht", "jsp", "jspa", "jspx", "jsw", "jsv", "jspf", "jtml", "asp", "aspx", "asa", "asax", "ascx", "ashx", "asmx", "cer", "swf", "htaccess", "ini");
$name = str_ireplace($blacklist, "", $name);
文件头检查
所谓的文件头检查是当上传文件后,服务器端的PHP代码对文件的文件头进行名单验证,符合上传规则就上传成功,反之上传失败。 文件头的相关知识:百度文件头介绍及常见的文件头。值得一提的是txt文件是没有文件头的,相同的内容的php文件与txt文件用winhex打开后内容是一样的。 绕过的策略:将jpg,png等符合上传规则的文件文件头截取,复制到php文件最前部分即可实现绕过。
.htaccess绕过
.htaccess文件可以配置很多事情,如是否开启站点的图片缓存、自定义错误页面、自定义默认文档、设置WWW域名重定向、设置网页重定向、设置图片防盗链和访问权限控制。.htaccess详解。 上传一个.htaccess文件修改配置信息,然后在上传一个命令执行文件就可以造成上传漏洞。大佬的文件漏洞博客。
<FilesMatch "is">
setHandler application/x-httpd-php
</FilesMatch>
后缀为is的文件解析为PHP文件
AddType application/x-httpd-php jpg
后缀为jpg结尾的文件当作PHP文件
|