Answer to the XSS Trick

Let’s learn an interesting XSS trick and why it works :)

SecurityGOAT
5 min readJul 28, 2021

So in my previous post where I covered on one of the labs by Thexssrat, I showed you some different XSS payloads. And one of them was a bonus payload:

Payload:

<script>eval(8680439..toString(30)+“(1337)”)</script>

Reference: https://portswigger.net/web-security/cross-site-scripting

I suggest you to check that writeup first, so you can get the most out of this post! You can find that writeup here:

So, were you able to come up with why the provided payload works?

No worries if you couldn’t! That’s perfectly fine… We are all learning :)

The Answer is 42

Hahaha, let’s build the foundation first, to get to the answer! And it’s not 42 xP

I will walk you through how I would have approached it, if I didn’t knew what this payload did. Simple process makes life more simpler ;)

Inside the script, we have:

eval(8680439..toString(30)+“(1337)”)

So it evals something and results in an alert!

But why does it works? The thing that should be passed to eval must be alert(1337).

We can clearly see (1337) part. So this weird looking expression must lead us to alert right!

8680439..toString(30)

But how? How is this number equal to alert?

Let’s first try it out in the browser console. Press CTRL+SHIFT+I, navigate to the console window and enter the payload:

8680439..toString(30)

It’s indeed equivalent to alert. But how?

Did you notice the argument being passed to toString method?

That is the base or radix, which must be in the range 2 to 36.

Base 10 means the decimal numbers which we are familiar with (0 to 9). It consists of 10 possible values.

Base 2 means binary — just 0s and 1s. So it consists of 2 possible values.

Base 16 means 0–9 and a-f — 16 possible values make it up!

Base36 would be 0–9 and a-z — 36 possible values, as you must have guessed!

If we give an integer to the toString method, we need to put it in the braces `()`, else .toString() gives an error!

Why an error, you may wonder — the reason is that there’s a flaw in Javascript’s parser that tries to parse the dot notation on number as a floating point literal. And therefore —

10.toString() would be same as 10.0toString() which doesn’t makes any sense right!

So either we can put it in braces or assign it to a variable and apply the toString method on that variable like so:

count = 10; count.toString()

But there’s another way to do it, without using braces or extra variables — by converting the int to float and applying the toString on it! And it works perfectly, saving us space as well ;)

10..toString() is same as 10.0.toString()

Bonus tip:

You can also use a space instead of a ‘.’ to avoid any conversion to floating point. So this payload would work as well:

10 .toString()

Notice the space between 10 and the period (.)

And if you feel skeptic about it, see for yourself ;)

8680439 .toString(30)

The Final Answer

Okay now you know all the stuff to figure the payload out!

But if you are in a hurry, let’s jump to it!

So we had this to start with:

8680439..toString(30)

.toString() as we learnt can accept a base/radix.

Base30 means: 0–9 and a-t

Don’t believe me?

Then calculate this:

(9–0 + 1) + (‘t’.charCodeAt() — ‘a’.charCodeAt() + 1)

So we can use the characters from 0–9 and a-t.

Can you see that ‘t’ is the stopping point! Because if you notice, the character with the largest code point (or numeric ascii value) in alert is ‘t’, that is, t comes after all the other characters present in alert. And that’s why there was this radix of 30!

Could have been 36 as well, no harm, but we don’t need more characters right, so we are not going with 36, but you can, if you want to!

Okay, that cleared, now it should be pretty obvious what that payload does! Right?

Yes correct! You guessed it, finally! That number you see is the numeric value of alert string in base 30.

Don’t trust me? Let me show you:

Makes more sense now right!

Payload Utility

Now you might be wondering, okay great! I just learnt yet another way to pop-up an alert. But what’s the utility of this payload. Where can it actually help me?

And I would say, brilliant question my friend! It’s important to understand where a payload is applicable, because in some pentesting situations, you might find certain constraints and limitations, so not every payload is applicable in all scenarios!

This payload can be used if there’s a WAF that’s filtering out alert, eval, from the user input etc. toString is too benign to get blocked* ;)

*Note: If there’s a WAF that filters out the braces (), then ofcourse this payload fails as well. The payload just helps you bypass some obvious regex checks.

Maybe this ‘*’ scares you a bit now, and therefore I will cover on Parenthesis-less XSS as well, in one of my next posts :)

So that’s why you must add it to your XSS Payload list, and thank me later if it helps you some day :D

Closing Thoughts

I hope you liked this payload and how we got to it! In infosec, its more important to understand a concept rather than copy-pasting payloads from some other people’s blogs or tweets!

And that’s why I wanted to show you that obscure looking things are not always obscure, but might contain some easy pieces that make it up!

I hope this post was informative and helped you learn something interesting!

In case you enjoyed it, please share it among your friends in the infosec community :)

Let me know your feedback in the comments below and feel free to connect on twitter: @_SecurityGOAT

Lastly, if you have been enjoying my work and would love to support me, consider checking my Patreon page or you can even Buy Me a Coffee :)

See ya!
Until next time my friend, keep learning and happy hacking.

--

--