XSS va CSRF
XSS va CSRF โ web ilovalarga eng ko'p tahdid soladigan ikki hujum turi. Ular bir-biriga o'xshab ketadi, lekin butunlay boshqacha ishlaydi. Ushbu darsda biz har birini faqat himoya nuqtai nazaridan tushunamiz: zaiflik qanday paydo bo'ladi va undan qanday himoyalanish kerak.
XSS nima?
XSS (Cross-Site Scripting) โ bu hujumchi sizning sahifangizga zararli JavaScript kod "joylashtira" olishi natijasida yuzaga keladigan zaiflik. Bu ko'pincha shunday sodir bo'ladi: ilova foydalanuvchi kiritgan matnni HTML sifatida, uni tozalamasdan sahifaga chiqaradi.
Masalan, izohlar bo'limi foydalanuvchi yozgan matnni to'g'ridan-to'g'ri HTML'ga qo'ysa va foydalanuvchi matn o'rniga <script> tegi yozsa, brauzer uni oddiy matn emas, bajariladigan kod deb qabul qiladi. Natijada boshqa foydalanuvchilar sahifani ochganda o'sha kod ularning brauzerida ishlaydi.
Nima uchun bu xavfli? Chunki zararli skript foydalanuvchining brauzerida, sizning saytingiz nomidan ishlaydi:
- U cookie'larni o'qib olishi mumkin (agar ular
HttpOnlybo'lmasa); - U foydalanuvchi nomidan so'rovlar yuborishi mumkin;
- U sahifa mazmunini o'zgartirib, foydalanuvchini aldashi mumkin.
XSS himoyasi 1: chiqishni eskeyplash
Eng asosiy himoya: foydalanuvchi ma'lumotini sahifaga chiqarishda uni HTML sifatida emas, oddiy matn sifatida ko'rsatish. Buning uchun maxsus HTML belgilarini "qochirish" (escaping) kerak:
// Foydalanuvchi kiritmasidagi xavfli belgilarni eskeyplash
function htmlEskeyp(matn) {
return String(matn)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
// Endi foydalanuvchi '<script>...' yozsa ham,
// u matn sifatida ko'rinadi, kod sifatida BAJARILMAYDI.
const xavfsiz = htmlEskeyp(foydalanuvchiIzohi);
Amaliyotda ko'pchilik shablon tizimlari (masalan, EJS, Pug, Handlebars) o'zgaruvchilarni avtomatik eskeyplaydi. Muhimi: avtomatik eskeyplashni o'chirmaslik. Masalan, EJS'da <%= x %> eskeyplaydi, <%- x %> esa eskeyplamaydi โ ikkinchisi xavfli:
// EJS shablonida:
// XAVFSIZ (avtomatik eskeyplanadi):
// <%= foydalanuvchi.ismi %>
//
// XAVFLI (eskeyplanmaydi, xom HTML chiqadi):
// <%- foydalanuvchi.ismi %> <-- foydalanuvchi ma'lumotiga BUNI ishlatmang!
XSS himoyasi 2: textContent va innerHTML
Mijoz tomonidagi JavaScript'da eng ko'p uchraydigan XSS sababi โ innerHTML ni foydalanuvchi ma'lumoti bilan ishlatish. innerHTML berilgan matnni HTML sifatida talqin qiladi, ya'ni ichidagi teglar ishga tushadi:
// XAVFLI: innerHTML foydalanuvchi ma'lumotini HTML deb talqin qiladi
const izoh = olinganFoydalanuvchiIzohi; // masalan '<img src=x onerror=...>'
element.innerHTML = izoh; // zararli kod ishga tushishi mumkin!
// XAVFSIZ: textContent hamma narsani ODDIY MATN deb qo'yadi
element.textContent = izoh; // teglar matn sifatida ko'rinadi, bajarilmaydi
Qoida oddiy: foydalanuvchi ma'lumotini ko'rsatishda deyarli har doim textContent ishlating, innerHTML emas. Agar HTML tuzilmasi yaratishingiz kerak bo'lsa, elementlarni createElement bilan yarating va matnni textContent orqali qo'ying:
// HTML tuzilmasini xavfsiz yaratish
const div = document.createElement('div');
div.className = 'izoh';
const nom = document.createElement('strong');
nom.textContent = foydalanuvchi.ismi; // xavfsiz
const matn = document.createElement('p');
matn.textContent = foydalanuvchi.izohi; // xavfsiz
div.append(nom, matn);
konteyner.append(div);
DOMPurify kabi sinovdan o'tgan kutubxonadan foydalaning: u xavfli teg va atributlarni olib tashlaydi.XSS himoyasi 3: Content Security Policy (CSP)
CSP โ bu qo'shimcha himoya qatlami. U HTTP sarlavhasi orqali brauzerga aytadi: "faqat shu manbalardagi skriptlarni ishga tushir". Agar XSS'ga yo'l qo'yilgan bo'lsa ham, CSP ruxsat bermagan skript ishga tushmaydi.
// CSP sarlavhasini o'rnatish (Express, helmet orqali)
const helmet = require('helmet');
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"], // faqat o'z domenimizdan
scriptSrc: ["'self'"], // inline skript va tashqi skriptlar taqiqlanadi
styleSrc: ["'self'"],
imgSrc: ["'self'", 'data:'],
objectSrc: ["'none'"] // <object>, <embed> taqiqlanadi
}
}));
CSP'ning kuchli tomoni: scriptSrc 'self' bo'lsa, HTML ichiga joylashtirilgan (inline) skriptlar ishlamaydi. Bu esa ko'plab XSS hujumlarini avtomatik to'xtatadi, chunki hujumchi joylashtirgan skript aynan inline bo'ladi.
CSRF nima?
CSRF (Cross-Site Request Forgery) โ bu foydalanuvchining allaqachon login qilgan holatidan foydalanib, uni bilmagan holda biror amalni bajartirishga aldash zaifligi. XSS'dan farqi: bu yerda hujumchi sizning saytingizga kod joylashtirmaydi โ u foydalanuvchi brauzerining cookie'ni avtomatik yuborish odatidan foydalanadi.
Muammoning ildizi: brauzer sizning saytingizga so'rov yuborilganda, u saytingiz cookie'larini avtomatik qo'shadi โ hattoki so'rov boshqa (zararli) saytdan kelib chiqqan bo'lsa ham. Agar server faqat cookie'ning mavjudligiga ishonsa, u bu so'rovni haqiqiy foydalanuvchining so'rovi deb qabul qiladi.
Masalan, foydalanuvchi bank saytiga login qilgan, cookie'si bor. So'ng u boshqa zararli sahifani ochsa, o'sha sahifa foydalanuvchi bilmagan holda bank saytiga so'rov jo'natishga urinishi mumkin โ va brauzer avtomatik ravishda bank cookie'sini biriktiradi.
GET so'rov bilan bajarilmasligi kerak โ ular POST/PUT/DELETE bo'lishi va CSRF himoyasiga ega bo'lishi lozim.CSRF himoyasi 1: SameSite cookie
Eng oddiy va samarali zamonaviy himoya โ cookie'ga SameSite atributini qo'yish. Bu brauzerga aytadi: bu cookie'ni boshqa saytdan kelgan so'rovlarda yuborma. Shu bilan CSRF hujumining asosiy mexanizmi (cookie'ning avtomatik yuborilishi) buziladi:
// SameSite bilan cookie: boshqa saytdan kelgan so'rovlarda
// cookie yuborilmaydi -> CSRF ning asosiy yo'li yopiladi
res.cookie('sessionId', sessionId, {
httpOnly: true,
secure: true,
sameSite: 'lax' // yoki 'strict' โ undan ham qattiqroq
});
SameSite=Lax ko'pchilik holatlar uchun yaxshi standart: u oddiy navigatsiyani buzmaydi, lekin xavfli o'zaro-sayt so'rovlarida cookie'ni yubormaydi. SameSite=Strict yanada qattiqroq, lekin ba'zan foydalanuvchi tajribasiga ta'sir qilishi mumkin.
CSRF himoyasi 2: CSRF token
An'anaviy va ishonchli himoya โ CSRF token (yoki "anti-forgery token"). G'oya shunday: server har bir forma uchun tasodifiy, taxmin qilib bo'lmaydigan token yaratadi. Bu token formaga yashirin maydon sifatida qo'yiladi. So'rov kelganda, server tokenning to'g'riligini tekshiradi.
Nima uchun bu ishlaydi? Chunki boshqa (zararli) sayt bu tokenni bila olmaydi โ u faqat sizning saytingizdagi haqiqiy formada mavjud. Cookie avtomatik yuborilsa ham, to'g'ri CSRF token yuborilmasa, so'rov rad etiladi.
// Kontseptual CSRF himoya oqimi (Express)
const crypto = require('crypto');
// 1. Forma sahifasini berishda token yaratamiz
app.get('/parol-ozgartirish', (req, res) => {
const csrfToken = crypto.randomBytes(32).toString('hex');
req.session.csrfToken = csrfToken; // serverda saqlaymiz
res.render('parol-forma', { csrfToken });
});
// Formada yashirin maydon:
// <input type="hidden" name="_csrf" value="...token...">
// 2. So'rov kelganda tokenni tekshiruvchi middleware
function csrfTekshir(req, res, next) {
const yuborilgan = req.body._csrf;
const saqlangan = req.session.csrfToken;
if (!yuborilgan || yuborilgan !== saqlangan) {
return res.status(403).json({ xato: 'CSRF token yaroqsiz' });
}
next();
}
app.post('/parol-ozgartirish', csrfTekshir, (req, res) => {
// Bu yerga faqat to'g'ri CSRF token bilan yetib kelinadi
// ... parolni o'zgartiramiz
});
csurf yoki freymvorkning o'z himoyasidan) foydalaning. Yuqoridagi kod tamoyilni ko'rsatish uchun soddalashtirilgan.SameSite cookie (birinchi mudofaa) + CSRF token (ishonchli ikkinchi qatlam). API'lar uchun, agar autentifikatsiya cookie'da emas, Authorization sarlavhasidagi tokenda bo'lsa, CSRF tabiiy ravishda kamroq muammo bo'ladi (chunki sarlavha avtomatik yuborilmaydi).XSS va CSRF: farqni eslab qolish
- XSS โ hujumchi sizning saytingizda kod ishga tushiradi; himoya: kirishni eskeyplash,
textContent, CSP; - CSRF โ hujumchi foydalanuvchining login holatidan foydalanib so'rov yuboradi; himoya:
SameSitecookie, CSRF token; - XSS aslida CSRF himoyasini ham buzishi mumkin (chunki u sahifada CSRF tokenni o'qiy oladi) โ shuning uchun XSS'ni oldini olish birlamchi.
Xulosa
- XSS โ foydalanuvchi ma'lumoti kod sifatida bajarilishi; birlamchi himoya โ chiqishni eskeyplash va
textContentishlatish; innerHTMLni foydalanuvchi ma'lumoti bilan ishlatmang; kerak bo'lsaDOMPurifydan foydalaning;- CSP โ qo'shimcha qatlam: inline skriptlarni bloklab, XSS ta'sirini kamaytiradi;
- CSRF โ foydalanuvchining login holatidan noqonuniy foydalanish; himoya โ
SameSitecookie va CSRF token; - Holatni o'zgartiruvchi amallar hech qachon
GETbilan bo'lmasin; - Eng yaxshi yondashuv โ bir necha himoya qatlamini birlashtirish (defense in depth).