learn-bug-bounty
JavaScript – The language made for bugs
December 8, 2022
JavaScript is a programming language that can be used on both the client and server side for development. It is widely used on the Internet and is used on almost all web pages. In this article, we will discuss strange and interesting behaviours that JavaScript has built in and how they can be used by an attacker.
Function calls
In JavaScript, functions are first-class objects that refer to the Function object. Unlike other objects, the Function object can be called and return a value.
There are many different ways to call a function in JavaScript. We can call it directly, chain functions to call each other or call them from objects/prototypes.
In the payloads below, you can see some examples of how the alert() function can be called. An attacker can use these payloads to prove the existence of a Cross Site Scripting (XSS) vulnerability.
window.alert()
window['alert']()
alert()
alert``
onload=alert
\u0061lert()
globalThis.alert()
window?.alert()
eval?.('ale'+'rt('+')')
[1].find(alert)
好=alert,好()
var x=x||alert;x()
alert(1),ErrExit
[][0]??alert()
null??alert()
undefined??alert()
x??alert();var x;
Newlines
JavaScript supports newlines that are not valid ASCII characters (\u2028 and \u2029). These two chars can be used just like any other newline char. To test this function, you can run the following commands below, copy the output and run it.
console.log('alert//\u2028(1)')
console.log('alert//\u2029(1)')
As a Proof of Concept, you can see that the code you executed is presented on a “single line” and that a comment (//) is in place. The JavaScript code still works without problems and this is because \u2028 and \u2029 are seen as a new line.
Comments
The most common JavaScript comments are the double forward slash (//) and multi-line comments (/**/), but JavaScript also supports two additional comments that are rarely mentioned. The <!-- and --> are both supported within JavaScript. These comments are built-in and are also supported in the backend when Node.js is running. The JavaScript code below is valid and uses all four comment methods.
Hoisting
In JavaScript, variables and functions can be used before they are declared, which can lead to many strange behaviours.
In the code snippet below, the function x is used in the if statement before it is declared, but because of the way JavaScript is hoisting, the function x is automatically declared in the hoisting process before the code is executed.
This behaviour causes the if statement to execute and print the text “Oh snap“.
JavaScript function hoisting
If you define variables directly in a function, the variable (x) will set its value (20) both inside and outside the function.
This behaviour is interesting from an attacker’s point of view: when the attacker can control a value set in a function, he can infect other code processes that use this variable.
Imagine that a developer creates two variables with the same name, one inside a function and one outside. The developer doesn’t realise that they are the same variable, so in reality, (s)he created a single variable that is being reused when the function is called. This is because (s)he had forgotten to declare the variable with var, let or const.
In this code, the variable str is first set to the value location.search and the variable name is set to the value returned by the ParamNames function (infected). When the ParamNames function is called, it uses the same variable name (str) that was used outside the function. This made the variable str update its value globally because the variable str wasn’t properly declared inside the function.
Error behaviour
JavaScript runs until an error occurs, as long as it is not a syntax error.
Imagine that you have found a Cross Site Scripting (XSS) vulnerability. The injection works, but you want to stop future code from running. You can trigger an error in JavaScript which will act as an “exit command“. This causes JavaScript to run the code (including your payload) and stop when it encounters the error.
Document Object Model (DOM) XSS methods
An input that is vulnerable to a DOM XSS gives an attacker a big advantage when exploiting an XSS. In a DOM XSS, the attacker sometimes only needs one character to exploit the vulnerability, the backslash character (\).
The backslash character can be used to write in Hex, Unicode and Octal encoded forms. In this case, the payload <h1>Hello</h1> can be written in all the different ways listed below:
1. <h1>Hello</h1>
2. \x3Ch1\x3EHello\x3C\x2Fh1\x3E
3. \u003Ch1\u003EHello\u003C\u002Fh1\u003E
4. \u{3C}h1\u{3E}Hello\u{3C}\u{2F}h1\u{3E}
5. \74\150\61\76Hello\74\57\150\61\76
This method can be used to exploit one of our vulnerable code snippet (#10).
Code Styles
JavaScript code can be written in many strange ways sometimes. Some code styles are nearly never used in development, but only in attack scenarios. These code styles are therefore a great advantage for an attacker…
Unicode
Instead of writing JavaScript as intended, you can also write characters [a-zA-Z] in Unicode encoded form. This will run the code without any problems.
1. var a; a == \u0061 // true
2. alert() == \u0061\u006c\u0065\u0072\u0074() // true
JSFuck
JavaScript can be written with only six characters ([]()+!): this method is called JsFuck. This code style can be used to bypass restricted filters, protections and/or to write stealth exploits/payloads.
(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]] === "ert" // true
JsFuck works when it’s mixed with regular JavaScript code style. Below is a payload that calls the alert() function from the object top.
top['al'+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]](1)
The payload used JsFuck to embed the string "ert" (with quotes) to the top object, resulting in the following payload: top['al'+"ert"](1)
Cross-Site Scripting exploitation
XSS is an underestimated vulnerability as it is often referred to as “the pop-up window alert(1)“. An XSS vulnerability should be exploited like any other vulnerability to show its full impact potential, with a takeover of a victim’s account, for example.
Session hijack
If the cookie has weak security, it is often very easy for an attacker to exploit XSS and take over the entire account from the victim. An attacker hijacks the session value(s) in the cookie and sends them to a server that (s)he owns.
Iframe exploit
When a session is used within cookies and use strong security, this is where creativity comes into play. A good technique would be to take advantage of iframes. If the iframe security policy is weak, you can use the XSS to embed an iframe that mirrors the original domain and hijack the data within the embedded iframe.
Keylogger
JavaScript can be used to write a keylogger that hijacks the victim’s keystrokes, making it possible to hijack credentials in clear text.
Keyloggers can be combined with other exploitation techniques, such as the iframe exploitation technique explained above. By combining these two techniques, it is possible to follow the victim and hijack all keystrokes from almost any endpoint.
XSS exploitation frameworks
Metasploit offers JavaScript exploitation modules, e.g. the JavaScript keylogger. This module is good to include in your report as a Proof of Concept when an XSS vulnerability is detected in an application.
Note that YesWeHack has recently released a tool called xsstools. This XSS development framework, written by our Tech Ambassador BitK, makes it easier to create XSS payloads. This tool is ideal for building a working Proof of Concept to demonstrate a real impact.