flawopen.com/Teardowns/cve-2022-31150-undici-crlf-injection
●
CVE-2022-31150 · CVSS 5.3 · 中危
安全研究 · FlawOpen
CVE-2022-31150:Undici CRLF 注入
CVE-2022-31150 使不可信 CR/LF 进入 Undici 请求序列化。本文说明上游修复、影响范围和安全升级方法。
💡 通俗易懂的原理解析 (ELI5)
HTTP 请求像一张有固定换行的表单:每一行对应一个字段。如果未经检查就复制文本,隐藏的换行可能让后续内容看起来像新字段。Undici 的修复会在写入前检查请求头值、方法和路径。
核心概念与专有名词
Undici- Node.js 的 HTTP/1.1 客户端库;Node.js 的内置 fetch 也包含 Undici 实现。
CRLF 注入- 不可信的回车和换行字节进入协议字段,可能改变行边界。
HTTP token- 协议元素使用的受限字符集,例如请求头名称和方法。
请求目标- HTTP 请求发送的路径和查询;控制字符不得改变其结构。
框架映射
- 本指南所述弱点的 CWE 参考: CWE-93
根本原因剖析 (Root Cause)
修复前,Undici 可能将含有无效控制字符的不可信请求头值序列化到 HTTP 请求中。CR/LF 是行分隔符;接受它们可能注入或破坏请求头行。上游补丁将请求头名称按 HTTP token 校验,拒绝值中的无效字符,校验方法 token,并禁止路径中的控制字符。GitHub 公告列出的受影响包版本为低于 5.8.0;NVD 描述为低于 5.7.1。两者均将 5.8.0 标为修复版本。这是客户端请求注入;SSRF 或凭据泄露并非必然结果,取决于应用和网络路径。
攻击执行流程分解
步骤 1
1. 不可信值
应用数据进入 Undici 的请求头、方法或路径参数。
步骤 2
2. 缺少校验
受影响版本可能让无效控制字符进入请求构造过程。
步骤 3
3. 协议边界
HTTP 序列化依赖行边界;接受控制字符可能注入或破坏字段。
步骤 4
4. 修复与限制
Undici 5.8.0 在序列化前校验请求头字节、方法 token 和路径字符;实际影响取决于上下文。
源代码对比:漏洞与安全实现
存在漏洞的实现
// a29a151 之前 lib/core/request.js 中相关的序列化位置
function serializeRequest(request, method, path, headers) {
request.method = method;
request.path = path;
for (const [key, value] of Object.entries(headers)) {
// 序列化前未验证协议字符。
request.headers += `${key}: ${value}\r\n`;
}
}
加固后的安全修复
// 上游请求解析器采用的强化验证模式
const token = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
const invalidFieldValue = /[^\t\x20-\x7e\x80-\xff]/;
const invalidPath = /[^\u0021-\u00ff]/;
function validateRequestTarget(method, path) {
if (!token.test(method)) throw new InvalidArgumentError('invalid request method');
if (invalidPath.test(path)) throw new InvalidArgumentError('invalid request path');
}
function processHeader(request, key, value) {
if (!token.test(key)) throw new InvalidArgumentError('invalid header key');
if (invalidFieldValue.test(value)) throw new InvalidArgumentError(`invalid ${key} header`);
request.headers += `${key}: ${value}\r\n`;
}
工程与系统安全加固清单
- ✓将 npm undici 依赖升级至 5.8.0 或更高版本;使用内置 fetch 时,核实受支持 Node.js 版本捆绑的 Undici 版本并更新 Node.js。
- ✓拒绝不可信请求头值中的无效控制字符;不要静默删除字符后继续处理含义不明的输入。
- ✓使用 Undici 结构化请求 API,避免自行拼接原始 HTTP 文本。
- ✓为含控制字符的请求头名称和值、方法及路径添加回归测试,并确认它们在发送前被拒绝。
- ✓如果应用接受用户指定的目标地址,还应单独实施目标允许列表和网络出站策略;这属于纵深防御,并非该 CVE 的修复。
- ✓检查锁文件及传递依赖,确保没有遗留易受影响的 Undici 副本。