京东6.18大促主会场领京享红包更优惠

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

2024-11-3 18:03| 发布者: 2ae29| 查看: 54| 评论: 0

摘要: 目录原生毛病PHP示例代码:原生毛病PHP毛病优化意见(获取暂时文件的真实范例):对Laravel框架,也有同样的题目,别用错函数:对Laravel恣意文件上传毛病优化意见(获取暂时文件的真实范例):整体修复意见:扩展:
目录

说明:恣意文件上传毛病,许多PHP开发者也会做一些简单的防护,但是这个防护有被绕过的大概。

原生毛病PHP示例代码:

[code]$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); [/code]

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

原生毛病PHP毛病优化意见(获取暂时文件的真实范例):

[code]$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); [/code]

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

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

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

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

对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范例。

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

两者底层对获取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获取魔术数字实现方案:

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

到此这篇关于PHP文件上传安全:优化代码有效防范毛病的文章就介绍到这了,更多相干PHP防止恣意文件上传毛病内容请搜刮脚本之家以前的文章或继承浏览下面的相干文章希望大家以后多多支持脚本之家!


来源:https://www.jb51.net/program/310009xfa.htm
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
关闭

站长推荐上一条 /6 下一条

QQ|手机版|小黑屋|梦想之都-俊月星空 ( 粤ICP备18056059号 )|网站地图

GMT+8, 2025-7-1 22:12 , Processed in 0.042366 second(s), 18 queries .

Powered by Mxzdjyxk! X3.5

© 2001-2025 Discuz! Team.

返回顶部