ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Node.js 安全实践:阻止不安全的重定向(Unsafe Redirect)漏洞

Node.js 安全实践:阻止不安全的重定向(Unsafe Redirect)漏洞 文档教程后端【免费下载链接】nodebestpractices✅ The Node.js best practices list (July 2026)项目地址https://gitcode.com/GitHub_Trending/no/nodebestpractices点击查看免费下载在 Node.js 与 Express 应用中重定向redirect是登录、支付、OAuth 回调等场景最常见的能力之一但若直接把用户提供的 URL 交给res.redirect()就会引入被称为“开放重定向Open Redirect”的安全漏洞。本文以 Node.js Best Practices 仓库安全章节的 saferedirects.basque.md英文原版见 saferedirects.md为骨架完整讲解该漏洞的形成原理、攻击场景以及基于白名单的安全重定向落地写法读完后你能直接在自己的 Express 路由中实现防御性重定向逻辑并把它接入整个 Node.js 安全加固体系。一、漏洞定位这是 Node.js Best Practices 的第 6.24 条安全实践在本仓库的 README.md 中“Prevent unsafe redirects”被列为6.24 Prevent unsafe redirects归属于“6. Security Practices (25)”安全实践大类参见 README 目录中的 6.24 小节并带有OWASP Threats – A1: Injection的威胁标签。README 对该实践的 TL;DR 描述是未对用户输入做校验的重定向会让攻击者得以发起网络钓鱼phishing骗局、窃取用户凭据并执行其他恶意操作。也就是说这条实践属于输入注入类威胁的防御范畴与同章节的“Validate the incoming JSON schemas”validation.md、“Escape HTML, JS and CSS output”等实践共同构成了“不信任外部输入”的防御主线。二、攻击模型恶意链接如何在公共渠道扩散原文档开篇就点明了漏洞利用的完整链条当我们在 Node.js 或 Express 中实现重定向时在服务器端进行输入校验非常重要。当攻击者发现你没有校验用户提供的外部输入时他们会在论坛、社交媒体以及其他公共场合发布精心制作的链接来诱使用户点击以此达到漏洞利用的目的。攻击者的操作可以拆解为三步探测向你的登录/跳转接口传入一个外部 URL 参数观察服务端是否原样返回 302 跳转构造把恶意目标地址拼进合法站点的重定向参数例如https://your-app.com/login?urlhttps://evil.example.com投放将加工后的链接发布在论坛、社交网络等公共场所诱导用户点击。用户看到的链接前缀是你的可信域名但点击后浏览器却被服务端 302 导向了攻击者控制的站点。这个看似“只是多跳了一次”的行为实际可能造成三类后果网络钓鱼用户被导向一个外观与你的站点几乎一致的仿冒页面例如examp1e.com这种极易混淆的域名随后被诱导输入账号密码凭据窃取仿冒登录页收集到的账号密码直接落入攻击者手中信任滥用攻击者借助你域名的可信度在社交渠道扩散链接绕过用户的警惕心理。三、反模式代码把用户输入直接喂给res.redirect原文档给出的不安全示例完整摘录如下const express require(express); const app express(); app.get(/login, (req, res, next) { if (req.session.isAuthenticated()) { res.redirect(req.query.url); } });这段代码的核心问题在于res.redirect(req.query.url)req.query.url是完全由客户端控制的外部输入任何请求都能随意指定Express 的res.redirect()支持相对路径、完整 URL含http://、https://以及协议相对 URL以//开头如//evil.example.com浏览器会沿用当前页面的协议去解析主机一旦传入类似https://evil.example.com或//evil.example.com的值服务端就变成了“攻击者的跳板”把用户导向任意第三方站点。从代码结构看这里甚至不需要攻击者攻破任何鉴权只要用户本身处于已认证状态req.session.isAuthenticated()为真点击恶意链接就会触发跳转漏洞随每一次合法登录流程被放大。四、修复原则不要以未校验的用户输入作为重定向依据原文档给出的修复方向非常明确建议的避免不安全重定向的方案是避免依赖用户输入的内容来进行重定向。如果一定要使用用户输入的内容可以通过使用白名单重定向的方式来避免暴露漏洞。由此可以总结出两条优先级的策略首选重定向目标由服务端自行推导完全不读取用户输入。例如登录成功后的跳转地址固定指向站内首页、或由服务端会话中保存的“来源页”决定并对该来源页同样做站内校验次选当业务上确实需要接受用户提供的跳转目标如支持“记住我上次访问的页面”时必须把该输入通过白名单/校验函数过滤后才允许使用任何不在白名单内的值一律回退到安全的默认地址。五、白名单方案getValidRedirect的完整实现与逐行剖析原文档给出的安全实现完整摘录如下const whitelist { https://google.com: 1 }; function getValidRedirect(url) { // 检查 url 是否以单个斜杠开头 if (url.match(/^\/(?!\/)/)) { // 前置我们的域名来确保安全 return https://example.com url; } // 否则对照白名单列表 return whitelist[url] ? url : /; } app.get(/login, (req, res, next) { if (req.session.isAuthenticated()) { res.redirect(getValidRedirect(req.query.url)); } });5.1 正则^\/(?!\/)拦截协议相对 URL这是整段防御逻辑的关键一行。逐段拆解片段含义^匹配字符串开头确保从 URL 的第一个字符就开始约束\/匹配一个普通斜杠/(?!\/)否定先行断言negative lookahead断言紧随其后的不是另一个斜杠两者合在一起的含义是“URL 以单个斜杠开头”。这样一来/dashboard→ 匹配成功视为站内相对路径//evil.example.com→ 以双斜杠开头匹配失败不会命中相对路径分支https://evil.example.com→ 以字母开头同样匹配失败。双斜杠被单独拦截是必要的因为//evil.example.com是协议相对 URL浏览器会把它解析到evil.example.com这个外部主机——它是开放重定向最经典的绕过向量之一白名单方案必须显式封堵。5.2 前置域名把相对路径钉死在站内对于通过校验的相对路径代码执行return https://example.com url;即在用户传入的相对路径前强制拼接自己的域名。这确保了任何站内路径最终都落在https://example.com之下即使原始输入里包含路径穿越之类的痕迹最终跳转目标的主机也始终可控。5.3 白名单查表与默认回退对于不以单斜杠开头的输入如完整的https://google.com代码不再自行放行而是查表return whitelist[url] ? url : /;命中白名单例如https://google.com被显式收录→ 原样返回该 URL未命中包括攻击者构造的任何外部地址→ 一律回退到/即跳回站内首页。这个“不匹配就回退到安全默认值”的写法是整个方案的兜底逻辑默认行为是安全的只有显式白名单条目才能改变跳转目标从根上杜绝了“未知输入被直接透传”的可能。5.4 接入路由改动面极小方案落地只需要把路由里的res.redirect(req.query.url)换成res.redirect(getValidRedirect(req.query.url))鉴权逻辑、路由结构、响应行为均保持不变。当后续需要新增允许跳转的外部站点时只需扩充whitelist对象即可无需改动路由代码。六、纵深防御让输入校验尽早发生白名单方案解决的是“重定向参数校验”而仓库的安全章节强调所有外部输入都应当尽早、显式地校验。参见 validation.md 中的核心观点Validation is about being very explicit on what payload our app is willing to accept and failing fast should the input deviate from the expectations.即明确声明应用愿意接受什么样的载荷一旦输入偏离预期就快速失败fail fast。这条原则与重定向白名单是同一思想的两种落地对重定向参数用getValidRedirect做语义级白名单校验对请求体/其他查询参数可以用 JSON-Schema、joi 等校验库或在 Express 中通过中间件在请求进入路由处理器之前完成校验validation.md 给出了router.post(/, validator(Product.validate), ...)的中间件用法。把两类校验组合使用重定向参数就不会成为整个校验体系的漏网之鱼。此外仓库的 commonsecuritybestpractices.md 还从更宏观的层面给出了配套建议——例如比较敏感值使用crypto.timingSafeEqual、用crypto.randomBytes生成安全随机串、cookie 配置secure/HttpOnly等。开放重定向通常只是攻击链的第一环配合这些实践才能构成完整防线。七、社区观点两条值得记住的结论原文档在“其他博主的看法”一节引用了两位资深博主对开放重定向的总结这里转述其核心观点原文链接见 saferedirects.md 末尾幸运的是缓解此漏洞的方法非常简单——不要使用未经验证的用户输入作为重定向的基础。但是如果服务器端的重定向逻辑没有对 url 参数的数据进行校验的话你的用户可能最终访问的地址跟你的地址看起来几乎完全一致examp1e.com而这最终满足了犯罪黑客们的需求。这两句话恰好分别对应了本实践的两条主线修复方式足够简单值得立刻落地不修复的后果足够隐蔽且严重不值得赌运气。八、小结三个可以立即执行的检查项搜代码全局检索res.redirect(和redirect(调用逐一确认参数是否可能包含用户输入req.query.*、req.body.*、req.params.*替换把直接透传用户输入的写法改为白名单 默认回退的getValidRedirect模式回归为getValidRedirect补充测试用例至少覆盖站内相对路径、双斜杠协议相对 URL、白名单外完整 URL 三种输入验证它们分别得到预期结果原文档的完整代码与注释见 sections/security/saferedirects.basque.md 及英文原版 sections/security/saferedirects.md。重定向是用户体验的一部分但绝不能以牺牲安全为代价。把“默认拒绝、显式放行”作为重定向逻辑的第一原则开放重定向漏洞就能被稳定地封堵在路由层之外。赞分享文档教程后端【免费下载链接】nodebestpractices✅ The Node.js best practices list (July 2026)项目地址https://gitcode.com/GitHub_Trending/no/nodebestpractices点击查看免费下载相关推荐listmonk 如何把活动邮件发布为公开订阅表单页面并嵌入网站listmonk 如何把活动邮件发布为公开订阅表单页面并嵌入网站 如果你用 listmonk 发送过 newsletter 活动邮件想把这些邮件变成不需要登录文档教程后端PhotoGIMP 完整指南如何把 GIMP 改成 Photoshop 布局5分钟装好PhotoGIMP 完整指南如何把 GIMP 改成 Photoshop 布局5分钟装好 PhotoGIMP 是一个免费的 GIMP 补丁它替你重写 GI文档教程后端SafeLine重定向安全开放重定向漏洞防护SafeLine重定向安全开放重定向漏洞防护 开放重定向漏洞Web安全的潜在威胁 开放重定向Open Redirect漏洞是Web应用中常见的安全威胁WAF网络安全应用安全上一篇安卓位置保护终极指南虚拟定位技术完全掌握下一篇安卓定位修改与位置保护工具FakeLocation全方位使用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表