如何将Host头注入攻击场景下的响应改为404 Not Found?
Host头注入场景下301响应改404问题排查与解决
当前服务器响应
<HTML> <head><title>301 Moved Permanently</title></head> <body> <center><h1>301 Moved Permanently</h1></center> <hr><center>nginx</center> </body> </html>
需求:需将上述响应改为404 Not Found。
服务器Host验证逻辑代码
app.use((req, res, next) => { const host: any = req.headers.host; const url = new URL(config.app.baseUrl); const domain = url.hostname; console.log(domain,"domain"); const allowedHosts = [domain + ":" + config.app.port]; const allowedHosts = ['localhost:4000', 'testserver.com']; if (!allowedHosts.includes(host)) { res.status(HttpStatus.STATUS_BAD_REQUEST).send({ ResponseMessage: "Invalid Host header", IsError: true }); } else { next(); } }); app.all("*", (req, res) => { if (!req.path.startsWith("/api")) { return res .status(HttpStatus.STATUS_FORBIDDEN) .send({ ResponseMessage: "Access denied", IsError: true }); } });
请求头信息
GET /assets HTTP/1.1 Host: testserver.com Cookie: i18next=en Sec-Ch-Ua: "Chromium";v="109", "Not_A Brand";v="99" Accept: application/json, text/plain, */* From: U2FsdGVkX1s1L2a3QELNbGz66lPBKVCYAI4iTEUYKW9a1y5Y= Sec-Ch-Ua-Mobile: ?0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.5414.75 Safari/537.36 Sec-Ch-Ua-Platform: "Linux" Sec-Fetch-Site: same-origin Sec-Fetch-Mode: cors Sec-Fetch-Dest: empty Referer: https://testserver.com Accept-Encoding: gzip, deflate Accept-Language: en-GB,en-US;q=0.9,en;q=0.8 Connection: close
问题分析
- 301响应来源:当前返回的301是nginx层面的重定向,请求还没到达Node.js应用的验证逻辑就被nginx拦截处理了。
- 代码逻辑问题:代码中重复声明
allowedHosts,后一个数组会覆盖前一个;另外,即使请求到达Node.js,/assets路径会触发403而非404,但实际请求根本没到应用层。
解决方案
1. 调整nginx配置
检查nginx配置,移除针对/assets或非预期Host的重定向规则,确保不符合要求的请求要么直接返回404,要么正确转发到Node.js服务。比如可以在nginx配置中添加规则,对非法Host直接返回404:
server { listen 80; server_name _; return 404; }
2. 修复Node.js代码逻辑
- 移除重复的
allowedHosts声明,合并允许规则 - 将Host验证失败的响应码从400改为404
- 调整非API路径的响应码为404
修改后的代码示例:
app.use((req, res, next) => { const host = req.headers.host; const url = new URL(config.app.baseUrl); const domain = url.hostname; console.log(domain,"domain"); // 合并合法Host列表 const allowedHosts = [domain + ":" + config.app.port, 'localhost:4000', 'testserver.com']; if (!allowedHosts.includes(host)) { return res.status(HttpStatus.NOT_FOUND).send({ ResponseMessage: "Resource not found", IsError: true }); } next(); }); app.all("*", (req, res) => { if (!req.path.startsWith("/api")) { return res.status(HttpStatus.NOT_FOUND).send({ ResponseMessage: "Resource not found", IsError: true }); } });
3. 验证请求链路
查看nginx和Node.js的日志,确认请求是否正常到达应用层,确保转发配置无误。
内容的提问来源于stack exchange,提问作者Rakesh L
相关产品推荐
相关产品推荐

