1

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.

FZs
  • 16,581
  • 13
  • 41
  • 50
Sebast1aan
  • 19
  • 2

2 Answers2

4

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!

Endothermic_Dragon
  • 1,147
  • 3
  • 13
2

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));
Miro
  • 8,402
  • 3
  • 34
  • 72
  • 1
    What's the name of that syntax where it assigns characters at certain index to variables? I've been using js for a few years but I guess I'd never seen it lol. – Mahdi Ghajary Mar 05 '21 at 21:39
  • 1
    No clue. First time I see this syntax also. – Miro Mar 05 '21 at 21:50
  • 1
    Thanks, that's great – Sebast1aan Mar 09 '21 at 22:04
  • @Mahdi just found out that what it uses is ES6 feature called [Destructuring Assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) - "unpack values from array into distinct variables – Miro Mar 10 '21 at 02:59
  • @Miro I knew about Destructuring but this one seems a bit tricky. I'd never seen destructuring a single string by specifying indexes. – Mahdi Ghajary Mar 10 '21 at 10:45
  • 1
    @Mahdi oh, i got the other part but didn't know destructing. Check my edit :) – Miro Mar 10 '21 at 11:20