PHP文件上传中fileinfo出现的安全问题

本文详细介绍了PHP的fileinfo扩展,用于检测上传文件的MIME类型,防止文件类型伪装。通过开启fileinfo并使用其常量,如FILEINFO_MIME_TYPE,来判断文件的真实类型。然而,通过示例展示了即使fileinfo检测到的MIME类型正确,依然可能存在安全漏洞,因为伪造文件头可以绕过检查。文章通过实际操作演示了如何上传一个伪装的PHP文件并通过更改文件头使其被误判为合法的图片文件,从而揭示了fileinfo检测的安全隐患。

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

什么是fileinfo

fileinfo的函数通过在文件的给定位置查找特定的魔术字节序列 来猜测文件的内容类型以及编码,也就是说我们可以获得上传文件的MIME信息

在windows中我们可以在php.ini中开启
在这里插入图片描述

extension=fileinfo

在linux中开启fileinfo

找到fileinfo的路径
执行命令:find / -name fileinfo,查询到fileinfo所在目录
执行phpsize命令
执行命令:/usr/local/php/bin/phpize
执行configure配置
执行命令:./configure --with-php-config=/usr/local/php/bin/php-config
注意:如果提示php-config命令不存在,则需要先安装php-devel,执行命令:yum install php-devel。
编译安装
命令:make && make install
修改php.ini文件
在php.ini文件中添加extension=fileinfo.so

在打开fileinfo后我们就可以使用fileinfo扩展了
那fileinfo包括哪些呢
在这里插入图片描述
像如图红圈中的那些都是fileinfo扩展。

fileinfo预定义常量

常量名作用
FILEINFO_NONE无特殊处理
FILEINFO_SYMLINK跟随符号链接
FILEINFO_MIME_TYPE返回 mime 类型。 自 PHP 5.3.0 可用
FILEINFO_MIME_ENCODING返回文件的 mime 编码。 自 PHP 5.3.0 可用
FILEINFO_MIME按照 RFC 2045 定义的格式返回文件 mime 类型和编码
FILEINFO_COMPRESS解压缩压缩文件。 由于线程安全问题,自 PHP 5.3.0 禁用
FILEINFO_DEVICES查看设备的块内容或字符
FILEINFO_CONTINUE返回全部匹配的类型
FILEINFO_PRESERVE_ATIME如果可以的话,尽可能保持原始的访问时间
FILEINFO_RAW对于不可打印字符不转换成 \ooo 八进制表示格式
FILEINFO_EXTENSION根据 MIME 类型返回适当的文件扩展名。 有的文件类型具有多种扩展名,例如 JPEG 将会返回多个扩展名,以斜杠分隔,比如 “jpeg/jpg/jpe/jfif”。如果在 magic.mime 数据库里类型未知,则返回的是 “???”。 PHP 7.2.0 起有效

如何使用fileinfo去过滤上传文件

首先我们要创建一个 fileinfo 资源,然后就可以调用 fileinfo 资源了

$file = $_FILES;
$finfor = finfo_open(FILEINFO_MIME_TYPE);
$info = finfo_file($finfor, $file['jpg']['tmp_name']); //拿上传文件的MIME头与finfo_open()返回mime类型进行比较返回真实的mime头

此时若上传文件是txt文件伪造后的jpg等图片文件则会返回一个txt文件的mime头
那修改掉数据包中的mime头可以绕过吗?
在这里插入图片描述
上面这图就是直接上传的一个txt改jpg图片文件的,可以看到他的mime类型为image/jpeg

POST /study/wjsc/sc.php HTTP/1.1
Host: 192.168.0.106
Content-Length: 199
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://192.168.0.106
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarymrijfqP5su2sSW5Y
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.0.106/study/wjsc/sc.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

------WebKitFormBoundarymrijfqP5su2sSW5Y
Content-Disposition: form-data; name="jpg"; filename=".jsp.jpg"
Content-Type: image/jpeg

<?php phpinfo();?>
------WebKitFormBoundarymrijfqP5su2sSW5Y--

看一下上传后的效果
在这里插入图片描述
提示不合法,可以看一下返回的mime类型
在这里插入图片描述
返回为text/x-php类型。

如何去绕过fileinfo检测

这样写看似安全,但是由于fileinfo的检测原理恰恰会出现安全漏洞。
首先,先上传一个正常的图片
在这里插入图片描述
提示合法。
那接下来若上传的是一个图片马呢
图片马的合成
在这里插入图片描述
提示合法,可以看到mime类型也是image/png,那由此可见fileinfo也不是无敌的。
在这里插入图片描述
接下来就是思考正常的图片与伪造过后的图片有哪些不一样,在一张图片中大概是由文件头和内容组成那伪造的图片除了内容以外就是文件头的问题了
在伪造的文件中加上GIF89a,然后上传。
在这里插入图片描述
可以看到提示合法
在这里插入图片描述
就这样就绕过了fileinfo的检测
方便实验我将文件后缀改成了.php
在这里插入图片描述
执行成功!
在墨者学院的在线靶场中也存在一样的漏洞靶场可以帮助快速了解这个漏洞

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值