Open Redirect
What is an Open Redirect Vulnerability?
An open redirect occurs when a flaw in a website’s client-side or server-side code allows an attacker to redirect a user to a malicious site by abusing a legitimate website’s redirect functionality. This is often used in phishing attacks because the victim sees a trusted domain in the URL before being redirected.
Exploitation in Practice
Discovery
Look for URL parameters that look like paths or URLs. For example:
https://site.com/login?ReturnURL=https://site.com/my-account
https://site.com/form-complete?return=/completed
https://site.com/api/v2/redirect?url=https://site.com/404
If there are no obvious parameters, try fuzzing for hidden ones using a tool like ffuf
or Burp Suite.
A good parameter wordlist is burp-parameter-names.txt
. If you have SecLists installed, you can find it at /usr/share/seclists/Discovery/Web-Content
. On Kali Linux, install it with:
apt install seclists
or download it from GitHub: SecLists
Exploitation
If the parameter contains a URL like https://site.com/my-account
, change it to your malicious URL:
https://site.com/login?ReturnURL=https://attacker-website.com
If the parameter is a path, like /completed
, try replacing it with a full URL. If that fails, use tricks like the username@hostname
syntax.
Username@Hostname Bypass
Some sites concatenate the parameter to their own domain, like this:
app.get('/form-complete', (req, res) => {
var redirectPath = req.query.return;
res.redirect('https://site.com' + redirectPath);
});
If you pass @attacker-website.com
as the parameter, it produces:
Location: https://site.com@attacker-website.com
Browsers interpret site.com
as a username, so the request goes to attacker-website.com
.
Example request:
GET /form-complete?return=@attacker-website.com HTTP/1.1
Host: site.com
Result: the victim is redirected to the attacker’s site.
Common Defense Evasions
1. Includes Domain
If the application checks that the target URL includes its own domain, bypass it by adding the domain as a parameter to your own site:
https://site.com/login?return=https://attacker-website.com/?foo=site.com
Payload: https://attacker-website.com/?foo=site.com
2. Starts With Domain
If the site checks whether the URL starts with the domain, bypass it with the same username@hostname
trick:
https://site.com/login?return=https://site.com@attacker-website.com
Payload: https://site.com@attacker-website.com
3. Blacklist
If the application blacklists http://
and https://
by matching the entire string, you can sometimes bypass it by adding an extra slash:
https://site.com/login?return=https:///attacker-website.com
Payload: https:///attacker-website.com
(notice the third slash)
Mitigation
Avoid dynamic redirects when possible; use hardcoded URLs.
If dynamic redirects are needed, prefix the URL with
/
to enforce an internal path:// Safer res.redirect('/' + path); // Risky res.redirect('https://site.com' + path);
Use strict validation with regex or a whitelist of allowed paths:
re = /^[\w/]+$/; if (re.test(req.query.return)) { res.redirect(req.query.return); } else { res.redirect('/error'); }
Tips
Use webhook.site to test your payloads in practice.
Burp Suite has extensions specifically for finding open redirects.
URL shorteners can help hide malicious redirect URLs in phishing attacks.
Last updated