“Clickjacking” hujumi yomon sahifaga tashrif buyuruvchi nomidan "jabrlanuvchi sayt"da bosish imkonini beradi.
Ko’plab saytlar shu tariqa buzilgan, jumladan Twitter, Facebook, Paypal va boshqa saytlar. Albatta, ularning hammasi tuzatilgan.
G’oya
G’oya juda oddiy.
Mana Facebook bilan clickjacking qanday amalga oshirilgan:
- Tashrif buyuruvchi yomon sahifaga aldatiladi. Bu qanday bo’lishi muhim emas.
- Sahifada zararsiz ko’rinadigan havola bor (“hozir boyib ket” yoki “bu yerda bos, juda kulgili” kabi).
- O’sha havolaning ustiga yomon sahifa facebook.com dan
src
bilan shaffof<iframe>
ni joylashtiradi, shunday qilib “Like” tugmasi o’sha havolaning to’g’ri ustida bo’ladi. Odatda buz-index
bilan amalga oshiriladi. - Havolani bosishga harakat qilganda, tashrif buyuruvchi aslida tugmani bosadi.
Demo
Mana yomon sahifa qanday ko’rinadi. Narsalarni aniqlashtirish uchun <iframe>
yarim shaffof (haqiqiy yomon sahifalarda u to’liq shaffof):
<style>
iframe { /* jabrlanuvchi saytdan iframe */
width: 400px;
height: 100px;
position: absolute;
top:0; left:-20px;
opacity: 0.5; /* haqiqatda opacity:0 */
z-index: 1;
}
</style>
<div>Hozir boyib ketish uchun bos:</div>
<!-- Jabrlanuvchi saytdan url -->
<iframe src="/clickjacking/facebook.html"></iframe>
<button>Bu yerda bos!</button>
<div>...Va siz zo'rsiz (Men aslida zo'r hacker man)!</div>
Hujumning to’liq demosi:
<!DOCTYPE html>
<html>
<body style="margin: 10px; padding: 10px">
<input
type="button"
onclick="alert('facebook.html da like bosildi!')"
value="Men bunu yaxshi ko'raman!"
/>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<style>
iframe {
width: 400px;
height: 100px;
position: absolute;
top: 5px;
left: -14px;
opacity: 0.5;
z-index: 1;
}
</style>
<div>Ijtimoiy tarmoqlarda tavakkal qo'shilish uchun:</div>
<!-- Jabrlanuvchi saytining url-i -->
<iframe src="facebook.html"></iframe>
<button>Buni bosing!</button>
<div>...Va siz zo'rsiz (aslida men ajoyib xakerman)!</div>
</body>
</html>
Bu yerda bizda yarim shaffof <iframe src="facebook.html">
bor va misolda uni tugma ustida suzayotganini ko’rishimiz mumkin. Tugmani bosish aslida iframe ni bosadi, lekin bu foydalanuvchi uchun ko’rinmaydi, chunki iframe shaffof.
Natijada, agar tashrif buyuruvchi Facebook da avtorizatsiyalangan bo’lsa (“meni eslab qol” odatda yoqilgan), u holda “Like” qo’shadi. Twitter da bu “Follow” tugmasi bo’lardi.
Mana bir xil misol, lekin haqiqatga yaqinroq, <iframe>
uchun opacity:0
bilan:
<!DOCTYPE html>
<html>
<body style="margin: 10px; padding: 10px">
<input
type="button"
onclick="alert('facebook.html da like bosildi!')"
value="Men bunu yaxshi ko'raman!"
/>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<style>
iframe {
width: 400px;
height: 100px;
position: absolute;
top: 5px;
left: -14px;
opacity: 0;
z-index: 1;
}
</style>
<div>Ijtimoiy tarmoqlarda tavakkal qo'shilish uchun:</div>
<!-- Jabrlanuvchi saytidan url -->
<iframe src="facebook.html"></iframe>
<button>Bu yerni bosing!</button>
<div>...Va siz zo'rsiz (aslida men ajoyib xakerman)!</div>
</body>
</html>
Hujum qilish uchun bizga kerak bo’lgan narsa – yomon sahifada <iframe>
ni shunday joylashtirishki, tugma havolaning to’g’ri ustida bo’lsin. Shunda foydalanuvchi havolani bosganda, ular aslida tugmani bosadi. Bu odatda CSS bilan amalga oshirilishi mumkin.
Hujum faqat sichqoncha harakatlariga ta’sir qiladi (yoki mobilda tegish kabi shunga o’xshashlar).
Klaviatura kiritishini yo’naltirish ancha qiyin. Texnik jihatdan, agar buzish uchun matn maydonimiz bo’lsa, iframe ni shunday joylashtirishimiz mumkinki, matn maydonlari bir-birining ustiga tushsin. Shunda tashrif buyuruvchi sahifada ko’rgan kiritishga fokuslanishga harakat qilganda, ular aslida iframe ichidagi kiritishga fokuslanadi.
Lekin keyin muammo bor. Tashrif buyuruvchi yozgan hamma narsa yashirin bo’ladi, chunki iframe ko’rinmaydi.
Odamlar odatda ekranda yangi belgilarining chop etilayotganini ko’ra olmasalar, yozishni to’xtatadilar.
Eski maktab mudofaasi (zaif)
Eng qadimiy mudofaa sahifani ramkada ochishni taqiqlovchi bir oz JavaScript (so’zma-so’z “framebusting” deb ataladi).
Bu shunday ko’rinadi:
if (top != window) {
top.location = window.location;
}
Ya’ni: agar oyna o’zining yuqorida emasligini bilsa, u avtomatik ravishda o’zini yuqoriga qo’yadi.
Bu ishonchli mudofaa emas, chunki uni buzishning ko’plab usullari mavjud. Bir nechtasini ko’rib chiqaylik.
Top-navigation ni bloklash
Biz beforeunload hodisa ishlov beruvchisida top.location
ni o’zgartirish sabab bo’lgan o’tishni bloklay olamiz.
Yuqori sahifa (o’rab turuvchi, hackerga tegishli) unga oldini oluvchi ishlov beruvchi o’rnatadi:
window.onbeforeunload = function() {
return false;
};
iframe
top.location
ni o’zgartirishga harakat qilganda, tashrif buyuruvchi chiqishni xohlash-xohlamasligini so’raydigan xabar oladi.
Ko’p hollarda tashrif buyuruvchi salbiy javob beradi, chunki ular iframe haqida bilmaydi – ular faqat yuqori sahifani ko’rishadi, chiqish uchun hech qanday sabab yo’q. Shunday qilib top.location
o’zgarmaydi!
Amalda:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<div>top.location ni javascript.info ga o'zgartiradi</div>
<script>
top.location = "https://javascript.info";
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<style>
iframe {
width: 400px;
height: 100px;
position: absolute;
top: 0;
left: -20px;
opacity: 0;
z-index: 1;
}
</style>
<script>
function attack() {
window.onbeforeunload = function () {
window.onbeforeunload = null;
return "Barcha sirlarni o'rganmasdan ketishni xohlaysizmi (he-he)?";
};
document.body.insertAdjacentHTML(
"beforeend",
'<iframe src="iframe.html">'
);
}
</script>
</head>
<body>
<p>
Tugmani bosgandan so'ng, tashrif buyuruvchiga "g'alati" savol tug'iladi
ular ketishni xohlaydilarmi.
</p>
<p>Ehtimol, ular "Yo'q" deb javob berishadi va iframe himoyasi buzilgan.</p>
<button onclick="attack()">"Himoyalangan" iframe qo'shing</button>
</body>
</html>
Sandbox xossasi
sandbox
xossasi tomonidan cheklanadigan narsalardan biri navigatsiyadir. Sandbox qilingan iframe top.location
ni o’zgartira olmaydi.
Shunday qilib, biz iframe ni sandbox="allow-scripts allow-forms"
bilan qo’shishimiz mumkin. Bu cheklovlarni yumshatadi, skriptlar va formalarga ruxsat beradi. Lekin biz allow-top-navigation
ni qoldiramiz, shunda top.location
ni o’zgartirish taqiqlanadi.
Mana kod:
<iframe sandbox="allow-scripts allow-forms" src="facebook.html"></iframe>
Bu oddiy himoyani chetlab o’tishning boshqa usullari ham bor.
X-Frame-Options
Server tomonidagi X-Frame-Options
sarlavhasi sahifani ramka ichida ko’rsatishga ruxsat berishi yoki taqiqlashi mumkin.
U aniq HTTP-sarlavha sifatida yuborilishi kerak: brauzer uni HTML <meta>
tegida topsa e’tiborsiz qoldiradi. Shuning uchun <meta http-equiv="X-Frame-Options"...>
hech narsa qilmaydi.
Sarlavha 3 ta qiymatga ega bo’lishi mumkin:
DENY
- Sahifani hech qachon ramka ichida ko’rsatmang.
SAMEORIGIN
- Agar ota hujjat bir xil kelib chiqishdan kelsa, ramka ichida ruxsat bering.
ALLOW-FROM domain
- Agar ota hujjat berilgan domendan bo’lsa, ramka ichida ruxsat bering.
Masalan, Twitter X-Frame-Options: SAMEORIGIN
dan foydalanadi.
Mana natija:
<iframe src="https://twitter.com"></iframe>
Brauzeringizga qarab, yuqoridagi iframe
yo bo’sh yoki brauzer o’sha sahifani bu tarzda navigatsiya qilishga ruxsat bermasligini bildiradigan ogohlantirish.
O’chirilgan funksionallik bilan ko’rsatish
X-Frame-Options
sarlavhasining yon ta’siri bor. Boshqa saytlar bizning sahifamizni ramkada ko’rsata olmaydi, hatto ularda buning uchun yaxshi sabablari bo’lsa ham.
Shuning uchun boshqa yechimlar mavjud… Masalan, biz sahifani height: 100%; width: 100%;
stillari bilan <div>
bilan “qoplashimiz” mumkin, shunda u barcha bosishlarni to’sadi. Agar window == top
bo’lsa yoki himoya kerak emasligini aniqlasak, o’sha <div>
olib tashlanishi kerak.
Mana shunday:
<style>
#protector {
height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 99999999;
}
</style>
<div id="protector">
<a href="/" target="_blank">Saytga o'ting</a>
</div>
<script>
// yuqori oyna boshqa kelib chiqishdan bo'lsa xato bo'ladi
// lekin bu yerda bu yaxshi
if (top.document.domain == document.domain) {
protector.remove();
}
</script>
Demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<style>
#protector {
height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 99999999;
}
</style>
</head>
<body>
<div id="protector">
<a href="/" target="_blank">Saytga o'tish</a>
</div>
<script>
if (top.document.domain == document.domain) {
protector.remove();
}
</script>
Ushbu matn har doim ko'rinadi. Ammo agar sahifa hujjat ichida ochiq bo'lsa
boshqa domen, uning ustidagi div har qanday harakatni oldini oladi.
<button onclick="alert(1)">Bunday holda bosish ishlamaydi</button>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<iframe src="iframe.html"></iframe>
</body>
</html>
Samesite cookie xossasi
samesite
cookie xossasi ham clickjacking hujumlarini oldini olishi mumkin.
Bunday xossaga ega cookie faqat veb-saytga to’g’ridan-to’g’ri ochilganda yuboriladi, ramka orqali yoki boshqacha yo’l bilan emas. Cookies, document.cookie bobida ko’proq ma’lumot.
Agar Facebook kabi sayt o’zining autentifikatsiya cookie sida samesite
xossasiga ega bo’lsa, masalan:
Set-Cookie: authorization=secret; samesite
…U holda bunday cookie Facebook boshqa saytdan iframe da ochilganda yuborilmaydi. Shunday qilib hujum muvaffaqiyatsiz bo’ladi.
samesite
cookie xossasi cookie lar ishlatilmaganda ta’sir qilmaydi. Bu boshqa veb-saytlarga bizning ochiq, autentifikatsiyalanmagan sahifalarimizni iframe larda osongina ko’rsatish imkonini berishi mumkin.
Biroq, bu clickjacking hujumlarining bir necha cheklangan hollarda ishlashiga ham imkon berishi mumkin. Masalan, IP manzillarni tekshirish orqali takroriy ovoz berishning oldini oladigan anonim so’rov veb-sayti hali ham clickjacking uchun zaif bo’ladi, chunki u cookie lar yordamida foydalanuvchilarni autentifikatsiya qilmaydi.
Xulosa
Clickjacking foydalanuvchilarni nima sodir bo’layotganini bilmasdan ham jabrlanuvchi saytni bosishga “aldash” usulidir. Muhim bosish bilan faollashadigan harakatlar bo’lsa, bu xavfli.
Hacker o’zining yomon sahifasiga havolani xabarda joylashtirishishi yoki tashrif buyuruvchilarni boshqa usullar bilan o’z sahifasiga jalb qilishi mumkin. Ko’plab variantlar mavjud.
Bir tomondan – hujum “chuqur emas”: hacker faqat bitta bosishni to’sib oladi. Lekin boshqa tomondan, agar hacker bosishdan keyin boshqa boshqaruv paydo bo’lishini bilsa, u holda ular foydalanuvchini ularni ham bosishga majburlash uchun ayyor xabarlardan foydalanishi mumkin.
Hujum juda xavfli, chunki UI ni loyihalashtirishda biz odatda hackerning tashrif buyuruvchi nomidan bosishini kutmaymiz. Shuning uchun zaifliklar butunlay kutilmagan joylarda topilishi mumkin.
- Ramka ichida ko’rishga mo’ljallanmagan sahifalarda (yoki butun veb-saytlarda)
X-Frame-Options: SAMEORIGIN
dan foydalanish tavsiya etiladi. - Agar sahifalarimizni iframe larda ko’rsatishga ruxsat berishni xohlasak, lekin xavfsiz bo’lishni istasak, qoplaydi
<div>
dan foydalaning.
Izohlar
<code>
yorlig'ini ishlating, bir nechta satrlar uchun - ularni<pre>
yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepen…)