返回首页

Go 中的安全文件上传:7 种攻击

本文描述了 Go 文件上传针对 7 种攻击的防护:类型伪造魔术字节、通过 MaxBytesReader+槽位的 DoS、固定路径的路径遍历。使用无账户的 ECDSA 设备识别,适用于浏览器扩展。

Go 文件上传的 7 种攻击及其防护
Advertisement 728x90

Go语言文件上传安全防护:抵御7类常见攻击

在无传统认证机制的系统中,文件上传需具备强大的请求来源识别能力。对于一个将PDF转换为Markdown的浏览器扩展,我们采用基于WebCrypto API的ECDSA P-256加密模型。首次启动时,生成不可导出的密钥对:

const keyPair = await crypto.subtle.generateKey(
  { name: 'ECDSA', namedCurve: 'P-256' },
  false,  // extractable = false
  ['sign', 'verify']
);

公钥注册至服务器后,返回 device_iddevice_token。所有API请求均包含以下字段:

  • Authorization: Bearer <token>
  • X-Timestamp(±5分钟内有效)
  • X-Nonce(防重放攻击)
  • X-Body-SHA256(请求体哈希值)
  • X-Signature(使用ECDSA对 METHOD+PATH+TIMESTAMP+NONCE+BODY_HASH 签名)

服务器通过公钥验证签名,确保实现:

Google AdInline article slot
  • 按设备限流
  • 防止重放攻击
  • 任务槽位控制(最多3个活跃任务)
  • 注册频率限制(每IP每小时最多5次)

该模型显著提高攻击成本——模拟需完整实现ECDSA签名逻辑。

攻击1:文件类型伪装

攻击者将可执行文件伪装成PDF。防御策略分三层实施。

前端:校验MIME类型与扩展名:

Google AdInline article slot
const ALLOWED_TYPES = ['application/pdf'];
const ALLOWED_EXTENSIONS = ['.pdf'];

function validateFile(file) {
  const isPdf = ALLOWED_TYPES.includes(file.type) ||
                ALLOWED_EXTENSIONS.some(ext =>
                  file.name.toLowerCase().endsWith(ext));
  if (!isPdf) return { valid: false, error: '仅支持PDF' };
}

后端:依据 Content-Type 路由,并检查魔数(Magic Bytes):

pdfMagicBytes := "%PDF"
header4 := make([]byte, 4)
_, err := file.Read(header4)
if string(header4) != pdfMagicBytes {
    respondError(w, http.StatusBadRequest,
        models.ErrCodeValidationError,
        "文件不是有效的PDF")
}
file.Seek(0, 0)

通过读取文件开头字节,绕过头部和扩展名欺骗。对于多用途文件(合法PDF含恶意内容),需额外数字签名验证。

攻击2:磁盘耗尽(拒绝服务)

通过上传超大文件发起拒绝服务攻击。缓解措施包括:

Google AdInline article slot
  • http.MaxBytesReader(w, r.Body, MaxFileSize + 1MB) —— 读取超过限制即终止。
  • 设备级任务槽位控制:最多3个活跃任务(queued, processing, ready, error)。
  • 对注册与请求施加速率限制。

设备标识使IP或令牌轮换失效。

攻击3:路径遍历

攻击者尝试利用 ../../../etc/passwd解决方案:固定路径 {UUID}/input.pdf。用户输入完全忽略,不参与路径构建。

前端净化(增强层):

function sanitizeFileName(name) {
  return name
    .replace(/[/\\?%*:|"<>]/g, '-') 
    .replace(/^\.+/, '')
    .replace(/\.$/, '')
    .substring(0, 255)
    .trim();
}

后端独立生成路径,不受文件名影响。

攻击4:通过URL上传引发SSRF

针对“从URL上传”功能,以下行为被禁止:

  • 下载前进行DNS解析
  • 重定向跳转
  • 私有IP地址访问(黑名单:10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)

攻击5:重放攻击

依赖 X-Nonce + X-Timestamp + 数字签名。每个设备存储唯一nonce,时间戳有效期±5分钟。

攻击6:设备冒充

extractable: false 确保私钥无法导出。即使窃取 device_token,无有效签名仍无法伪造身份。

攻击7:应用层滥用

结合速率限制、槽位控制与加密签名。最大3个任务槽,每IP每小时最多5次注册。

核心要点

  • 使用加密设备标识替代账户体系进行限流。
  • 文件类型验证唯一可靠方式是检查魔数(%PDF)。
  • MaxBytesReader + 槽位管理可有效防止拒绝服务攻击。
  • 固定路径彻底消除路径遍历风险。
  • ECDSA P-256配合nonce与时间戳,可防范重放与冒充攻击。

— Editorial Team

Advertisement 728x90

继续阅读