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_id 和 device_token。所有API请求均包含以下字段:
Authorization: Bearer <token>X-Timestamp(±5分钟内有效)X-Nonce(防重放攻击)X-Body-SHA256(请求体哈希值)X-Signature(使用ECDSA对 METHOD+PATH+TIMESTAMP+NONCE+BODY_HASH 签名)
服务器通过公钥验证签名,确保实现:
- 按设备限流
- 防止重放攻击
- 任务槽位控制(最多3个活跃任务)
- 注册频率限制(每IP每小时最多5次)
该模型显著提高攻击成本——模拟需完整实现ECDSA签名逻辑。
攻击1:文件类型伪装
攻击者将可执行文件伪装成PDF。防御策略分三层实施。
前端:校验MIME类型与扩展名:
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:磁盘耗尽(拒绝服务)
通过上传超大文件发起拒绝服务攻击。缓解措施包括:
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
暂无评论。