18-bo‘lim

Xavfsiz dasturlash amaliyoti

Xavfsizlikni ishlab chiqish jarayoniga singdirish - tahdid modeli, xavfsiz kod standartlari, CI tekshiruvlari va kod ko'rigi.

🕑 12 daqiqa o‘qish 📄 826 so‘z 👁 6 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Xarajat egri chizig'i
  2. Xavfsiz ishlab chiqish sikli
  3. Xavfsizlik talablari
  4. Dizayn bosqichida tahdid modeli
  5. Xavfsiz kod standartlari
  6. Kirish tekshiruvi qatlami
  7. CI da xavfsizlik tekshiruvlari
  8. Xavfsizlik testlari
  9. Bog'liqliklar siyosati
  10. Kod ko'rigi ro'yxati
  11. Xavfsizlik yetakchilari
  12. Xavfsiz standart holat
  13. Ishga tushirishdan oldingi ro'yxat
  14. Xulosa

Xavfsizlikni oxirida qo'shib bo'lmaydi. U dizayn bosqichidan boshlab jarayonning bir qismi bo'lishi kerak.

Xarajat egri chizig'i #

Zaiflikni tuzatish xarajati qachon topilishiga bog'liq Dizayn 1x Kod 5x Test 15x Ishga tushirish 50x Hujumdan keyin 100x+ Xarajat
Erta topilgan zaiflik arzon; ishga tushgandan keyin qimmat

Xavfsiz ishlab chiqish sikli #

Har bosqichda xavfsizlik faoliyati Talablar Xavfsizlik talablari Suiiste'mol holatlari Dizayn Tahdid modeli Arxitektura ko'rigi Kod Xavfsiz standartlar Kod ko'rigi Test SAST, DAST, SCA Pentest Ishlash Monitoring Yamoqlash Fikr-mulohaza qaytadi Chapga siljish prinsipi Xavfsizlik tekshiruvini imkon qadar erta bosqichga ko'chiring
Xavfsizlik - alohida bosqich emas, butun jarayonning qismi

Xavfsizlik talablari #

MARKDOWN
# Foydalanuvchi hikoyasi: Parolni tiklash

## Funksional talablar
- Foydalanuvchi elektron pochtasini kiritadi
- Havola yuboriladi
- Havola orqali yangi parol o'rnatiladi

## Xavfsizlik talablari
- [ ] Token kriptografik tasodifiy, kamida 32 bayt
- [ ] Token bazada **xeshlangan** holda saqlanadi
- [ ] Token 30 daqiqada eskiradi
- [ ] Token bir marta ishlatiladi
- [ ] Foydalanuvchi mavjudligi oshkor qilinmaydi
- [ ] IP va pochta bo'yicha tezlik cheklovi
- [ ] Parol o'zgargach barcha sessiyalar tugatiladi
- [ ] Foydalanuvchiga xabar yuboriladi
- [ ] Barcha urinishlar jurnalga yoziladi

## Suiiste'mol holatlari
- Hujumchi tokenni taxmin qilishga urinadi → uzunlik va tezlik cheklovi
- Hujumchi tokenni bazadan o'g'irlaydi → xeshlash
- Hujumchi pochtalar ro'yxatini tekshiradi → bir xil javob
- Hujumchi havolani qayta ishlatadi → bir martalik token
Suiiste'mol holatlari

Odatiy talablar "foydalanuvchi nima qila oladi" ni tasvirlaydi.

Suiiste'mol holati esa "hujumchi nima qilishga urinadi" ni tasvirlaydi.

Har bir muhim funksiya uchun kamida 3 ta suiiste'mol holati yozing. Bu tahdid modelining eng oddiy shakli.

Dizayn bosqichida tahdid modeli #

MARKDOWN
# Tahdid modeli: Fayl yuklash funksiyasi

## 1. Nima quriladi?
Foydalanuvchilar profil rasmini yuklaydi.

## 2. Nima noto'g'ri ketishi mumkin? (STRIDE)

| Tahdid | Ssenariy | Himoya |
|--------|----------|--------|
| Spoofing | Boshqaning profiliga yuklash | Sessiya tekshiruvi |
| Tampering | .php faylni rasm sifatida | MIME + kengaytma + qayta kodlash |
| Repudiation | "Men yuklamadim" | Jurnal: kim, qachon, IP |
| Info disclosure | Boshqaning faylini o'qish | Tasodifiy nom, huquq tekshiruvi |
| DoS | 10 GB fayl yuklash | Hajm cheklovi, tezlik cheklovi |
| Elevation | Web shell orqali kod bajarish | Alohida domen, bajarish taqiqi |

## 3. Nima qilamiz?
- Hajm: maksimum 2 MB
- Turlar: faqat jpg, png, webp
- Tekshiruv: `getimagesize()` + qayta kodlash
- Saqlash: veb-ildizdan tashqarida
- Nom: tasodifiy UUID
- Xizmat: alohida domen (static.dokon.uz)
- Nginx: shu papkada PHP bajarish o'chirilgan

## 4. Yetarlimi?
- [x] Har bir tahdid uchun himoya bor
- [x] Himoyalar testlar bilan qoplangan
- [ ] Antivirus tekshiruvi - keyingi bosqichda
PHP
final class RasmYuklovchi
{
    private const MAKS_HAJM = 2 * 1024 * 1024;
    private const RUXSAT = ['image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp'];

    public function yuklang(array $fayl, int $foydalanuvchiId): string
    {
        if ($fayl['error'] !== UPLOAD_ERR_OK) {
            throw new YuklashXatosi('Yuklashda xato');
        }

        if ($fayl['size'] > self::MAKS_HAJM) {
            throw new YuklashXatosi('Fayl juda katta');
        }

        // MIME ni mazmundan aniqlaymiz, sarlavhadan emas
        $mime = (new finfo(FILEINFO_MIME_TYPE))->file($fayl['tmp_name']);

        if (!isset(self::RUXSAT[$mime])) {
            throw new YuklashXatosi('Ruxsat etilmagan tur');
        }

        // Haqiqiy rasmmi?
        $olcham = @getimagesize($fayl['tmp_name']);

        if ($olcham === false) {
            throw new YuklashXatosi('Bu rasm emas');
        }

        // Qayta kodlash - yashirin kodni yo'q qiladi
        $tasvir = match ($mime) {
            'image/jpeg' => imagecreatefromjpeg($fayl['tmp_name']),
            'image/png'  => imagecreatefrompng($fayl['tmp_name']),
            'image/webp' => imagecreatefromwebp($fayl['tmp_name']),
        };

        $nom = bin2hex(random_bytes(16)) . '.jpg';
        $yol = $this->saqlashYoli . '/' . $nom;

        imagejpeg($tasvir, $yol, 85);
        imagedestroy($tasvir);

        $this->jurnal->yozing('rasm.yuklandi', [
            'foydalanuvchi' => $foydalanuvchiId,
            'nom' => $nom,
            'hajm' => $fayl['size'],
            'ip' => $_SERVER['REMOTE_ADDR'],
        ]);

        return $nom;
    }
}
Qayta kodlash - eng kuchli himoya

Hujumchi rasm ichiga PHP kodini yashirishi mumkin (polyglot fayl).

imagecreatefromjpeg() + imagejpeg() faylni piksel darajasida qayta yaratadi. Yashirin kod yo'qoladi, chunki u pikselga aylanmagan.

Bu tekshiruvdan ko'ra ishonchliroq.

Xavfsiz kod standartlari #

MARKDOWN
# Xavfsiz kod standarti - PHP

## 1. Ma'lumotlar bazasi
- HAR DOIM tayyorlangan so'rov (prepared statement)
- Jadval/ustun nomi dinamik bo'lsa - oq ro'yxat
- TAQIQ: so'rovga o'zgaruvchini birlashtirish

## 2. Chiqish
- HTML: htmlspecialchars($x, ENT_QUOTES, 'UTF-8')
- JS ichida: json_encode($x, JSON_HEX_TAG | JSON_HEX_AMP)
- URL: rawurlencode($x)
- Shablon avtomatik ekranlash bilan bo'lsin

## 3. Autentifikatsiya
- password_hash() PASSWORD_ARGON2ID bilan
- Kirish muvaffaqiyatli bo'lgach session_regenerate_id(true)
- Sessiya cookie: HttpOnly, Secure, SameSite=Lax

## 4. Tasodifiylik
- random_bytes(), random_int() - faqat shular
- TAQIQ: rand(), mt_rand(), uniqid()

## 5. Taqqoslash
- Sirlarni hash_equals() bilan solishtiring
- TAQIQ: == yoki === sirlar uchun

## 6. Fayllar
- Foydalanuvchi kiritgan yo'l - hech qachon to'g'ridan-to'g'ri
- realpath() + prefiks tekshiruvi

## 7. Tashqi buyruqlar
- Iloji boricha ishlatmang
- Kerak bo'lsa: escapeshellarg() har bir argument uchun
- TAQIQ: shell_exec($foydalanuvchiKiritgani)

## 8. Deserializatsiya
- TAQIQ: unserialize($ishonchsiz)
- json_decode() ishlating

## 9. Xatolar
- display_errors = Off (ishlab chiqarishda)
- Foydalanuvchiga umumiy xabar, jurnalga to'liq

## 10. Sirlar
- Kodda sir bo'lmasin - muhit o'zgaruvchisi yoki sir boshqaruvchisi
- .env fayl git ga qo'shilmasin
PHP
// Xavfsiz asos sinf - loyihada barcha so'rovlar shu orqali
final class XavfsizBaza
{
    public function __construct(private PDO $pdo) {}

    public function tanlang(string $sql, array $parametrlar = []): array
    {
        $sorov = $this->pdo->prepare($sql);
        $sorov->execute($parametrlar);

        return $sorov->fetchAll(PDO::FETCH_ASSOC);
    }

    /** Dinamik saralash - faqat oq ro'yxatdan */
    public function saralashUchun(string $ustun, array $ruxsat): string
    {
        if (!in_array($ustun, $ruxsat, true)) {
            throw new InvalidArgumentException('Ruxsat etilmagan ustun');
        }

        return $ustun;
    }
}

Kirish tekshiruvi qatlami #

PHP
/**
 * Barcha tashqi ma'lumot shu qatlamdan o'tadi.
 * Nazorat: oq ro'yxat, qat'iy turlar, chegara.
 */
final class Tekshiruvchi
{
    private array $xatolar = [];

    public function butun(string $maydon, mixed $qiymat, int $min, int $maks): ?int
    {
        $son = filter_var($qiymat, FILTER_VALIDATE_INT);

        if ($son === false) {
            $this->xatolar[$maydon] = 'Butun son bo\'lishi kerak';
            return null;
        }

        if ($son < $min || $son > $maks) {
            $this->xatolar[$maydon] = sprintf('%d va %d orasida bo\'lsin', $min, $maks);
            return null;
        }

        return $son;
    }

    public function pochta(string $maydon, mixed $qiymat): ?string
    {
        $pochta = filter_var((string) $qiymat, FILTER_VALIDATE_EMAIL);

        if ($pochta === false || strlen($pochta) > 254) {
            $this->xatolar[$maydon] = 'Pochta manzili noto\'g\'ri';
            return null;
        }

        return strtolower($pochta);
    }

    public function tanlov(string $maydon, mixed $qiymat, array $ruxsat): ?string
    {
        $qator = (string) $qiymat;

        if (!in_array($qator, $ruxsat, true)) {
            $this->xatolar[$maydon] = 'Noto\'g\'ri qiymat';
            return null;
        }

        return $qator;
    }

    public function matn(string $maydon, mixed $qiymat, int $maksUzunlik): ?string
    {
        $qator = trim((string) $qiymat);

        if ($qator === '') {
            $this->xatolar[$maydon] = 'Bo\'sh bo\'lmasin';
            return null;
        }

        if (mb_strlen($qator) > $maksUzunlik) {
            $this->xatolar[$maydon] = sprintf('Maksimum %d belgi', $maksUzunlik);
            return null;
        }

        // Boshqaruv belgilarini olib tashlaymiz
        return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $qator);
    }

    public function xatolarBormi(): bool
    {
        return $this->xatolar !== [];
    }

    public function xatolar(): array
    {
        return $this->xatolar;
    }
}
PHP
// Ishlatish
$t = new Tekshiruvchi();

$malumot = [
    'pochta'   => $t->pochta('pochta', $_POST['pochta'] ?? ''),
    'yosh'     => $t->butun('yosh', $_POST['yosh'] ?? '', 14, 120),
    'holat'    => $t->tanlov('holat', $_POST['holat'] ?? '', ['faol', 'nofaol']),
    'izoh'     => $t->matn('izoh', $_POST['izoh'] ?? '', 1000),
];

if ($t->xatolarBormi()) {
    return $this->javob->xato(422, $t->xatolar());
}
Tozalash emas, rad etish

Ba'zilar noto'g'ri ma'lumotni tozalab ishlatadi:

PHP
$nom = str_replace(['<', '>'], '', $_POST['nom']);   // Yomon

Bu ishonchsiz - hujumchi tozalashni chetlab o'tish yo'lini topadi (<<script>>, kodlash, Unicode).

To'g'ri yondashuv: rad eting. Ma'lumot talabga mos kelmasa, xato qaytaring.

CI da xavfsizlik tekshiruvlari #

YAML
# .github/workflows/xavfsizlik.yml
name: Xavfsizlik tekshiruvi

on:
  pull_request:
  push:
    branches: [asosiy]
  schedule:
    - cron: '0 3 * * 1'    # Haftalik - yangi CVE lar uchun

permissions:
  contents: read
  security-events: write

jobs:
  sirlar:
    name: Sirlarni qidirish
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0    # Butun tarix

      - name: Gitleaks
        uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  bogliqliklar:
    name: Bog'liqliklar (SCA)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'

      - name: Composer audit
        run: composer audit --format=plain

      - name: Trivy
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: fs
          severity: CRITICAL,HIGH
          exit-code: '1'
          ignore-unfixed: true

  statik:
    name: Statik tahlil (SAST)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
          tools: psalm

      - name: Psalm taxonomiya
        run: psalm --taint-analysis --report=psalm.sarif

      - name: Semgrep
        uses: returntocorp/semgrep-action@v1
        with:
          config: >-
            p/php
            p/security-audit
            p/owasp-top-ten
            p/secrets

      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: psalm.sarif

  konteyner:
    name: Konteyner obrazi
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Obraz yig'ish
        run: docker build -t dokon:sinov .

      - name: Trivy obraz skani
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: dokon:sinov
          severity: CRITICAL,HIGH
          exit-code: '1'

      - name: Dockerfile lint
        uses: hadolint/hadolint-action@v3
        with:
          dockerfile: Dockerfile

  testlar:
    name: Xavfsizlik testlari
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: composer install --no-interaction
      - run: vendor/bin/phpunit --testsuite=xavfsizlik
Psalm taint tahlili

--taint-analysis foydalanuvchi ma'lumoti (manba) xavfli funksiyaga (cho'kma) yetib borishini kuzatadi:

Natija
$_GET['id'] → $so'rov → $pdo->query()   ← XATO topildi

Bu oddiy naqsh qidirishdan ancha kuchli - u ma'lumot oqimini kuzatadi.

Xavfsizlik testlari #

PHP
final class XavfsizlikTesti extends TestCase
{
    public function test_sql_inyeksiya_ishlamaydi(): void
    {
        $zararli = [
            "1' OR '1'='1",
            "1; DROP TABLE mijozlar; --",
            "1 UNION SELECT parol_xesh FROM foydalanuvchilar",
            "1' AND SLEEP(5) --",
        ];

        foreach ($zararli as $kirish) {
            $javob = $this->soragan('GET', '/mahsulot?id=' . urlencode($kirish));

            $this->assertContains($javob->kodi(), [400, 404, 422]);
            $this->assertStringNotContainsStringIgnoringCase('sql', $javob->tanasi());
            $this->assertStringNotContainsStringIgnoringCase('syntax', $javob->tanasi());
        }

        // Jadval hali joyida
        $this->assertTrue($this->baza->jadvalBormi('mijozlar'));
    }

    public function test_xss_ekranlanadi(): void
    {
        $yuk = '<script>alert(1)</script>';

        $this->kiring('[email protected]');
        $this->soragan('POST', '/izoh', ['matn' => $yuk]);

        $javob = $this->soragan('GET', '/izohlar');

        $this->assertStringNotContainsString('<script>', $javob->tanasi());
        $this->assertStringContainsString('&lt;script&gt;', $javob->tanasi());
    }

    public function test_idor_bloklanadi(): void
    {
        $birinchi = $this->mijozYarating();
        $ikkinchi = $this->mijozYarating();

        $buyurtma = $this->buyurtmaYarating($ikkinchi->id);

        $this->kiring($birinchi->pochta);
        $javob = $this->soragan('GET', "/buyurtma/{$buyurtma->id}");

        $this->assertSame(404, $javob->kodi());
    }

    public function test_csrf_tokensiz_rad_etiladi(): void
    {
        $this->kiring('[email protected]');

        $javob = $this->soragan('POST', '/profil', ['ism' => 'Yangi'], csrf: false);

        $this->assertSame(419, $javob->kodi());
    }

    public function test_admin_yoliga_oddiy_foydalanuvchi_kira_olmaydi(): void
    {
        $this->kiring('[email protected]');

        foreach (['/admin', '/admin/foydalanuvchilar', '/admin/sozlamalar'] as $yol) {
            $this->assertSame(403, $this->soragan('GET', $yol)->kodi(), $yol);
        }
    }

    public function test_parol_xeshlangan_holda_saqlanadi(): void
    {
        $this->royxatdanOting('[email protected]', 'JudaKuchliParol123!');

        $xesh = $this->baza->qiymat(
            'SELECT parol_xesh FROM foydalanuvchilar WHERE pochta = :pochta',
            ['pochta' => '[email protected]']
        );

        $this->assertStringStartsWith('$argon2id$', $xesh);
        $this->assertTrue(password_verify('JudaKuchliParol123!', $xesh));
    }

    public function test_xavfsizlik_sarlavhalari_mavjud(): void
    {
        $javob = $this->soragan('GET', '/');

        $this->assertNotEmpty($javob->sarlavha('Content-Security-Policy'));
        $this->assertSame('nosniff', $javob->sarlavha('X-Content-Type-Options'));
        $this->assertStringContainsString('max-age=', $javob->sarlavha('Strict-Transport-Security'));
    }

    public function test_tezlik_cheklovi_ishlaydi(): void
    {
        for ($i = 0; $i < 6; $i++) {
            $javob = $this->soragan('POST', '/kirish', [
                'pochta' => '[email protected]',
                'parol' => 'notogri',
            ]);
        }

        $this->assertSame(429, $javob->kodi());
    }
}
Har bir zaiflik uchun test

Zaiflik topilganda:

  1. Uni ko'rsatadigan test yozing (test yiqiladi)
  2. Zaiflikni tuzating (test o'tadi)
  3. Test doim CI da ishlaydi

Shunday qilib bir marta tuzatilgan zaiflik qaytib kelmaydi.

Bog'liqliklar siyosati #

MARKDOWN
# Bog'liqliklar siyosati

## Yangi kutubxona qo'shishdan oldin
- [ ] Haqiqatan kerakmi? (25 qatorlik kod uchun kutubxona shart emas)
- [ ] Oxirgi yangilanish 12 oydan yaqinmi?
- [ ] Ochiq CVE bormi? (osv.dev da qidiring)
- [ ] Nechta o'z bog'liqligi bor? (kamroq - yaxshiroq)
- [ ] Litsenziya mos keladimi?
- [ ] Kim qo'llab-quvvatlaydi? (bitta odammi?)

## Muddatlar
| Jiddiylik | Yangilash muddati |
|-----------|-------------------|
| Kritik + ekspluatatsiya bor | 24 soat |
| Kritik | 7 kun |
| Yuqori | 30 kun |
| O'rta | 90 kun |
| Past | Keyingi rejalashtirilgan yangilanish |

## Versiyalar
- composer.lock **git da** bo'lsin
- Ishlab chiqarishda `composer install`, hech qachon `update`
- Renovate/Dependabot haftalik PR yaratadi

## Taqiqlangan
- Qo'llab-quvvatlanmaydigan kutubxonalar
- Nomi mashhur paketga o'xshash paketlar (typosquatting)
- To'g'ridan-to'g'ri git URL dan (versiya belgilanmagan)
JSON
{
    "extends": ["config:recommended"],
    "schedule": ["before 6am on monday"],
    "vulnerabilityAlerts": {
        "labels": ["xavfsizlik"],
        "schedule": ["at any time"],
        "automerge": false
    },
    "packageRules": [
        {
            "matchUpdateTypes": ["patch"],
            "matchCurrentVersion": "!/^0/",
            "automerge": true
        }
    ]
}

Kod ko'rigi ro'yxati #

Xavfsizlik ko'rigi

Har bir PR da tekshiring:

SavolNima qidiriladi
Yangi kirish nuqtasi bormi?Yangi marshrut, forma, API
Ma'lumot qayerdan keladi?$_GET, $_POST, sarlavha, fayl
U tekshirildimi?Tekshiruvchi qatlamidan o'tdimi
So'rov tayyorlanganmi?Birlashtirish yo'qmi
Chiqish ekranlanganmi?htmlspecialchars yoki shablon
Huquq tekshirildimi?Faqat autentifikatsiya emas, avtorizatsiya ham
Sir kodda bormi?Kalit, parol, token
Xato xabari nima oshkor qiladi?Yo'l, versiya, SQL
Jurnalga nima yoziladi?Parol, karta, token yozilmasin
Yangi bog'liqlik bormi?Siyosatga mos keladimi
Test yozilganmi?Salbiy holatlar ham
Terminal
# Tez qo'lda tekshiruv - PR dagi o'zgarishlar bo'yicha
git diff asosiy...HEAD -- '*.php' | grep -nE '^\+' | grep -E \
    'query\(|exec\(|eval\(|shell_exec|system\(|unserialize|\$_(GET|POST|REQUEST|COOKIE)'

Xavfsizlik yetakchilari #

Xavfsizlik yetakchisi modeli Xavfsizlik jamoasi 2-3 kishi Jamoa A yetakchisi Dasturchi, 20% vaqt Jamoa B yetakchisi Dasturchi, 20% vaqt Jamoa C yetakchisi Dasturchi, 20% vaqt Xavfsizlik jamoasi 3 kishi emas - 12 kishi kabi ishlaydi
Har bir jamoada xavfsizlikka mas'ul dasturchi bo'lsin
Yetakchi nima qiladi?
  • PR larda xavfsizlik ko'rigini o'tkazadi
  • Tahdid modeli sessiyalarini boshqaradi
  • Jamoaga yangi tahdidlarni yetkazadi
  • Xavfsizlik jamoasi bilan bog'lovchi
  • Oyiga bir marta xavfsizlik jamoasi bilan uchrashadi

Bu to'liq stavka emas - vaqtining 20% i. Lekin xavfsizlik madaniyatini butun tashkilotga tarqatadi.

Xavfsiz standart holat #

PHP
// Yomon: xavfsizlikni yoqish kerak
$sozlama = new Sozlama();
$sozlama->csrfYoqing();          // Unutilsa - zaiflik
$sozlama->xssHimoyasiniYoqing();

// Yaxshi: xavfsizlik standart, o'chirish ongli qaror
final class Sozlama
{
    private bool $csrf = true;
    private bool $xss = true;

    /** Faqat aniq sabab bilan o'chiring */
    public function csrfOchiring(string $sabab): self
    {
        // Sabab jurnalga yoziladi va ko'rikda ko'rinadi
        $this->jurnal->ogohlantirish('CSRF o\'chirildi', ['sabab' => $sabab]);
        $this->csrf = false;

        return $this;
    }
}
PHP
// Marshrutlar: standart holatda himoyalangan
final class Marshrut
{
    private array $himoyalar = ['auth', 'csrf', 'tezlik'];

    /** Ochiq sahifa - ongli qaror */
    public function ochiq(): self
    {
        $this->himoyalar = array_diff($this->himoyalar, ['auth']);

        return $this;
    }
}

// Ishlatish
$marshrutlar->get('/profil', [ProfilNazorat::class, 'korsating']);        // Himoyalangan
$marshrutlar->get('/', [BoshNazorat::class, 'korsating'])->ochiq();       // Ochiq (aniq)
Xavfsizlik standart holatda bo'lsin

Agar dasturchi bir narsani unutsa, natija xavfsiz bo'lishi kerak, zaif emas.

Bu prinsip "fail secure" deb ataladi va u insonni ishonchsiz bo'g'inligini tan oladi.

Ishga tushirishdan oldingi ro'yxat #

Ishga tushirish tekshiruvi
TalabBajarildi
display_errors = Off
Nosozliklarni tuzatish rejimi o'chirilgan
Standart parollar o'zgartirilgan
Sinov hisoblari o'chirilgan
.env, .git veb orqali ochilmaydi
Barcha sirlar muhit o'zgaruvchisida
HTTPS majburiy, HSTS yoqilgan
Xavfsizlik sarlavhalari o'rnatilgan
Tezlik cheklovi yoqilgan
Jurnal markazlashtirilgan
Zaxira sozlangan va sinovdan o'tgan
Bog'liqliklarda kritik CVE yo'q
SAST va SCA CI da o'tadi
Xavfsizlik testlari yashil
security.txt joylashtirilgan
Amaliy topshiriq
  1. Loyihangizdagi bitta funksiya uchun 5 ta suiiste'mol holati yozing.
  2. Shu funksiya uchun tahdid modelini tuzing.
  3. Xavfsiz kod standartini loyihangiz uchun yozing.
  4. Kirish tekshiruvi qatlamini amalga oshiring.
  5. CI ga Semgrep va sirlarni qidirish qo'shing.
  6. Composer audit ni CI da majburiy qiling.
  7. Beshta xavfsizlik testini yozing (SQL, XSS, IDOR, CSRF, huquq).
  8. Bog'liqliklar siyosatini hujjatlang.
  9. Kod ko'rigi ro'yxatini jamoangizga tarqating.
  10. Ishga tushirish tekshiruv ro'yxatini to'ldiring.

Xulosa #

  • Dizayn bosqichida topilgan zaiflik 100 marta arzon.
  • Xavfsizlik talablari funksional talablar bilan birga yoziladi.
  • Suiiste'mol holatlari - tahdid modelining eng oddiy shakli.
  • Kirish ma'lumotini tozalamang, rad eting.
  • Fayl yuklashda qayta kodlash eng kuchli himoya.
  • CI da: sirlar, SCA, SAST, konteyner skani, xavfsizlik testlari.
  • Har bir topilgan zaiflik uchun test yozing - qaytmasligi uchun.
  • Bog'liqliklar siyosati va yangilash muddatlarini belgilang.
  • Kod ko'rigida xavfsizlik ro'yxatidan foydalaning.
  • Har bir jamoada xavfsizlik yetakchisi bo'lsin.
  • Xavfsizlik standart holatda bo'lsin, qo'shimcha emas.

Keyingi bo'limda siyosat, muvofiqlik va boshqaruvni ko'ramiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.