复现HTTP Header注入漏洞需在Express路由中直接使用req.query等未过滤用户输入调用res.setHeader(),如GET /api?sort=rating%0d%0aX-Injected:1触发响应头截断;Node.js不自动校验CRLF,须在解码后检查\r\n\0并采用白名单过滤。

如何复现 HTTP Header 注入漏洞(Express 场景)
直接在 Express 路由里用 req.query 或 req.body 值调用 res.setHeader(),就是最典型的触发路径。比如:
- 攻击者发请求:
GET /api?sort=rating%0d%0aX-Injected:1 - 服务端代码写成:
res.setHeader('X-Sort-By', req.query.sort) - Node.js 的
http.ServerResponse在底层会原样拼接字符串,%0d%0a解码后变成\r\n,导致响应头被截断并插入恶意头
注意:Node.js 本身不会自动过滤 CRLF 字符,也不校验 header name/value 合法性——这是开发者责任,不是框架义务。
为什么 express-validator 的 isAscii() 不够用
单纯校验 ASCII 字符,无法拦截 %0d%0a 这类 URL 编码的 CRLF。真正有效的验证必须在解码后进行:
- 先调用
decodeURIComponent()(或让 Express 自动做,取决于express.urlencoded()配置) - 再检查字符串是否含
\r、\n、\0等控制字符 - 更稳妥的做法是白名单:只允许字母、数字、下划线、短横线等安全字符,例如用正则
/^[a-zA-Z0-9_-]+$/
别依赖前端 JS 过滤——绕过太容易;也别只对 query 做,body、headers、cookie 一样要查。
helmet 中间件能防 Header 注入吗
不能。helmet 只负责设置安全响应头(如 X-Content-Type-Options),它不干预你调用 res.setHeader() 的参数来源。它的作用域在「输出层」,而 Header 注入发生在「输入→输出」的映射环节。
使用一条命令部署ProbeChain Rydberg测试网代理节点。自动注册为Agent(NodeType=1),免gas,支持macOS/Linux/Windows。触发词:/r
正确姿势是分层防御:
- 输入层:用
express-validator+ 自定义 sanitizer 清洗 CRLF - 输出层:避免直接透传用户输入到
res.setHeader()、res.cookie()、res.redirect() - 运行时:启用 Node.js 的
--disable-proto=throw和--no-deprecation减少原型污染风险
VS Code 调试时怎么快速验证修复效果
在 VS Code 的 launch.json 里配好 Node 调试后,直接用 curl 模拟攻击请求,观察响应头是否干净:
curl -v "http://localhost:3000/api?sort=rating%0d%0aX-Test:boom"
关键看响应中是否出现 X-Test: 这类非法头。如果没出现,再检查调试器里 req.query.sort 的值是否已被清洗为 "rating" —— 这才是修复落地的证据。
别只看页面渲染结果;Header 注入是静默型漏洞,不报错、不崩溃,但可能被用于会话劫持或缓存污染。

















