文件魔数是文件头的十六进制标识,用于准确识别文件类型,如JPG为FFD8FF、PNG为89504E47;PHP可通过fread读取文件前16字节并转换为十六进制,再与标准魔数比对,结合finfo获取MIME类型、限制目录执行权限及重命名文件等措施,可有效防止恶意文件上传。

上传文件时仅靠扩展名判断类型很容易被绕过,攻击者可以将恶意脚本伪装成图片或其他安全格式。为提高安全性,PHP应通过读取文件的“魔数”(即文件头信息)来识别文件的真实类型。
什么是文件魔数?
文件魔数是文件开头的一段十六进制数据,用于标识文件的真实格式。例如:
JPG 文件开头通常是 FF D8 FF PNG 文件开头是 89 50 4E 47 GIF 文件以 47 49 46 38(GIF8)开始 PRPS 文件(PDF)为 25 50 44 46(%PDF)这些数据无法通过简单修改后缀名改变,因此更可靠。
使用 PHP 读取文件头并校验类型
可以通过 fread() 读取文件前几个字节,并与已知魔数比对:
立即学习“PHP免费学习笔记(深入)”;
小艺 华为公司推出的AI智能助手
549 查看详情
function checkFileMimeType($filePath) { $handle = fopen($filePath, 'rb'); if (!$handle) { return false; } // 读取前16个字节 $bin = fread($handle, 16); fclose($handle); $hexValues = unpack('H*', $bin); $hex = strtoupper($hexValues[1]); // 提取前几位进行匹配 $header = substr($hex, 0, 8); if (strpos($header, 'FFD8FF') === 0) { return 'image/jpeg'; } elseif (strpos($header, '89504E47') === 0) { return 'image/png'; } elseif (strpos($header, '47494638') === 0) { return 'image/gif'; } elseif (strpos($header, '25504446') === 0) { return 'application/pdf'; } // 可继续添加其他类型... return 'unknown';}// 使用示例$uploadedFile = $_FILES['file']['tmp_name'];$mimeType = checkFileMimeType($uploadedFile);if ($mimeType === 'image/jpeg' || $mimeType === 'image/png') { // 允许上传} else { die('文件类型不合法!');}登录后复制结合 MIME 类型多重验证更安全
建议组合以下方式提升安全性:
校验文件头魔数:防止伪造扩展名 使用 finfo 扩展获取 MIME 类型:<font face="Courier New">$finfo = finfo_open(FILEINFO_MIME_TYPE);$mimeType = finfo_file($finfo, $filePath);finfo_close($finfo); </font>登录后复制 限制上传目录权限:禁止执行脚本(如 .php) 重命名上传文件:避免利用已知文件名攻击
常见问题与注意事项
某些图像编辑软件可能在文件头部添加额外数据(如元信息),影响读取。建议多读取一些字节并跳过常见干扰位,或结合多种方法交叉验证。
不要完全依赖 $_FILES['type'],该值由客户端提供,极易伪造。
基本上就这些,魔数检测虽不能百分百防御所有伪装,但能有效拦截大多数基础攻击手段。配合其他措施,可大幅提升文件上传的安全性。
以上就是php如何上传文件校验文件头信息_php读取文件魔数判断真实类型防伪装的详细内容,更多请关注php中文网其它相关文章!



