通过拆分攻击实现的SSRF攻击
字数 1000 2025-08-27 12:33:37

通过拆分攻击实现的SSRF攻击技术分析

前言

本文详细分析了一种通过HTTP请求拆分实现的服务器端请求伪造(SSRF)攻击技术,该漏洞源于Node.js对Unicode字符的错误处理,导致攻击者可以构造特殊请求绕过安全限制。

漏洞背景

Node.js的Unicode字符处理缺陷

在Node.js 8及更早版本中,当处理HTTP请求路径中的Unicode字符时存在以下问题:

  1. 对于不包含主体的请求(如GET/DELETE),Node.js默认使用"latin1"编码
  2. "latin1"是单字节编码,无法表示高编号的Unicode字符
  3. 这些字符会被截断为JavaScript表示的最低字节
// 示例:Unicode字符被截断
> Buffer.from('čĊ', "latin1").toString()
'\r\n'  // 被转换为CRLF控制字符

HTTP请求拆分原理

HTTP作为基于文本的协议,容易受到注入攻击。当服务器:

  1. 接受用户输入
  2. 将其包含在内部HTTP请求的路径中
  3. 且请求具有0长度主体(如GET/DELETE)

攻击者可以注入协议控制字符到请求中,实现请求拆分。

漏洞利用细节

攻击构造方法

  1. 精心选择Unicode字符,使其在latin1编码后变为HTTP控制字符
  2. 将这些字符插入到用户可控的输入字段(如电子邮件地址)
  3. 触发服务器发出包含这些字符的HTTP请求
// 攻击示例
v = 'x@̠̠ňƆƆƆƆɐɐį1̮̮1č̊̊č̊̊ɆɆͅͅƆƆ̠̠įaccountįf9f9eebb05ef4b819b0467cc5ddd3b4aįsessions̠̠ňƆƆƆƆɐɐį1̮̮1č̊̊č̊̊.cc'
Buffer.from(v.toLowerCase(), "latin1").toString()
// 输出包含多个HTTP请求

实际攻击场景

在Firefox Accounts系统中,攻击者可以:

  1. 创建包含特殊Unicode字符的电子邮件地址
  2. 触发删除该邮箱地址的操作
  3. 导致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

修复方案

短期修复

  1. 对所有电子邮件地址进行十六进制编码处理
  2. 确保用户输入不直接进入请求路径

长期缓解

  1. 升级到Node.js 10+,其对非ASCII字符会抛出错误
  2. 使用safe-url-assembler等工具确保URL正确编码
  3. 考虑使用gRPC等结构化协议替代HTTP进行内部通信

防御建议

  1. 输入验证:严格验证所有用户输入,特别是可能进入URL的部分
  2. 编码处理:对所有动态生成的URL组件进行适当编码
  3. 协议升级:尽可能使用HTTP/2或gRPC等更安全的协议
  4. 权限隔离:内部服务通信使用最小权限原则
  5. 监控审计:记录所有内部服务请求,便于异常检测

总结

这种通过Unicode字符拆分HTTP请求实现的SSRF攻击展示了文本协议的安全隐患。防御此类攻击需要多层防护:从输入验证到协议设计,再到权限控制。开发人员应特别注意用户输入与协议控制字符的交互,避免类似安全漏洞。

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