跳到主要内容

未验证的重定向

威胁描述

未验证的重定向是一种攻击方式,攻击者通过操纵URL参数或表单数据,将用户重定向到恶意网站。这种攻击通常用于钓鱼攻击,诱导用户输入敏感信息(如用户名、密码、信用卡号等)。未验证的重定向可能导致用户信任的网站被用来传播恶意链接,从而导致身份盗窃、财务损失和声誉损害。

工作原理

  1. 应用程序存在一个重定向功能,使用用户输入来确定重定向的目标URL
  2. 攻击者构造包含恶意URL的参数或表单数据
  3. 应用程序未对重定向目标进行适当验证或白名单检查
  4. 用户被重定向到恶意网站,可能遭受进一步攻击

示例代码

1. 简单的未验证重定向

// 前端代码
const redirectUrl = new URLSearchParams(window.location.search).get('redirect');
if (redirectUrl) {
window.location.href = redirectUrl;
}

// 攻击者构造的URL
https://trusted-website.com/login?redirect=https://malicious-website.com/phishing

// 用户登录后被重定向到恶意网站

2. 表单中的未验证重定向

<!-- 前端表单 -->
<form action="/login" method="POST">
<input type="text" name="username" placeholder="用户名">
<input type="password" name="password" placeholder="密码">
<input type="hidden" name="redirect" value="https://malicious-website.com/phishing">
<button type="submit">登录</button>
</form>

<!-- 不安全的后端代码(Node.js) -->
app.post('/login', (req, res) => {
// 验证用户名和密码
if (authenticated) {
const redirectUrl = req.body.redirect || '/dashboard';
res.redirect(redirectUrl);
}
});

3. 跳转链接中的未验证重定向

<!-- 不安全的跳转链接 -->
<a href="/redirect?url=https://malicious-website.com/phishing">点击继续</a>

<!-- 后端代码 -->
app.get('/redirect', (req, res) => {
const url = req.query.url;
res.redirect(url);
});

防御措施

1. 前端验证

在前端对重定向URL进行基本验证,确保其合法性:

// 验证重定向URL是否属于可信域
function validateRedirectUrl(url) {
const trustedDomains = ['trusted-website.com', 'api.trusted-website.com'];
try {
const parsedUrl = new URL(url);
return trustedDomains.includes(parsedUrl.hostname);
} catch (e) {
return false;
}
}

// 安全的重定向处理
const redirectUrl = new URLSearchParams(window.location.search).get('redirect');
if (redirectUrl && validateRedirectUrl(redirectUrl)) {
window.location.href = redirectUrl;
} else {
window.location.href = '/dashboard'; // 默认重定向
}

2. 后端白名单验证

在后端对重定向目标进行严格的白名单验证:

// 后端白名单验证(Node.js)
const allowedRedirects = ['/dashboard', '/profile', '/settings'];

app.get('/redirect', (req, res) => {
const url = req.query.url;
// 验证URL是否在白名单中
if (allowedRedirects.includes(url)) {
res.redirect(url);
} else {
// 处理无效重定向
res.redirect('/dashboard');
}
});

3. 使用相对路径

尽量使用相对路径而非绝对路径进行重定向:

// 安全的相对路径重定向
res.redirect('/dashboard');

// 而非绝对路径
// res.redirect('https://trusted-website.com/dashboard');

4. 避免传递完整URL

避免在URL参数中传递完整URL,而是使用标识符:

// 使用标识符而非完整URL
const redirectMap = {
'dashboard': '/dashboard',
'profile': '/profile',
'settings': '/settings'
};

app.get('/redirect', (req, res) => {
const target = req.query.target;
const redirectUrl = redirectMap[target] || '/dashboard';
res.redirect(redirectUrl);
});

最佳实践

  1. 对所有重定向目标进行严格的白名单验证
  2. 尽量使用相对路径而非绝对路径进行重定向
  3. 避免在URL参数中传递完整URL,使用标识符代替
  4. 在前端和后端都实施重定向验证,但以后端验证为主
  5. 教育用户识别钓鱼网站的特征(如URL异常、拼写错误等)
  6. 实施内容安全策略(CSP),限制重定向的来源
  7. 定期进行安全测试,包括未验证重定向测试
  8. 保持Web应用程序和依赖库的更新,以防止已知漏洞被利用
  9. 对敏感操作后的重定向进行额外验证,确保安全性