Նախաբան
Բարև 👋️
Սա իմ առաջին գրառումն է, կարծում եմ ներկայանալու կարիք չկա, բայց եթե կարճ․
ես Սևադան եմ, ինքնուս բագ֊հանթեր։
Վերադառնալով թեմային, նախ եկեք ասեմ, որ որոշակի JS իմացությունը ցանկալի է այս թեման և պրակտիկ քայլերը հասկանալու համար,
Ի՞նչ է postMessage֊ը
postMessage-ը API է բրաուզերներում որի միջոցով 2 պատուհան կարող են իրար հետ «շփվել», այդ պատուհանների կապը կարող է ստեղծվել ինչպես iframe-ի շնորհիվ, այնպես էլ window.open() JS հրամանի շնորհիվ ինչպես նաև <a href=… target=_blank> օգտագործմամբ (եթե ուզում են opener-ը չմնա, կարող են գրել rel="noopener") . հեսա ավելի լավ կբացատրեմ մի տագնապեք։
(վարագույրների ետևում, chrome-ը ուղղակի վերցնում է մեկ պատուհանի տված դատան, և փոխանցում մյուսին, իսկ պատուհանը բացված կարող է ստանալ այդ դատան, onmessage event listener-ի օգնությամբ)
Կարճ դեմո
Նախ մի հատ եկեք պարզ դեմո անենք, օգտագործելով իմ գրած JS4hacking extension-ը, այն քաշեք որպես zip, unzip արեք,
ապա մտնելով chrome://extensions/ , միացրեք “Developer mode“֊ը և “Load unpacked“
Հիմա ընտրեք JS4hacking-ը unzip եղած։
Հիմա բացեք ասենք example.com կայքը, ու եկեք բացենք նոր պատուհան window.open()-ով (կապ չունի ինչ կայք կբացեք), և ուղարկենք որոշակի դատա, բայց նախքան դա՝ extension֊ից մեկ հատ switch միացրեք, “PostMessage Logger“֊ը, ապա կրկնեք այն հրամանները որոնք ես արել եմ screenshot֊երում, ահա այստեղ 👇️



Այստեղ դուք կարող եք տեսնել, թե ինչպես եմ ես մեկ պատուհանից ուղարկում ինչ֊որ դատա, և ստանում այն մեկ այլ պատուհանում։
Եվ եկեք մի քանի բան պարզեցնենք այստեղ․
նախ և առաջ, շա՜տ֊շա՜տ ծրագրավորողներ են օգտագործում JSON.stringify() → JSON.parse()
Object-ները postMessage անելուց առաջ, սակայն դրա կարիքը ընդհանրապես չկա, այս API-ը կարող է թե Object ուղարկել, և թե String,
Ուստի հարց է առաջանում ինչու է սա արվում․ պատասխանը շատ պարզ է,
որպեսզի չդնեն երկար֊բարակ check,
if (typeof e.data === ‘object’) {…} else {…}
միանգամից շատ ավելի հեշտ է գրել,
try {JSON.parse(e.data)} catch {…}
Դե եթե պարզապես String տանք JSON.parse()-ին , error կառաջանա, ու catch բլոկը ավտոմատ կաշխատի։
Մյուս բանը որ կուզեի նշել, դա այն է, որ postMessage-ի 2-րդ արգումենտում նշվում է թե ուր է ուղղված նամակը՝ որ origin-ին, սակայն իմ extension-ը ավելի բարձր թույլտվությամբ է աշխատում, և տեսնում է բոլոր message-ները։
Այլապես ահա, ես գրեցի example.com֊ում շատ պարզ onmessage-logger

Եվ ինչպես տեսնում եք, միայն վերջին նամակն է, որ log է եղել կայքի JS-ը մնացած նամակները չի տեսնում,
Այո՝ “https://www.example.com”-ին ուղղվածն էլ, այն նույն origin չէ ինչ “https://example.com”֊ը
Origin-ը իր մեջ ներառում է․ protocol + host + port
Անապահով postMessage-ի օգտագործում
Երբեմն֊երբեմն, կայքեր են հանդիպում, որոնք մոռանում են գրել check-եր որպեսզի ստուգեն origin-ը թե որտեղից է գալիս նամակը, և գործարկում են անապահով JS կոդ վստահելով կամայական տեղից եկող նամակին էսպես ասած։
Վատ կոդի օրինակներ, որ հանգեցնելու են XSS-ի
1)
window.addEventListener("message", (e) => {
const data = JSON.parse(e.data);
document.getElementById("output").innerHTML = data.html;
});
հարձակվողը ուղարկում է․՝
target.postMessage('{"html":"<img src=x onerror=alert(1)>"}', "*");
բու՛մ, XSS
2)
window.addEventListener("message", (e) => {
const data = JSON.parse(e.data);
window.location.href = data.url;
});
հարձակվողը ուղարկում է․՝
target.postMessage('{"url":"javascript:alert(1)"}', "*");
կրկին XSS
Ինչպես նաև հնարավոր է տվյալների արտահոսք, կամ նույնիսկ ATO (Account Takeover)
եթե օրինակ․՝ կայքը ինչ֊որ token փոխանցի իր parent-ին, կամ opener-ին, 2-րդ արգումենտ օգտագործելով “*“ սա, կամ postMessage back, to event.source, այն դեպքում, երբ կրկին չի ստուգվում origin-ը, սակայն առաջին նամակը ակնկալվում է opener֊ից կամ parent-ից
Հիմա եկեք ցույց տամ կոդի ապահով տարբերակ, origin checking
window.addEventListener("message", (e) => {
if (e.origin !== "https://www.valid.com") return;
const data = JSON.parse(e.data);
document.getElementById("output").innerHTML = data.html;
});
Ամփոփում
Մի խոսքով,
կարծում եմ հետաքրքիր էր, և մի բան սովորեցիք։
Ամեն բան եթե լավ սովորել կարելի է հասնել արդյունքների,
ժամանակի ու պրակտիկայի հարց ա։
Ես մեկ տարվա մեջ հանդիպել եմ 3 բագերի, հենց կոնկրետ միայն postMessage-ի շնորհիվ, 2 տեղ check չկար` XSS by redirect
վերջին հանդիպածս դեպքում էլ, չեքը bypass եմ արել, շատ հետաքրքիր չեք էր դրած :D
Եվ ստացա Cross-Site Storage Read-Write
Կկիսվեմ մի օր էդ խոցելի կոդի հատվածով, նույնիսկ եթե Disclosure չթողնեն, կկիսվեմ էստեղ ;D
Բայց հիմա քանի դեռ կայքում այդ խոցելի կոդը կա, ինչքան էլ ես թիրախը չնշեմ, ու ձևափոխած գցեմ կոդը․․․ մի քիչ հարմար չեմ համարում դա։
Մինչ նոր հանդիպում, իսկ դուք գրեք մեկնաբանություններում ձեր կարծիքը, եթե քերականական սխալ նկատեք՝ նույնպես նշեք խնդրում եմ։
Հ․Գ․ Փոստը գրելը մեկ ժամ տևեց 💀️








Comments (2)