是防止在nodejs安全的开放redirect攻击?

我试图阻止打开redirect攻击。 请看下面的代码并检查安全性:

var = require('url'); // http://example.com/login?redirect=http://example.com/dashboard app.route('/login', function (req, res, next) { var redirect = req.query.redirect, paths = url.parse(redirect); if (paths.host !== req.headers.host) { return next(new Error('Open redirect attack detected')); } return res.redirect(redirect); }); 

防止打开redirect攻击是否足够?还是应该添加其他内容?

CWE-601:URLredirect到不受信任的站点(“打开redirect”)

Open Redirect描述:

http参数可能包含一个URL值,并可能导致Web应用程序将请求redirect到指定的URL。 通过将URL值修改为恶意网站,攻击者可以成功启动钓鱼诈骗并窃取用户凭据。 由于修改后的链接中的服务器名称与原始网站相同,因此networking钓鱼尝试的外观更加值得信赖。

input validation策略防止开放redirect攻击的build议:

假设所有的input都是恶意的。 使用“接受已知的好”inputvalidation策略,即使用严格符合规范的可接受input的白名单。 拒绝不严格符合规范的任何input,或者将其转换为某种情况。 不要完全依靠寻找恶意或畸形input(即不要依赖黑名单)。 黑名单可能会遗漏至less一个不良的input,尤其是如果代码的环境发生变化的话。 这可能给攻击者足够的空间来绕过预期的validation。 但是,黑名单可以用于检测潜在的攻击或确定哪些input是如此恶劣,以至于应该直接拒绝。 使用经批准的URL或域的白名单用于redirect。

使用req.headers.hostreq.hostreq.hostname是不安全的,因为req.headers可以被伪造(例如,一个HTTP请求有一个自定义的Host头来访问一个用下面代码写的快速应用)

 var url = require('url'); app.get('/login', function (req, res, next) { var redirect = req.query.redirect, targetUrl = url.parse(redirect); console.log('req.headers.host: [%s]', req.headers.host); console.log('req.host: [%s]', req.host); console.log('req.hostname: [%s]', req.hostname); if (targetUrl.host != req.headers.host) { return next(new Error('Open redirect attack detected')); } return res.redirect(redirect); }); 

使用curl提出请求:

 $ curl -H 'Host: malicious.example.com' 'http://localhost:3012/login?redirect=http://malicious.example.com' -i HTTP/1.1 302 Found X-Powered-By: Express Location: http://malicious.example.com Vary: Accept Content-Type: text/plain; charset=utf-8 Content-Length: 54 Date: Mon, 13 Jun 2016 06:30:55 GMT Connection: keep-alive $ #server output req.headers.host: [malicious.example.com] req.host: [malicious.example.com] req.hostname: [malicious.example.com] 

我build议你使用白名单来validationinput,下面是一个示例代码:

 const WHITELIST_TO_REDIRECT = new Set(["localhost:3012", "www.realdomain.com"]); app.get('/login', function (req, res, next) { var redirect = req.query.redirect, targetUrl = url.parse(redirect); console.log("req.hostname: [%s]", req.hostname); console.log("url.host: [%s]", targetUrl.host); if (!WHITELIST_TO_REDIRECT.has(targetUrl.host)) { return next(new Error('Open redirect attack detected')); } return res.redirect(redirect); }); 

在这种情况下,我会使用HMAC 。 这将允许login控制器validationredirect参数是由知道密钥的人员生成的。

在生成“login”URL时,您将redirect参数的HMAC摘要与redirect参数本身一起添加到该URL。

login处理程序可以使用HMAC来确保redirect参数由知道HMAC密钥的可信服务器生成,从而防止打开redirect攻击。

例如

 var crypto = require('crypto'); var secretKey = 'change-me'; var loginUrl = 'http://example.com/login' // called to work out where to redirect to for login function getLoginUrl(redirectBackUrl) { var sig = crypto.createHmac('sha1', secretKey) .update(redirectBackUrl) .digest('hex'); return loginUrl + '?redirect=' + encodeURIComponent(redirectBackUrl) +'&sig=' + sig; } // called by the login function to ensure that the // redirect parameter is valid function isRedirectUrlValid(url, sig) { var expectedSig = crypto.createHmac('sha1', secretKey) .update(url) .digest('hex'); return expectedSig === sig; }