CWE-601: Redirecting URL to untrusted site ('Open Redirect')
Description of Open Redirect :
The http parameter may contain a URL value and may cause the web application to redirect the request to the specified URL. By changing the value of the URL to a malicious site, an attacker can successfully launch phishing scams and steal user credentials. Since the server name in the modified link is identical to the original site, phishing attempts have a more reliable appearance.
input validation strategy recommendation to prevent an open redirect attack:
Suppose all input is malicious. Use the โacknowledge wellโ admission strategy, i.e. Use a whitelist of valid input that strictly conforms to the specifications. Reject any input that is strictly out of specification or converts it into something that does. Do not rely solely on the search for malicious or incorrect input data (i.e. do not rely on the blacklist). A blacklist is likely to miss at least one unwanted entry, especially if the code environment changes. This can give attackers enough room to circumvent the alleged test. However, blacklists can be useful in detecting potential attacks or determining which entries are so distorted that they should be rejected directly. Use a whitelist of the approved URLs or domains that will be used for redirection.
Using req.headers.host , req.host or req.hostname unsafe because req.headers can be faked (for example, an HTTP request has its own Host header to access the express application written in the code below)
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); });
Use curl to make a request:
$ 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 $
I suggest you use a whitelist to validate your input, sample code below:
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); });