Skip to content

开放重定向(Open Redirect)

登录成功后跳转 ?redirect=、注销跳转、next= 等参数若未校验,攻击者可构造链接:登录可信域名 → 立刻跳到钓鱼站,用户难以察觉。


攻击 URL 示意

text
https://trust.example/login?redirect=https://evil.example/phishing

若登录成功后执行:

js
const params = new URLSearchParams(location.search);
const redirect = params.get('redirect');
window.location.href = redirect; // 危险:任意域名

用户完成登录后浏览器将被带到恶意站点(可能伪造同款登录框二次盗号)。


不安全代码

js
function afterLogin() {
  const u = new URLSearchParams(location.search).get('redirect');
  window.location.assign(u || '/');
}

安全写法:白名单前缀或路径

js
const ALLOWED_HOSTS = new Set(['app.example.com', 'trust.example.com']);

function safeRedirect(raw) {
  if (!raw) return '/home';
  try {
    const url = new URL(raw, location.origin);
    if (!ALLOWED_HOSTS.has(url.hostname)) return '/home';
    return url.pathname + url.search + url.hash;
  } catch {
    return '/home';
  }
}

function afterLogin() {
  const params = new URLSearchParams(location.search);
  window.location.assign(safeRedirect(params.get('redirect')));
}

仅允许站内相对路径时更简单:

js
function safeRedirectPath(raw) {
  if (!raw || !raw.startsWith('/') || raw.startsWith('//')) return '/home';
  return raw;
}

服务端侧建议

由服务端签发 一次性、签名过的跳转令牌,或使用固定枚举:redirectId=1 映射到已知路径,避免把完整 URL 交给用户可控参数。


小结

原则:永远不要信任用户提供的完整跳转 URL;使用 白名单域名 / 仅相对路径 / 服务端签发令牌