PostMessage API yordamida domenlararo xavfsiz aloqani o'rganing. Veb-ilovalaridagi zaifliklarni bartaraf etish uchun uning imkoniyatlari, xavfsizlik xatarlari va ilg'or amaliyotlari bilan tanishing.
Domenlararo aloqa: PostMessage API bilan xavfsizlik na'munalari
Zamonaviy vebda ilovalar ko'pincha turli manbalardan kelgan resurslar bilan o'zaro aloqada bo'lishlari kerak. Yagona domen siyosati (Same-Origin Policy - SOP) skriptlarning boshqa domendagi resurslarga kirishini cheklovchi muhim xavfsizlik mexanizmidir. Biroq, domenlararo aloqa zarur bo'lgan qonuniy stsenariylar mavjud. postMessage API buni amalga oshirish uchun boshqariladigan mexanizmni taqdim etadi, lekin uning potentsial xavfsizlik xatarlarini tushunish va tegishli xavfsizlik na'munalarini qo'llash juda muhim.
Yagona domen siyosatini (SOP) tushunish
Yagona domen siyosati veb-brauzerlardagi fundamental xavfsizlik tushunchasidir. U veb-sahifalarning veb-sahifani taqdim etgan domendan boshqa domenga so'rovlar yuborishini cheklaydi. Manba sxema (protokol), xost (domen) va port orqali aniqlanadi. Agar ulardan birortasi farq qilsa, manbalar har xil hisoblanadi. Masalan:
https://example.comhttps://www.example.comhttp://example.comhttps://example.com:8080
Bularning barchasi turli manbalardir va SOP ular o'rtasida to'g'ridan-to'g'ri skript kirishini cheklaydi.
PostMessage API bilan tanishish
postMessage API domenlararo aloqa uchun xavfsiz va boshqariladigan mexanizmni taqdim etadi. U skriptlarga ularning manbasidan qat'i nazar, boshqa oynalarga (masalan, iframelar, yangi oynalar yoki tablar) xabarlar yuborish imkonini beradi. Qabul qiluvchi oyna keyin bu xabarlarni tinglashi va shunga mos ravishda qayta ishlashi mumkin.
Xabar yuborishning asosiy sintaksisi:
otherWindow.postMessage(message, targetOrigin);
otherWindow: Maqsad oynaga havola (masalan,window.parent,iframe.contentWindowyokiwindow.openorqali olingan oyna ob'ekti).message: Siz yubormoqchi bo'lgan ma'lumotlar. Bu seriyalashtirilishi mumkin bo'lgan har qanday JavaScript ob'ekti bo'lishi mumkin (masalan, satrlar, raqamlar, ob'ektlar, massivlar).targetOrigin: Xabarni yubormoqchi bo'lgan manbani belgilaydi. Bu muhim xavfsizlik parametrdir.
Qabul qiluvchi tomonda siz message hodisasini tinglashingiz kerak:
window.addEventListener('message', function(event) {
// ...
});
event ob'ekti quyidagi xususiyatlarni o'z ichiga oladi:
event.data: Boshqa oyna tomonidan yuborilgan xabar.event.origin: Xabarni yuborgan oynaning manbasi.event.source: Xabarni yuborgan oynaga havola.
Xavfsizlik xatarlari va zaifliklar
postMessage SOP cheklovlarini chetlab o'tish usulini taklif qilsa-da, agar ehtiyotkorlik bilan amalga oshirilmasa, u potentsial xavfsizlik xatarlarini ham keltirib chiqaradi. Mana bir nechta keng tarqalgan zaifliklar:
1. Maqsad manba nomuvofiqligi
event.origin xususiyatini tekshirmaslik jiddiy zaiflikdir. Agar qabul qiluvchi xabarga ko'r-ko'rona ishonsa, har qanday veb-sayt zararli ma'lumotlarni yuborishi mumkin. Xabarni qayta ishlashdan oldin har doim event.origin kutilgan manbaga mos kelishini tekshiring.
Misol (Zaif kod):
window.addEventListener('message', function(event) {
// BUNI QILMANG!
processMessage(event.data);
});
Misol (Xavfsiz kod):
window.addEventListener('message', function(event) {
if (event.origin !== 'https://trusted-origin.com') {
console.warn('Ishonchsiz manbadan xabar olindi:', event.origin);
return;
}
processMessage(event.data);
});
2. Ma'lumotlarni kiritish (Data Injection)
Qabul qilingan ma'lumotlarni (event.data) bajariladigan kod sifatida ko'rib chiqish yoki uni to'g'ridan-to'g'ri DOMga kiritish Saytlararo skripting (XSS) zaifliklariga olib kelishi mumkin. Qabul qilingan ma'lumotlardan foydalanishdan oldin ularni har doim tozalang va tekshiring.
Misol (Zaif kod):
window.addEventListener('message', function(event) {
if (event.origin === 'https://trusted-origin.com') {
document.body.innerHTML = event.data; // BUNI QILMANG!
}
});
Misol (Xavfsiz kod):
window.addEventListener('message', function(event) {
if (event.origin === 'https://trusted-origin.com') {
const sanitizedData = sanitize(event.data); // To'g'ri tozalash funksiyasini amalga oshiring
document.getElementById('message-container').textContent = sanitizedData;
}
});
function sanitize(data) {
// Bu yerda mustahkam tozalash mantiqini amalga oshiring.
// Masalan, DOMPurify yoki shunga o'xshash kutubxonadan foydalaning
return DOMPurify.sanitize(data);
}
3. O'rtadagi odam (Man-in-the-Middle - MITM) hujumlari
Agar aloqa xavfsiz bo'lmagan kanal (HTTP) orqali amalga oshirilsa, MITM hujumchisi xabarlarni ushlab olishi va o'zgartirishi mumkin. Xavfsiz aloqa uchun har doim HTTPSdan foydalaning.
4. Saytlararo so'rovlarni soxtalashtirish (Cross-Site Request Forgery - CSRF)
Agar qabul qiluvchi olingan xabarga asoslanib, tegishli tekshiruvsiz harakatlarni amalga oshirsa, hujumchi qabul qiluvchini kutilmagan harakatlarni bajarishga undash uchun xabarlarni soxtalashtirishi mumkin. CSRF himoya mexanizmlarini, masalan, xabarga maxfiy token qo'shish va uni qabul qiluvchi tomonda tekshirish kabilarni amalga oshiring.
5. targetOrigin da umumiy belgilardan ('*') foydalanish
targetOrigin ni * ga o'rnatish har qanday manbaga xabarni qabul qilish imkonini beradi. Bunga mutlaqo zarur bo'lmasa, yo'l qo'ymaslik kerak, chunki bu manbaga asoslangan xavfsizlik maqsadini yo'qqa chiqaradi. Agar * dan foydalanishga majbur bo'lsangiz, xabar autentifikatsiya kodlari (MAC) kabi boshqa kuchli xavfsizlik choralarini qo'llaganingizga ishonch hosil qiling.
Misol (Bundan qoching):
otherWindow.postMessage(message, '*'); // Mutlaqo zarur bo'lmasa, '*' dan foydalanishdan saqlaning
Xavfsizlik na'munalari va eng yaxshi amaliyotlar
postMessage bilan bog'liq xatarlarni kamaytirish uchun ushbu xavfsizlik na'munalari va eng yaxshi amaliyotlarga rioya qiling:
1. Manbani qat'iy tekshirish
Har doim qabul qiluvchi tomonda event.origin xususiyatini tekshiring. Uni oldindan belgilangan ishonchli manbalar ro'yxati bilan solishtiring. Solishtirish uchun qat'iy tenglikdan (===) foydalaning.
2. Ma'lumotlarni tozalash va tekshirish
postMessage orqali olingan barcha ma'lumotlarni ishlatishdan oldin tozalang va tekshiring. Ma'lumotlardan qanday foydalanilishiga qarab tegishli tozalash usullaridan foydalaning (masalan, HTML ekranlash, URL kodlash, kiritishni tekshirish). HTMLni tozalash uchun DOMPurify kabi kutubxonalardan foydalaning.
3. Xabar autentifikatsiya kodlari (MAC)
Xabarning yaxlitligi va haqiqiyligini ta'minlash uchun unga Xabar Autentifikatsiya Kodini (MAC) qo'shing. Yuboruvchi MACni umumiy maxfiy kalit yordamida hisoblaydi va uni xabarga qo'shadi. Qabul qiluvchi MACni xuddi shu umumiy maxfiy kalit yordamida qayta hisoblaydi va uni qabul qilingan MAC bilan solishtiradi. Agar ular mos kelsa, xabar haqiqiy va o'zgartirilmagan hisoblanadi.
Misol (HMAC-SHA256 yordamida):
// Yuboruvchi
async function sendMessage(message, targetOrigin, sharedSecret) {
const encoder = new TextEncoder();
const data = encoder.encode(JSON.stringify(message));
const key = await crypto.subtle.importKey(
"raw",
encoder.encode(sharedSecret),
{ name: "HMAC", hash: "SHA-256" },
false,
["sign"]
);
const signature = await crypto.subtle.sign("HMAC", key, data);
const signatureArray = Array.from(new Uint8Array(signature));
const signatureHex = signatureArray.map(b => b.toString(16).padStart(2, '0')).join('');
const securedMessage = {
data: message,
signature: signatureHex
};
otherWindow.postMessage(securedMessage, targetOrigin);
}
// Qabul qiluvchi
async function receiveMessage(event, sharedSecret) {
if (event.origin !== 'https://trusted-origin.com') {
console.warn('Ishonchsiz manbadan xabar olindi:', event.origin);
return;
}
const securedMessage = event.data;
const message = securedMessage.data;
const receivedSignature = securedMessage.signature;
const encoder = new TextEncoder();
const data = encoder.encode(JSON.stringify(message));
const key = await crypto.subtle.importKey(
"raw",
encoder.encode(sharedSecret),
{ name: "HMAC", hash: "SHA-256" },
false,
["verify"]
);
const signature = await crypto.subtle.sign("HMAC", key, data);
const signatureArray = Array.from(new Uint8Array(signature));
const signatureHex = signatureArray.map(b => b.toString(16).padStart(2, '0')).join('');
if (signatureHex === receivedSignature) {
console.log('Xabar haqiqiy!');
processMessage(message); // Xabarni qayta ishlashni davom eting
} else {
console.error('Xabar imzosini tekshirish muvaffaqiyatsiz tugadi!');
}
}
Muhim: Umumiy maxfiy kalit xavfsiz tarzda yaratilishi va saqlanishi kerak. Kalitni kodda qattiq belgilashdan saqlaning.
4. Nonce va vaqt belgilaridan foydalanish
Qayta ijro etish hujumlarining oldini olish uchun xabarga noyob nonce (bir marta ishlatiladigan raqam) va vaqt belgisini qo'shing. Qabul qiluvchi keyin nonce avval ishlatilmaganligini va vaqt belgisi qabul qilinadigan vaqt oralig'ida ekanligini tekshirishi mumkin. Bu hujumchining avval ushlab olingan xabarlarni qayta yuborish xavfini kamaytiradi.
5. Eng kam imtiyoz printsipi
Boshqa oynaga faqat minimal zarur imtiyozlarni bering. Masalan, agar boshqa oynaga faqat ma'lumotlarni o'qish kerak bo'lsa, unga ma'lumotlarni yozishga ruxsat bermang. Aloqa protokollaringizni eng kam imtiyoz printsipini hisobga olgan holda loyihalashtiring.
6. Kontent xavfsizligi siyosati (CSP)
Skriptlar qaysi manbalardan yuklanishi mumkinligini va skriptlar qanday harakatlarni bajarishi mumkinligini cheklash uchun Kontent xavfsizligi siyosatidan (CSP) foydalaning. Bu postMessage ma'lumotlarini noto'g'ri ishlash natijasida yuzaga kelishi mumkin bo'lgan XSS zaifliklarining ta'sirini kamaytirishga yordam beradi.
7. Kiritishni tekshirish
Har doim qabul qilingan ma'lumotlarning tuzilishi va formatini tekshiring. Aniq xabar formatini belgilang va qabul qilingan ma'lumotlar ushbu formatga mos kelishiga ishonch hosil qiling. Bu kutilmagan xatti-harakatlar va zaifliklarning oldini olishga yordam beradi.
8. Ma'lumotlarni xavfsiz seriyalashtirish
Xabarlarni seriyalashtirish va deseriyalashtirish uchun JSON kabi xavfsiz ma'lumotlarni seriyalashtirish formatidan foydalaning. eval() yoki Function() kabi kod bajarilishiga imkon beruvchi formatlardan foydalanishdan saqlaning.
9. Xabar hajmini cheklash
postMessage orqali yuboriladigan xabarlar hajmini cheklang. Katta hajmdagi xabarlar ortiqcha resurslarni sarflashi va potentsial ravishda xizmat ko'rsatishni rad etish (denial-of-service) hujumlariga olib kelishi mumkin.
10. Muntazam xavfsizlik auditlari
Potensial zaifliklarni aniqlash va bartaraf etish uchun kodingizning muntazam xavfsizlik auditlarini o'tkazing. postMessage ni amalga oshirishga alohida e'tibor bering va barcha xavfsizlik bo'yicha eng yaxshi amaliyotlarga rioya qilinganligiga ishonch hosil qiling.
Misol stsenariysi: Iframe va uning ota-onasi o'rtasidagi xavfsiz aloqa
https://iframe.example.com da joylashgan iframe https://parent.example.com da joylashgan ota-ona sahifasi bilan aloqa qilishi kerak bo'lgan stsenariyni ko'rib chiqing. Iframe foydalanuvchi ma'lumotlarini qayta ishlash uchun ota-ona sahifasiga yuborishi kerak.
Iframe (https://iframe.example.com):
// Umumiy maxfiy kalit yaratish (xavfsiz kalit yaratish usuli bilan almashtiring)
const sharedSecret = 'SIZNING_XAVFSIZ_UMUMIY_MAXFIY_KALITINGIZ';
// Foydalanuvchi ma'lumotlarini olish
const userData = {
name: 'John Doe',
email: 'john.doe@example.com'
};
// Foydalanuvchi ma'lumotlarini ota-ona sahifasiga yuborish
async function sendUserData(userData) {
const encoder = new TextEncoder();
const data = encoder.encode(JSON.stringify(userData));
const key = await crypto.subtle.importKey(
"raw",
encoder.encode(sharedSecret),
{ name: "HMAC", hash: "SHA-256" },
false,
["sign"]
);
const signature = await crypto.subtle.sign("HMAC", key, data);
const signatureArray = Array.from(new Uint8Array(signature));
const signatureHex = signatureArray.map(b => b.toString(16).padStart(2, '0')).join('');
const securedMessage = {
data: userData,
signature: signatureHex
};
parent.postMessage(securedMessage, 'https://parent.example.com');
}
sendUserData(userData);
Ota-ona sahifasi (https://parent.example.com):
// Umumiy maxfiy kalit (iframening kaliti bilan mos kelishi kerak)
const sharedSecret = 'SIZNING_XAVFSIZ_UMUMIY_MAXFIY_KALITINGIZ';
window.addEventListener('message', async function(event) {
if (event.origin !== 'https://iframe.example.com') {
console.warn('Ishonchsiz manbadan xabar olindi:', event.origin);
return;
}
const securedMessage = event.data;
const userData = securedMessage.data;
const receivedSignature = securedMessage.signature;
const encoder = new TextEncoder();
const data = encoder.encode(JSON.stringify(userData));
const key = await crypto.subtle.importKey(
"raw",
encoder.encode(sharedSecret),
{ name: "HMAC", hash: "SHA-256" },
false,
["verify"]
);
const signature = await crypto.subtle.sign("HMAC", key, data);
const signatureArray = Array.from(new Uint8Array(signature));
const signatureHex = signatureArray.map(b => b.toString(16).padStart(2, '0')).join('');
if (signatureHex === receivedSignature) {
console.log('Xabar haqiqiy!');
// Foydalanuvchi ma'lumotlarini qayta ishlash
console.log('Foydalanuvchi ma\'lumotlari:', userData);
} else {
console.error('Xabar imzosini tekshirish muvaffaqiyatsiz tugadi!');
}
});
Muhim eslatmalar:
SIZNING_XAVFSIZ_UMUMIY_MAXFIY_KALITINGIZni xavfsiz tarzda yaratilgan umumiy maxfiy kalit bilan almashtiring.- Umumiy maxfiy kalit ham iframeda, ham ota-ona sahifasida bir xil bo'lishi kerak.
- Ushbu misolda xabar autentifikatsiyasi uchun HMAC-SHA256 ishlatiladi.
Xulosa
postMessage API veb-ilovalarda domenlararo aloqani ta'minlash uchun kuchli vositadir. Biroq, potentsial xavfsizlik xatarlarini tushunish va bu xatarlarni kamaytirish uchun tegishli xavfsizlik na'munalarini qo'llash juda muhim. Ushbu qo'llanmada keltirilgan xavfsizlik na'munalari va eng yaxshi amaliyotlarga rioya qilish orqali siz mustahkam va xavfsiz veb-ilovalarni yaratish uchun postMessage dan xavfsiz foydalanishingiz mumkin.
Har doim xavfsizlikka ustuvorlik berishni va veb-ishlab chiqish uchun eng so'nggi xavfsizlik bo'yicha eng yaxshi amaliyotlardan xabardor bo'lishni unutmang. Ilovalaringiz potentsial zaifliklardan himoyalanganligiga ishonch hosil qilish uchun kodingizni va xavfsizlik sozlamalaringizni muntazam ravishda ko'rib chiqing.