← 返回文件上传漏洞

🎭 实验二:MIME 类型欺骗

⚠️ 漏洞场景

服务器只检查 Content-Type,但 MIME 类型由客户端设置,可被伪造

🎮 攻击演示

上传恶意文件(伪造 MIME)

点击上传查看结果...

📊 MIME 检查对比

❌ 不安全:只检查 MIME

if (!ALLOWED_MIMES.includes(req.body.mime)) {
  return res.status(400).json({ error: '类型不允许' })
}
// 问题:MIME 可被客户端伪造!

✅ 安全:检查文件魔数

// 读取文件头部字节
const magic = buffer.slice(0, 4).toString('hex')
const signatures = {
  'ffd8ff': 'image/jpeg',
  '89504e47': 'image/png'
}
// 根据实际内容判断类型

📖 文件魔数(Magic Number)

文件类型魔数(十六进制)ASCII
JPEGFF D8 FFÿØÿ
PNG89 50 4E 47‰PNG
GIF47 49 46 38GIF8
PDF25 50 44 46%PDF
ZIP50 4B 03 04PK..
EXE4D 5AMZ

🛡️ 正确的验证方式

const fileType = require('file-type')

async function validateFile(buffer, claimedMime) {
  // 1. 检测实际文件类型
  const detected = await fileType.fromBuffer(buffer)
  
  // 2. 对比声明的类型
  if (!detected || detected.mime !== claimedMime) {
    throw new Error('文件类型与声明不符')
  }
  
  // 3. 检查是否在白名单
  if (!ALLOWED_MIMES.includes(detected.mime)) {
    throw new Error('不允许的文件类型')
  }
  
  return true
}