PHP文件上传安全:优化代码有效防范漏洞

2024-03-01 0 797
目录
  • 原生漏洞PHP示例代码:
  • 原生漏洞PHP漏洞优化意见(获取临时文件的真实类型):
  • 对Laravel框架,也有同样的问题,别用错函数:
  • 对Laravel任意文件上传漏洞优化意见(获取临时文件的真实类型):
  • 整体修复意见:
  • 扩展:
    • mime_content_type函数与(new \\finfo(\\FILEINFO_MIME_TYPE))->file('file_path')的区别?
    • (new \\finfo(\\FILEINFO_MIME_TYPE))->file('file_path')与finfo_file()的区别?
    • 什么是文件的魔术数字?

说明:任意文件上传漏洞,很多PHP开发者也会做一些简单的防护,但是这个防护有被绕过的可能。

原生漏洞PHP示例代码:

$file = $_FILES[\’file\’] ?? [];
//检测文件类型
$allow_mime = [\’image/jpg\’, \’image/jpeg\’, \’image/png\’, \’image/gif\’];
if(! in_array($file[\’type\’], $allow_mime)) {
echo json_encode([\’code\’ => 1, \’msg\’ => \”文件类型错误\”], JSON_UNESCAPED_UNICODE);
return;
}

print_r($file);

上传一个PHP文件,提示文件类型错误,使用ApiPost修改上传的Content-Type,把原先的application/x-httpd-php修改为image/png,则可绕过。因为:$_FILES['type']是根据上传文件的content-type获取的,并文件本身的mime-type,而content-type又可以被篡改。

原生漏洞PHP漏洞优化意见(获取临时文件的真实类型):

$file = $_FILES[\’file\’] ?? [];
//检测文件类型
$allow_mime = [\’image/jpg\’, \’image/jpeg\’, \’image/png\’, \’image/gif\’];
if(! in_array((new \\finfo(\\FILEINFO_MIME_TYPE))->file($file[\’tmp_name\’]), $allow_mime)) {
echo json_encode([\’code\’ => 1, \’msg\’ => \”文件类型错误\”], JSON_UNESCAPED_UNICODE);
return;
}

print_r($file);

对Laravel框架,也有同样的问题,别用错函数:

$file->getClientMimeType(); //相当于$_FILES[\’file\’][\’type\’];
$file->getMimeType(); //相当于(new \\finfo(\\FILEINFO_MIME_TYPE))->file($_FILES[\’file\’][\’tmp_name\’])

说话得有依据,经过反复的追Laravel的源码:

底层对getClientMimeType()的实现:
是在vendor/symfony/http-foundation/Request.php的createFromGlobals()中,基于$_FILES做的封装。
底层对getMimeType()的实现:
是在vendor/symfony/mime/FileinfoMimeTypeGuesser.php的guessMimeType()中,利用finfo的内置PHP类实现的。

对Laravel任意文件上传漏洞优化意见(获取临时文件的真实类型):

使用getMimeType函数。

整体修复意见:

先判断文件后缀,在判断临时文件的mime类型属性,不要根据请求头判断。

扩展:

mime_content_type函数与(new \\finfo(\\FILEINFO_MIME_TYPE))->file('file_path')的区别?

检测文件mime类型,还有一个mime_content_type();

  • mime_content_type()获取的mime类型,会与操作系统的mime类型有映射,意味着不同的系统可能存在一些小差别。
  • finfo类使用了 PHP 的 FileInfo 扩展。FileInfo 扩展利用了文件的特征签名(或称为魔术数字)来检测文件的实际类型,并根据文件的内容进行精确的 MIME 类型推断。

虽然两者相差不大,但是推荐用(new \\finfo(\\FILEINFO_MIME_TYPE))->file('file_path');

(new \\finfo(\\FILEINFO_MIME_TYPE))->file('file_path')与finfo_file()的区别?

使用finfo_file()也可以获取文件的mime类型。

$mime = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $file[\’tmp_name\’]);
$mime = (new \\finfo(FILEINFO_MIME_TYPE))->file($file[\’tmp_name\’]);

两者底层对获取mime类型的实现无差别,展示写法不同。

什么是文件的魔术数字?

文件的魔术数字是文件头部的一段特定的字节序列,用来描述文件的类型或格式,一般用16进制表示。文件的魔术数字一般包含一些特殊的字符和数字组成的固定长度的字节串,不同类型的文件具有不同的魔术数字。例如,PNG 图像文件的魔术数字为 89 50 4E 47 0D 0A 1A 0A,而 JPG 图像文件的魔术数字为 FF D8 FF E0 00 10 4A 46 49 46 00 01。PHP获取魔术数字实现方案:

$fileHandle = fopen($_FILES[\’file\’][\’tmp_name\’], \’rb\’);
$hex = \’\’;
while (! feof($fileHandle)) {
$byte = fread($fileHandle, 1);
$hex .= sprintf(\”%02X \”, ord($byte));
}
fclose($fileHandle);
echo $hex;

到此这篇关于PHP文件上传安全:优化代码有效防范漏洞的文章就介绍到这了,更多相关PHP防止任意文件上传漏洞内容请搜索悠久资源网以前的文章或继续浏览下面的相关文章希望大家以后多多支持悠久资源网!

您可能感兴趣的文章:

  • PHP 图片文件上传实现代码
  • 一个经典的PHP文件上传类分享
  • PHP文件上传实例详解!!!
  • php+ajax实现图片文件上传功能实例
  • jQuery Ajax文件上传(php)
  • php 文件上传实例代码
  • PHP实现视频文件上传完整实例
  • php 文件上传后缀名与文件类型对照表(几乎涵盖所有文件)
  • PHP实现文件上传功能实例代码
  • PHP文件上传判断file是否己选择上传文件的方法

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悠久资源 PHP PHP文件上传安全:优化代码有效防范漏洞 https://www.u-9.cn/biancheng/php/181789.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务