Xavfsizlik — XSS, CSRF, SQL injection, sessiya o'g'irlash
Muammodan boshlaylik
Kurs davomida xavfsizlik haqida alohida darslarda gaplashdik: XSS (20-dars), SQL injection (36-dars), parollar (38-dars), fayl yuklash (22-dars). Bu darsda hammasini bitta tizimga yig'amiz va hali ko'rmagan muhim hujum — CSRF ni o'rganamiz.
Asosiy tamoyil bitta: foydalanuvchidan kelgan har qanday narsa — hujum bo'lishi mumkin. Brauzer sizning nazoratingizda emas.
1. SQL Injection
Hujum: foydalanuvchi ma'lumoti SQL kodi sifatida bajariladi.
// ❌
$pdo->query("SELECT * FROM users WHERE email = '$email'");
Himoya: prepared statements — har doim, istisnosiz.
// ✅
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$email]);
Ustun nomlari va ORDER BY yo'nalishi — faqat whitelist orqali.
2. XSS — Cross-Site Scripting
Hujum: foydalanuvchi kiritgan HTML/JavaScript boshqa foydalanuvchilarning brauzerida bajariladi. Natija: cookie o'g'irlash, sahifani soxtalashtirish, foydalanuvchi nomidan amallar.
// ❌
<p><?= $izoh ?></p>
Himoya:
// ✅
<p><?= htmlspecialchars($izoh, ENT_QUOTES, 'UTF-8') ?></p>
Qo'shimcha himoya qavatlari:
- Sessiya cookie si
httponly— JavaScript uni o'qiy olmaydi - Content-Security-Policy sarlavhasi — brauzerga qaysi skriptlarni bajarishga ruxsat borligini aytadi:
<?php
header("Content-Security-Policy: default-src 'self'; script-src 'self'");
Endi sahifaga qandaydir yo'l bilan <script> kirib qolsa ham — brauzer faqat sizning domeningizdagi skript fayllarini bajaradi, inline skriptlarni bloklaydi.
3. CSRF — Cross-Site Request Forgery
Bu yangi hujum turi. Diqqat bilan o'qing.
Vaziyat: foydalanuvchi sizning bankingiz saytiga kirgan (sessiya cookie si brauzerida bor). Keyin u boshqa tabda "Bepul iPhone yutib oling!" degan saytni ochdi. O'sha saytda yashirin forma bor:
<form action="https://sizning-bank.uz/otkazma" method="post" id="f">
<input type="hidden" name="kimga" value="hujumchi_hisobi">
<input type="hidden" name="summa" value="5000000">
</form>
<script>document.getElementById('f').submit();</script>
Brauzer bu formani sizning saytingizga yuboradi — va foydalanuvchining cookie sini qo'shib yuboradi. Sizning serveringiz uchun bu oddiy, login qilgan foydalanuvchidan kelgan to'g'ri so'rov. Pul o'tkazildi.
Foydalanuvchi hech narsa bosmadi. Hech qanday parol so'ralmadi.
Himoya: CSRF token
Har bir formaga hujumchi bilmaydigan tasodifiy qiymat qo'shamiz:
<?php
// src/csrf.php
function csrfToken(): string
{
if (empty($_SESSION['csrf'])) {
$_SESSION['csrf'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf'];
}
function csrfMaydon(): string
{
return '<input type="hidden" name="_csrf" value="' . csrfToken() . '">';
}
function csrfTekshir(): void
{
$kelgan = $_POST['_csrf'] ?? '';
if (!hash_equals($_SESSION['csrf'] ?? '', $kelgan)) {
http_response_code(419);
exit("So'rov muddati o'tgan. Sahifani yangilab, qayta urinib ko'ring.");
}
}
Formada:
<form method="post" action="/otkazma">
<?= csrfMaydon() ?>
<input name="kimga">
<input name="summa">
<button>O'tkazish</button>
</form>
Qayta ishlashda — birinchi qator:
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
csrfTekshir();
// ...
}
Hujumchining sayti foydalanuvchining sessiyasidagi tokenni bilmaydi va o'qiy olmaydi (brauzer boshqa saytning sahifasini o'qishga ruxsat bermaydi). Shuning uchun uning soxta formasi rad etiladi.
hash_equals() — oddiy === o'rniga. U har doim bir xil vaqtda ishlaydi, shuning uchun javob vaqtini o'lchab tokenni harfma-harf topish mumkin emas (timing attack).
Qo'shimcha himoya: SameSite cookie
<?php
session_set_cookie_params(['samesite' => 'Lax', 'httponly' => true, 'secure' => true]);
SameSite=Lax — brauzer boshqa saytdan kelgan POST so'rovlarga cookie qo'shmaydi. Zamonaviy brauzerlarda bu CSRF ning ko'p qismini to'xtatadi. Lekin eski brauzerlar va ba'zi holatlar uchun token baribir kerak.
[!TIP] Laravel da
@csrfdirektivasi vaVerifyCsrfTokenmiddleware aynan shu ishni avtomatik bajaradi. Endi siz uning ichida nima borligini bilasiz.
4. Sessiya o'g'irlash (Session Hijacking)
Hujum: hujumchi foydalanuvchining sessiya ID sini qo'lga kiritadi (XSS orqali, ochiq Wi-Fi da shifrlanmagan trafikdan, URL dagi ID dan) va uning nomidan kiradi.
Himoya:
<?php
ini_set('session.use_strict_mode', '1'); // noma'lum ID larni qabul qilmaslik
ini_set('session.use_only_cookies', '1'); // ID faqat cookie da, URL da hech qachon
session_set_cookie_params([
'httponly' => true, // XSS orqali o'g'irlab bo'lmaydi
'secure' => true, // faqat HTTPS
'samesite' => 'Lax',
]);
session_start();
Va har doim:
- Login da
session_regenerate_id(true)— session fixation dan himoya - Logout da
session_destroy() - Butun saytda HTTPS — Let's Encrypt bilan bepul
5. Boshqa muhim qoidalar
Avtorizatsiya — "bu ma'lumot shu foydalanuvchinikimi?"
Eng ko'p e'tibordan chetda qoladigan xato:
<?php
// ❌ Har kim ID ni o'zgartirib, boshqaning buyurtmasini ko'radi
$stmt = $pdo->prepare('SELECT * FROM buyurtmalar WHERE id = ?');
$stmt->execute([$_GET['id']]);
// ✅ Faqat o'zining buyurtmasi
$stmt = $pdo->prepare('SELECT * FROM buyurtmalar WHERE id = ? AND user_id = ?');
$stmt->execute([$_GET['id'], $_SESSION['user_id']]);
Bu IDOR (Insecure Direct Object Reference) deyiladi. /buyurtma/1043 → /buyurtma/1044 — hujumchi faqat raqamni o'zgartiradi.
Xatolarni yashirish
display_errors = Off
log_errors = On
Fayllarni veb-ildizdan tashqarida saqlash
Faqat public/ ochiq. config.php, .env, vendor/, src/, uploads/ — undan tashqarida.
Bog'liqliklarni yangilab turish
composer audit
O'rnatilgan paketlarda ma'lum zaifliklar bormi — tekshiradi.
Xavfsizlik ro'yxati
Har bir loyihani ishga tushirishdan oldin:
| Tekshiruv | |
|---|---|
| ☐ | Barcha SQL — prepared statements |
| ☐ | Barcha chiqish — htmlspecialchars |
| ☐ | Barcha POST formalarda — CSRF token |
| ☐ | Parollar — password_hash |
| ☐ | Sessiya cookie — httponly, secure, samesite |
| ☐ | Login da session_regenerate_id(true) |
| ☐ | Har bir so'rovda "bu foydalanuvchiga ruxsat bormi?" tekshiruvi |
| ☐ | Fayl yuklash — MIME tekshiruv, tasodifiy nom, PHP bajarilmaydi |
| ☐ | display_errors = Off |
| ☐ | HTTPS |
| ☐ | .env, config.php — veb-ildizdan tashqarida va Git da yo'q |
| ☐ | composer audit toza |
Nima uchun shunday?
Nima uchun veb-xavfsizlik bunchalik murakkab — nega brauzer o'zi himoya qilmaydi?
Chunki veb "ochiqlik" uchun yaratilgan: istalgan sayt istalgan saytga havola bera oladi, forma yubora oladi, rasm yuklay oladi. Bu ochiqlik internetni internet qilgan narsa. Lekin u har bir saytni potentsial hujum manbaiga ham aylantiradi. Brauzerlar yillar davomida himoya qavatlarini qo'shib kelgan (Same-Origin Policy, SameSite, CSP), lekin ular faqat siz to'g'ri sozlasangiz ishlaydi. Oxirgi himoya chizig'i — har doim sizning server kodingiz.
Xulosa
Eslab qoling:
- SQL injection → prepared statements
- XSS →
htmlspecialchars+httponlycookie + CSP - CSRF → har bir POST formada token +
hash_equals+SameSite - Sessiya o'g'irlash →
httponly,secure, strict mode,session_regenerate_id, HTTPS - IDOR → har bir so'rovda egalikni tekshiring (
AND user_id = ?) - Framework bularning ko'pini avtomatik qiladi — lekin qanday ishlashini bilish shart
Keyingi dars
44-dars: Laravel ga kirish — nima uchun framework kerak