症状
错误“开放重定向 — 未校验的跳转目标”指向一个明确的失效模式。下面依次给出症状、定位该原因的检查命令、根本原因、修复方案,以及证明修复有效的验证步骤。
可观察到的症状包括:
- 访问 /login?next=https://evil.example.com 跳转到站外
- 安全扫描报告开放重定向问题
- 同一参数被用作登录后的返回地址
诊断
先在隔离环境中复现故障,再按顺序执行以下检查,逐步缩小范围。
步骤 1
curl -i "https://app.example.com/login?next=https://evil.example.com" | grep -i location
Location 头指向站外,即证明跳转未经校验。
步骤 2
grep -rn "redirect(\|res.redirect\|Location" src/
每一处由请求值控制跳转目标的地方都是待防护候选。
常见诱因(按出现频率排序):
- 跳转目标来自请求参数且未校验
- 校验只判断字符串前缀为主机名,而非实际源
- 协议相对或编码后的 URL 绕过了粗糙白名单
根因
当跳转目标取自用户输入并直接使用时,攻击者可构造看似属于你域名、实则跳往他处的链接,从而实施钓鱼与令牌窃取。
修复
仅允许同源相对路径(拒绝任何含 scheme 或 host 的值),或在跳转前按已知目标的白名单严格校验。
注意:形如 startsWith(“https://[email protected]”) 的前缀检查不安全;应解析 URL 并精确比较源。
function safeRedirectTarget(next, fallback = '/') {
if (!next) return fallback;
try {
const url = new URL(next, 'https://app.example.com');
// allow only same-origin relative paths
if (url.origin !== 'https://app.example.com') return fallback;
return url.pathname + url.search + url.hash;
} catch {
return fallback;
}
}
验证
重发外部目标并确认被拒绝或替换为安全默认;验证合法相对路径仍可跳转。
修复后补充一条回归测试,复现原始症状,防止问题再次出现。
这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。