Web文件上传漏洞

本文探讨了PHP文件上传的基本漏洞,如00截断、字符集转换导致的截断和后缀黑名单绕过技巧,包括文件重命名和不重命名的实例,以及如何防范这些攻击。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 概述

文件上传在Web业务中很常见,如用户上传头像、编写文章上传图片等。在实现文件上传时,如果后端没有对用户上传的文件做好处理,会导致非常验中的安全问题,如服务器被上传恶意木马或者垃圾文件。

2. 基础文件上传漏洞

PHP的文件上传通常使用move_uploaded_file方法配合 $_FILES 变量实现。

<?php 
$file = $_FILES['file'];
move_uploaded_file($file['tmp_name'], $file['name']);
.......
?>

3. 截断绕过上传限制

3.1 00截断

00截断是绕过上传限制的一种常见方法。在C语言中,\0 是字符串的结束符,如果用户能够传入 \0 ,就能实现截断。

00截断绕过上传限制适用的场景为,后端先获取用户上传文件的文件名,如 x.php/00.jpg ,再根据文件名获得文件的实际后缀 jpg ;通过后缀的白名单校验后,最终在保存文件时发生截断,实现上传的文件为 x.php 。

PHP的底层代码为C语言,自然存在这种问题,但是实际PHP使用 $_FILES 实现文件上传时并不存在00截断绕过上传限制问题,因为PHP在注册 $_FILES 全局变量时已经产生了截断。上传文件名为 x.php/00.jpg 的文件,而注册到 $_FILES['name'] 的变量值为 x.php ,根据该值得到的后缀为 php ,因此无法通过后缀的白名单校验。

3.2 转换字符集造成的截断

虽然 PHP 的 $_FILES 文件上传不存在00截断绕过上传限制的问题,不过在文件名进行字符集转换的场景下也可能出现截断绕过。PHP在实现字符集转换时通常使用iconv()函数,UTF-8在单字节时允许的字符范围为0x00~0x7F,如果转换的字符不在该范围内,则会造成 PHP_ICONV_ERR_ILLEGAL_SEQ 异常,低版本PHP在 PHP_ICONV_ERR_ILLEGAL_SEQ 异常后不再处理后面字符从而造成截断问题。当PHP版本低于5.4时,转换字符集能够造成截断,但5.4及以上版本会返回 false 。

转换字符集造成的截断在绕过上传限制中适用的场景为,先在后端获取上传的文件后缀,经过后缀白名单判断后,如果有对文件名进行字符集转换操作,那么可能出现安全问题。

3.3 文件后缀黑名单校验绕过

黑名单校验上传文件后缀,即通过创建一个后缀名的黑名单列表,在上传时判断文件后缀名是否在黑名单列表,在黑名单中则不进行任何操作,不在则可以上传,从而实现对上传文件的过滤。

3.3.1 上传文件重命名

在文件名重命名的场景下,可控的只有文件后缀,通常使用一些比较偏门的可解析的文件后缀绕过黑名单限制。
PHP常见的可执行后缀为PHP3、PHP5、phtml、pht等,ASP常见的可执行后缀为cdx、cer、asa等,JSP等

3.3.2 上传文件不重命名

3.3.2.1 上传 .htaccess 文件绕过黑名单

.htaccess是Apache分布式配置文件的默认名称,也可以在Apache主配置文件中通过AccessFileName指令修改分布式配置文件的名称。

3.3.2.2 上传 .user.ini 文件绕过黑名单

References:

《从0到1 CTFer成长之路》
《CTF特训营》

### PHP Web 文件上传漏洞安全性解决方案 #### 一、文件类型验证不足引发的安全风险 当处理文件上传功能时,如果仅依赖于客户端提交的数据而不做服务器端校验,则可能导致恶意用户绕过前端限制上传危险文件。例如,在Apache环境下,默认情况下不识别`.rar`这样的压缩包扩展名,这使得它可能会错误地解析并执行这些看似无害但实际上可能隐藏着PHP代码的文件[^1]。 #### 二、具体实现措施 为了避免上述提到的风险以及其他潜在威胁,应当采取如下策略: - **严格限定允许上传的MIME类型** 通过配置应用程序逻辑来过滤掉不符合预期格式的文件。对于图片类资源而言,只接受JPEG、PNG等常见图形格式;而对于文档则应限缩至PDF、Word等形式。 ```php $allowed_mime_types = ['image/jpeg', 'image/png']; if (!in_array($_FILES['uploaded_file']['type'], $allowed_mime_types)) { die('Invalid file type.'); } ``` - **检查实际内容而非仅仅依靠声明的扩展名** 即使设置了严格的白名单机制,也不能完全排除伪造请求的可能性。因此还需要借助第三方库或者内置函数检测真实的内容编码方式,防止伪装成合法形式却携带非法指令的情况发生。 ```php $finfo = finfo_open(FILEINFO_MIME_TYPE); $mimetype = finfo_file($finfo, $_FILES['uploaded_file']['tmp_name']); finfo_close($finfo); // 进一步对比mimetype是否匹配预设列表... ``` - **临时保存路径设置为不可访问目录** 考虑到某些特殊场景下仍有可能存在漏网之鱼,故而推荐将接收到的新文件暂时存放在Web根目录之外的位置等待后续审核操作完成后再决定最终位置。 ```bash mkdir /var/www/html/uploads/temp/ chmod 700 /var/www/html/uploads/temp/ ``` - **启用沙盒模式加强防护力度** 参照最佳实践指南中的建议,在正式入库前先让待审资料处于受限环境中运行一段时间以便观察是否存在异常行为表现出来[^3]。 #### 三、总结说明 综上所述,针对PHP开发过程中涉及到的文件上传环节所面临的一系列安全隐患问题,除了要遵循官方给出的相关指导方针外,还应该结合实际情况灵活调整优化方案,从而最大程度降低遭受外部攻击的概率保障业务稳定可靠运转。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值