通过拆分攻击实现的SSRF攻击
字数 1000 2025-08-27 12:33:37
通过拆分攻击实现的SSRF攻击技术分析
前言
本文详细分析了一种通过HTTP请求拆分实现的服务器端请求伪造(SSRF)攻击技术,该漏洞源于Node.js对Unicode字符的错误处理,导致攻击者可以构造特殊请求绕过安全限制。
漏洞背景
Node.js的Unicode字符处理缺陷
在Node.js 8及更早版本中,当处理HTTP请求路径中的Unicode字符时存在以下问题:
- 对于不包含主体的请求(如GET/DELETE),Node.js默认使用"latin1"编码
- "latin1"是单字节编码,无法表示高编号的Unicode字符
- 这些字符会被截断为JavaScript表示的最低字节
// 示例:Unicode字符被截断
> Buffer.from('čĊ', "latin1").toString()
'\r\n' // 被转换为CRLF控制字符
HTTP请求拆分原理
HTTP作为基于文本的协议,容易受到注入攻击。当服务器:
- 接受用户输入
- 将其包含在内部HTTP请求的路径中
- 且请求具有0长度主体(如GET/DELETE)
攻击者可以注入协议控制字符到请求中,实现请求拆分。
漏洞利用细节
攻击构造方法
- 精心选择Unicode字符,使其在latin1编码后变为HTTP控制字符
- 将这些字符插入到用户可控的输入字段(如电子邮件地址)
- 触发服务器发出包含这些字符的HTTP请求
// 攻击示例
v = 'x@̠̠ňƆƆƆƆɐɐį1̮̮1č̊̊č̊̊ɆɆͅͅƆƆ̠̠įaccountįf9f9eebb05ef4b819b0467cc5ddd3b4aįsessions̠̠ňƆƆƆƆɐɐį1̮̮1č̊̊č̊̊.cc'
Buffer.from(v.toLowerCase(), "latin1").toString()
// 输出包含多个HTTP请求
实际攻击场景
在Firefox Accounts系统中,攻击者可以:
- 创建包含特殊Unicode字符的电子邮件地址
- 触发删除该邮箱地址的操作
- 导致API服务器向数据存储区发出恶意请求
DELETE /account/f9f9.../email/x@̠̠ňɔɔɐɐį1̮̮1č̊̊č̊̊ɇɇͅͅɔ̠̠įaccountįf9f9...įsessions̠̠ňɔɔɐɐį1̮̮1č̊̊č̊̊.cc
实际被写入的请求:
DELETE /account/f9f9.../email/x@ HTTP/1.1
GET /account/f9f9.../sessions HTTP/1.1
.cc
修复方案
短期修复
- 对所有电子邮件地址进行十六进制编码处理
- 确保用户输入不直接进入请求路径
长期缓解
- 升级到Node.js 10+,其对非ASCII字符会抛出错误
- 使用safe-url-assembler等工具确保URL正确编码
- 考虑使用gRPC等结构化协议替代HTTP进行内部通信
防御建议
- 输入验证:严格验证所有用户输入,特别是可能进入URL的部分
- 编码处理:对所有动态生成的URL组件进行适当编码
- 协议升级:尽可能使用HTTP/2或gRPC等更安全的协议
- 权限隔离:内部服务通信使用最小权限原则
- 监控审计:记录所有内部服务请求,便于异常检测
总结
这种通过Unicode字符拆分HTTP请求实现的SSRF攻击展示了文本协议的安全隐患。防御此类攻击需要多层防护:从输入验证到协议设计,再到权限控制。开发人员应特别注意用户输入与协议控制字符的交互,避免类似安全漏洞。