XSS and how JSFuck just f*cked my brain

The digital age has brought with it numerous advantages, but also new security threats. XSS, which stands for “Cross-Site Scripting”, has been one of the most frequent issues in the OWASP Top 10. One of the ways we can combat XSS is to properly sanitize the inputs of the requests. But what if there was a technique that could fucked up your sanitization? Introducing JSFuck!

Explaining XSS

Before I talk about JSFuck, I should first explain what XSS (Cross-Site Scripting) is. Imagine you are using a website or an online platform that you trust to input some information, such as your name or a message. An attacker who is aware of an XSS vulnerability in the website can inject malicious code into the site, which can then be executed by other users who visit the site. This malicious code can steal sensitive information, such as passwords and credit card numbers, or it can manipulate the website to display false information or perform actions that the attacker wants.

So, in the simplest terms, XSS is a way for a hacker to inject harmful code into a website that you visit, which can then steal information from you or harm your computer.

Schema of how the XSS attack works

There are also several security practices that you and your organization can follow in order to prevent XSS. I have narrowed it down to these five:

  1. Input validation: Make sure that any user input is validated and sanitized before being used in any way. This can help prevent malicious code from being executed on the website.
  2. Escaping user input: When displaying user input, it’s important to escape any characters that have special meaning in HTML, such as < and >. This will prevent any malicious code from being executed when it is displayed on the page.
  3. Content Security Policy (CSP): A Content Security Policy is a security feature that helps prevent XSS attacks by specifying which sources of content are allowed to be loaded by the browser.
  4. Up-to-date web browser: Keep your web browser up-to-date and use a browser that has a strong security record, as this can help prevent XSS attacks.
  5. Educate users: Educate your users about the dangers of XSS attacks and what they can do to protect themselves, such as not entering sensitive information into untrusted websites.

Introducing JSFuck

JSFuck is a form of obfuscated JavaScript code that uses only six characters ( , , ! , ( , ) , [ and ] ) to write malicious code. These six characters can be used in a variety of ways to create JavaScript code that can perform malicious actions, such as stealing sensitive information or executing harmful commands. The purpose of JSFuck is to bypass security measures that are designed to detect and block malicious JavaScript code.

note: JSFuck was inspired by Brainfuck, an esotheric programming language created in 1993 by Urban Müller.

In simple terms, JSFuck is a way for hackers to write malicious code that looks like gibberish to the average person, but that can still perform harmful actions when executed. This type of code is used to bypass security measures and harm individuals or organizations.

Okay, now we know what JSFuck is. Let’s take a look on how it works. These are the basics of JSFuck:

  • false → ![]
  • true → !![]
  • undefined → [][[]]
  • NaN → +[![]]
  • 0 → +[]
  • 1 → +!+[]
  • 2 → !+[]+!+[]
  • 10 → [+!+[]]+[+[]]
  • Array → []
  • Number → +[]
  • String → []+[]
  • Boolean → ![]
  • Function → []["filter"]
  • eval → []["filter"]["constructor"]( CODE )()
  • window → []["filter"]["constructor"]("return this")()

We can use the basics in order to translate the letter “a” in JSFuck:

  1. First start by creating an array [] which evaluates to false when used as a boolean value.
  2. Use the ! operator to invert the boolean value of the array result in true.
  3. Use the + operator to add the boolean value true to an empty array, resulting in the string "true".
  4. Use bracket notation to access the 2nd character in the string false, which is the letter “a”. The code would be ("true")[1].
  5. Simplify the code by replacing the string "true" with (![]+[]), which results in the following JSFuck code to represent the letter “a”: (![]+[])[1].
  6. Replate the number 1 with the atomic +!+[]. The result would be: (![]+[])[+!+[]]

If you want to test it yourself, there is a nice JSFuck translator available here.

Exploiting using JSFuck

In order to test JSFuck, I have set up a small playground by spinning up my Apache server and creating this simple webpage. I have also made a small modification to my server and increased the LimitRequestLine to 100 000 characters from the original 8 177 characters.

My goal is to exploit this webpage by displaying an alert window that says my name.

<html>
  <body>
    <h2>Pawn me?</h2>
    <script>
    vuln = (new URL(location).searchParams.get('userinput'))
    
    // "Sanitization" by removing alphabetical and numerical characters
    vuln = vuln.replace(/[A-Za-z0-9]/g, '')
    
    eval(vuln)
    </script>
    </body>
</html>

The website looks like this:

Our vulnerable webpage

Okay, time for me to put on my hacker hat. At first glance, there are no user inputs that I can exploit. I might, however, be able to create HTTP requests using the URL address. In this case, I am looking to exploit the GET parameter. Armed with this knowledge, I can look into the code. Let’s open my trusty DevTools!

DevTools view

Here I can see that the webpage has some logic in the background. Basically, what it does is that it takes the value associated with the URL parameter named userinput and sanitizes it by removing the alphabetical and numerical values. Because of this, I cannot simply exploit the webpage by trying to pass something like alert("Hung").

This is the time that JSFuck comes to the scene! What I need to do is convert the command alert("Hung") into the JSFuck form. In order to do this, I can use the online JSFuck translator.

Converting my payload to the JSFuck form

I cannot however just pass this JSFuck output as my payload. There is still one step and that is to convert it to the URL encoded format. For that we can use this online URL encoder.

Encoding JSFuck to URL format

Now the only thing remaining is to use this payload in order to finish the XSS attack.

Successfully breaching the site using XSS

Conclusion

In this article, we have learned about XSS and how JavaScript obfuscation using JSFuck can overcome improper sanitization. In order to protect your organization against these types of attacks, it is important to validate and sanitize user input, escape characters with special meaning in HTML, and use a Content Security Policy.

If you have read so far, you might want to follow me here on Hashnode. Feel free to connect with me over at LinkedIn or Mastodon.