20-bo‘lim
Amaliy loyiha - xavfsizlik auditi
Darslikda o'rganilgan bilimlarni birlashtirib, veb ilovaning to'liq xavfsizlik auditini o'tkazamiz va hisobot yozamiz.
Ushbu bo‘lim mundarijasi
- Loyiha shartlari
- Audit rejasi
- 1-bosqich: Qamrov
- 2-bosqich: Infratuzilma
- 3-bosqich: Ilova
- Qo'lda tekshirish: autentifikatsiya
- Qo'lda tekshirish: avtorizatsiya
- Qo'lda tekshirish: biznes mantiq
- 4-bosqich: Kod tahlili
- 5-bosqich: Jarayonlar
- 6-bosqich: Hisobot
- 7-bosqich: Qayta tekshirish
- Doimiy audit
- Darslik yakuni
- Xulosa
Endi hamma bilimni birlashtiramiz. Biz o'zimizning dokon.uz onlayn
do'konini to'liq audit qilamiz - infratuzilmadan kodgacha.
Loyiha shartlari #
Bu loyihani faqat o'zingizga tegishli yoki yozma ruxsat berilgan tizimda bajaring.
Amaliyot uchun xavfsiz muhitlar:
- Mahalliy virtual mashina (VirtualBox + Ubuntu)
- Docker konteynerlari
- OWASP Juice Shop, DVWA (ataylab zaif ilovalar)
- TryHackMe, HackTheBox, PortSwigger Web Security Academy
Boshqaning tizimini ruxsatsiz tekshirish - jinoyat.
# Sinov muhitini tayyorlash
mkdir -p ~/audit-laboratoriya && cd ~/audit-laboratoriya
# Zaif ilova - o'rganish uchun
docker run -d --name juice-shop -p 3000:3000 bkimminich/juice-shop
# O'z ilovangiz nusxasi
git clone https://github.com/foydalanuvchi/dokon.git
cd dokon
docker compose up -d
Audit rejasi #
1-bosqich: Qamrov #
# Audit qamrovi
**Tashkilot:** Dokon MChJ
**Sana:** 2026-09-15 dan 2026-09-25 gacha
**Auditor:** Ichki xavfsizlik jamoasi
## Qamrovda
| Aktiv | Manzil | Turi |
|-------|--------|------|
| Asosiy sayt | dokon.uz | Veb ilova |
| API | api.dokon.uz | REST API |
| Admin panel | admin.dokon.uz | Veb ilova |
| Statik fayllar | static.dokon.uz | CDN |
| Ma'lumotlar bazasi | 10.0.2.10 | MariaDB |
| Ilova serveri | 10.0.2.20 | Ubuntu 22.04 |
| Kod ombori | github.com/dokon/dokon | Git |
## Qamrovdan tashqarida
- To'lov provayderi tizimi (uchinchi tomon)
- Ofis tarmog'i
- Xodimlar noutbuklari
## Cheklovlar
- DoS testlari o'tkazilmaydi
- Ijtimoiy muhandislik o'tkazilmaydi
- Ishlab chiqarish bazasiga yozish operatsiyalari yo'q
- Test soatlari: 22:00 - 06:00
## Aloqa
- Auditor: @husanboy, +998 90 xxx
- Favqulodda to'xtatish: @aziz, +998 91 xxx
Og'zaki "ha, tekshirib ko'r" yetarli emas.
Yozma hujjatda bo'lishi kerak: nima, qachon, kim, qaysi usullar va kim ruxsat berdi.
Bu sizni ham, tashkilotni ham himoya qiladi.
2-bosqich: Infratuzilma #
#!/bin/bash
# infratuzilma-audit.sh
set -uo pipefail
MAQSAD="dokon.uz"
NATIJA="natijalar/infratuzilma"
mkdir -p "$NATIJA"
echo "===> 1. DNS yozuvlari"
{
dig +short "$MAQSAD" A
dig +short "$MAQSAD" AAAA
dig +short "$MAQSAD" MX
dig +short "$MAQSAD" TXT
dig +short "$MAQSAD" CAA
dig +short "_dmarc.$MAQSAD" TXT
} > "$NATIJA/dns.txt"
echo "===> 2. Ochiq portlar"
nmap -Pn -sV --top-ports 1000 "$MAQSAD" -oN "$NATIJA/portlar.txt"
echo "===> 3. TLS sozlamalari"
testssl.sh --quiet --color 0 "$MAQSAD" > "$NATIJA/tls.txt" 2>&1
echo "===> 4. Xavfsizlik sarlavhalari"
curl -sSI "https://$MAQSAD" > "$NATIJA/sarlavhalar.txt"
echo "===> 5. Subdomenlar"
curl -s "https://crt.sh/?q=%25.$MAQSAD&output=json" \
| python3 -c "import sys,json;[print(x['name_value']) for x in json.load(sys.stdin)]" \
| tr '\n' '\n' | sort -u > "$NATIJA/subdomenlar.txt"
echo "===> 6. Ochiq bo'lmasligi kerak bo'lgan yo'llar"
for yol in .git/config .env composer.json .DS_Store backup.sql \
phpinfo.php server-status .svn/entries web.config; do
KOD=$(curl -s -o /dev/null -w "%{http_code}" "https://$MAQSAD/$yol")
printf "%-24s %s\n" "$yol" "$KOD"
done | tee "$NATIJA/ochiq-yollar.txt"
echo "===> Tayyor. Natijalar: $NATIJA"
===> 6. Ochiq bo'lmasligi kerak bo'lgan yo'llar
.git/config 404
.env 404
composer.json 200 <-- MUAMMO
.DS_Store 404
backup.sql 404
phpinfo.php 404
server-status 403
.svn/entries 404
web.config 404
# Sarlavhalarni tekshirish
curl -sSI https://dokon.uz | grep -iE \
'strict-transport|content-security|x-frame|x-content-type|referrer-policy|permissions-policy|server|x-powered'
server: nginx/1.18.0 <-- versiya oshkor
x-powered-by: PHP/8.2.4 <-- versiya oshkor
strict-transport-security: max-age=31536000
x-content-type-options: nosniff
<-- CSP yo'q
<-- X-Frame-Options yo'q
# Tuzatish
server_tokens off;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'self'" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# Yashirin fayllarni to'sish
location ~ /\.(?!well-known) {
deny all;
return 404;
}
location ~ ^/(composer\.(json|lock)|package\.json|\.env) {
deny all;
return 404;
}
// PHP versiyasini yashirish - php.ini
// expose_php = Off
3-bosqich: Ilova #
# Yo'llarni aniqlash
gobuster dir \
-u https://dokon.uz \
-w /usr/share/wordlists/dirb/common.txt \
-x php,html,json,bak,old \
-t 20 \
--exclude-length 0 \
-o natijalar/yollar.txt
# ZAP avtomatik skan (o'z tizimingizda!)
docker run --rm -v "$(pwd)/natijalar:/zap/wrk" \
-t ghcr.io/zaproxy/zaproxy:stable \
zap-baseline.py \
-t https://sinov.dokon.uz \
-r zap-hisobot.html \
-w zap-ogohlantirish.md
Skanerlar quyidagilarni topa oladi:
- Ma'lum zaifliklar (CVE)
- Yo'q sarlavhalar
- Oddiy inyeksiya nuqtalari
Ular quyidagilarni topa olmaydi:
- Biznes mantiq xatolari
- IDOR (kontekstni bilmaydi)
- Huquqlarni oshirish yo'llari
- Narx manipulyatsiyasi
Shuning uchun qo'lda tekshirish majburiy.
Qo'lda tekshirish: autentifikatsiya #
# 1. Foydalanuvchi sanash - javob bir xilmi?
for pochta in [email protected] [email protected]; do
echo "--- $pochta"
curl -s -w "\nvaqt: %{time_total}s\n" \
-X POST https://dokon.uz/parolni-tiklash \
-d "pochta=$pochta"
done
--- [email protected]
{"xabar":"Havola yuborildi"}
vaqt: 0.412s
--- [email protected]
{"xabar":"Bunday foydalanuvchi topilmadi"} <-- MUAMMO
vaqt: 0.089s <-- vaqt farqi ham
// Tuzatish: bir xil javob va bir xil vaqt
public function parolniTiklang(string $pochta): Javob
{
$foydalanuvchi = $this->foydalanuvchilar->pochtaBoyicha($pochta);
if ($foydalanuvchi !== null) {
$this->tiklashXatiniYuboring($foydalanuvchi);
} else {
// Vaqt farqini yo'q qilamiz
$this->soxtaIshBajaring();
}
// Har doim bir xil javob
return $this->javob->ok([
'xabar' => 'Agar bunday hisob mavjud bo\'lsa, havola yuborildi',
]);
}
# 2. Tezlik cheklovi bormi?
for i in $(seq 1 15); do
KOD=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST https://dokon.uz/kirish \
-d "[email protected]&parol=notogri$i")
echo "$i: $KOD"
done
1: 401
2: 401
...
14: 401
15: 401 <-- MUAMMO: cheklov yo'q
// Tuzatish: ikki qatlamli cheklov
final class KirishCheklovi
{
public function tekshiring(string $pochta, string $ip): void
{
// Hisob bo'yicha - hisobni himoya qiladi
$hisobKaliti = 'kirish:hisob:' . hash('sha256', strtolower($pochta));
if ($this->kesh->soni($hisobKaliti) >= 5) {
$this->jurnal->ogohlantirish('kirish.hisob_bloklandi', [
'pochta' => $pochta, 'ip' => $ip,
]);
throw new JudaKopUrinish(900);
}
// IP bo'yicha - parol purkashdan himoya qiladi
$ipKaliti = 'kirish:ip:' . $ip;
if ($this->kesh->soni($ipKaliti) >= 30) {
throw new JudaKopUrinish(3600);
}
}
public function muvaffaqiyatsizlikniYozing(string $pochta, string $ip): void
{
$this->kesh->oshiring('kirish:hisob:' . hash('sha256', strtolower($pochta)), 900);
$this->kesh->oshiring('kirish:ip:' . $ip, 3600);
}
}
Faqat hisob bo'yicha cheklov: hujumchi 10 000 hisobga bittadan mashhur parolni sinaydi (parol purkash) - hech qaysi hisob bloklanmaydi.
Faqat IP bo'yicha cheklov: botnet 10 000 IP dan hujum qiladi - har bir IP chegaradan past qoladi.
Ikkalasi birga kerak.
Qo'lda tekshirish: avtorizatsiya #
# IDOR sinovi - matritsa usuli
# Ikki hisob yaratamiz va bir-birining resurslariga kirishga urinamiz
TOKEN_A="..." # birinchi mijoz
TOKEN_B="..." # ikkinchi mijoz
# B ning buyurtmasi
BUYURTMA_B=1042
for endpoint in \
"GET /api/buyurtma/$BUYURTMA_B" \
"PUT /api/buyurtma/$BUYURTMA_B" \
"DELETE /api/buyurtma/$BUYURTMA_B" \
"GET /api/buyurtma/$BUYURTMA_B/hujjat"
do
USUL=$(echo "$endpoint" | cut -d' ' -f1)
YOL=$(echo "$endpoint" | cut -d' ' -f2)
KOD=$(curl -s -o /dev/null -w "%{http_code}" \
-X "$USUL" \
-H "Authorization: Bearer $TOKEN_A" \
"https://api.dokon.uz$YOL")
printf "%-6s %-36s %s\n" "$USUL" "$YOL" "$KOD"
done
GET /api/buyurtma/1042 403
PUT /api/buyurtma/1042 403
DELETE /api/buyurtma/1042 403
GET /api/buyurtma/1042/hujjat 200 <-- MUAMMO
Bu juda tipik holat: asosiy endpointlar himoyalangan, lekin qo'shimcha yo'l (hujjat yuklab olish, eksport, chop etish) tekshiruvsiz qolgan.
Shuning uchun matritsa usuli kerak: har bir resurs uchun barcha yo'llarni sinang.
// Tuzatish: markazlashgan huquq tekshiruvi
abstract class BuyurtmaNazorat extends Nazorat
{
/**
* Har bir amal shu metod orqali buyurtmani oladi.
* Huquqni chetlab o'tishning iloji yo'q.
*/
protected function buyurtmaniOling(int $id): Buyurtma
{
$buyurtma = $this->buyurtmalar->id($id);
if ($buyurtma === null) {
throw new TopilmadiXatosi();
}
if (!$this->ruxsat->koraOladi($this->joriyFoydalanuvchi(), $buyurtma)) {
// 404 qaytaramiz - mavjudligini oshkor qilmaslik uchun
throw new TopilmadiXatosi();
}
return $buyurtma;
}
}
// Test - har bir yo'l uchun
public function test_barcha_buyurtma_yollari_himoyalangan(): void
{
$birinchi = $this->mijozYarating();
$ikkinchi = $this->mijozYarating();
$buyurtma = $this->buyurtmaYarating($ikkinchi->id);
$this->kiring($birinchi->pochta);
$yollar = [
['GET', "/api/buyurtma/{$buyurtma->id}"],
['PUT', "/api/buyurtma/{$buyurtma->id}"],
['DELETE', "/api/buyurtma/{$buyurtma->id}"],
['GET', "/api/buyurtma/{$buyurtma->id}/hujjat"],
['GET', "/api/buyurtma/{$buyurtma->id}/tolovlar"],
['POST', "/api/buyurtma/{$buyurtma->id}/bekor"],
];
foreach ($yollar as [$usul, $yol]) {
$javob = $this->soragan($usul, $yol);
$this->assertSame(404, $javob->kodi(), "$usul $yol himoyalanmagan");
}
}
Qo'lda tekshirish: biznes mantiq #
# 1. Manfiy miqdor
curl -X POST https://api.dokon.uz/savat \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"mahsulot_id": 10, "miqdor": -5}'
{"jami": -450000, "holat": "qoshildi"} <-- MUAMMO
# 2. Narxni mijoz yuboradi
curl -X POST https://api.dokon.uz/buyurtma \
-H "Authorization: Bearer $TOKEN" \
-d '{"mahsulot_id": 10, "miqdor": 1, "narx": 1}'
{"buyurtma_id": 1099, "jami": 1} <-- MUAMMO
# 3. Chegirma kodini takroran ishlatish (poyga holati)
for i in $(seq 1 10); do
curl -s -X POST https://api.dokon.uz/savat/chegirma \
-H "Authorization: Bearer $TOKEN" \
-d '{"kod": "YANGI50"}' &
done
wait
{"chegirma": 50, "jami": 225000}
{"chegirma": 50, "jami": 112500}
{"chegirma": 50, "jami": 56250} <-- MUAMMO: takror qo'llandi
// Tuzatish
final class SavatXizmati
{
public function qoshing(int $mahsulotId, int $miqdor): void
{
// 1. Miqdor chegarasi
if ($miqdor < 1 || $miqdor > 100) {
throw new NotogriMiqdor('Miqdor 1 va 100 orasida bo\'lsin');
}
// 2. Narx faqat serverdan olinadi
$mahsulot = $this->mahsulotlar->id($mahsulotId);
if ($mahsulot === null || !$mahsulot->faol) {
throw new TopilmadiXatosi();
}
// 3. Ombordagi qoldiq tekshiriladi
if ($mahsulot->qoldiq < $miqdor) {
throw new YetarliEmas("Omborda faqat {$mahsulot->qoldiq} dona");
}
$this->savat->qoshing($mahsulotId, $miqdor, $mahsulot->narx);
}
public function chegirmaQollang(string $kod): void
{
// Poyga holatidan himoya - bazada blok
$this->baza->tranzaksiya(function () use ($kod) {
$chegirma = $this->baza->qator(
'SELECT * FROM chegirmalar WHERE kod = :kod FOR UPDATE',
['kod' => $kod]
);
if ($chegirma === null || $chegirma['ishlatilgan'] >= $chegirma['limit']) {
throw new NotogriChegirma('Kod yaroqsiz');
}
// Bitta savatga faqat bitta chegirma
if ($this->savat->chegirmaBormi()) {
throw new NotogriChegirma('Chegirma allaqachon qo\'llangan');
}
$this->baza->bajaring(
'UPDATE chegirmalar SET ishlatilgan = ishlatilgan + 1 WHERE id = :id',
['id' => $chegirma['id']]
);
$this->savat->chegirmaOrnating($chegirma);
});
}
}
Mijoz yuboradigan yagona narsa - mahsulot identifikatori va miqdor.
Narx, chegirma, soliq, yetkazib berish narxi - hammasi serverda hisoblanadi.
Bu qoida buzilgan holat - onlayn do'konlardagi eng ko'p uchraydigan va eng qimmat zaiflik.
4-bosqich: Kod tahlili #
#!/bin/bash
# kod-audit.sh
set -uo pipefail
mkdir -p natijalar/kod
echo "===> 1. Sirlarni qidirish (butun tarix)"
gitleaks detect --source . --report-path natijalar/kod/sirlar.json --verbose
echo "===> 2. Bog'liqliklar"
composer audit --format=json > natijalar/kod/bogliqliklar.json || true
npm audit --json > natijalar/kod/npm.json 2>/dev/null || true
echo "===> 3. Statik tahlil"
semgrep --config=p/php --config=p/security-audit --config=p/owasp-top-ten \
--json --output=natijalar/kod/semgrep.json .
echo "===> 4. Xavfli naqshlar"
{
echo "--- SQL birlashtirish"
grep -rnE '(query|exec)\s*\(\s*["'"'"'].*\$' --include='*.php' . || echo "yo'q"
echo "--- Kod bajarish"
grep -rnE '\b(eval|assert|create_function|preg_replace\s*\(.*/e)' --include='*.php' . || echo "yo'q"
echo "--- Tashqi buyruq"
grep -rnE '\b(shell_exec|system|passthru|proc_open|popen)\s*\(' --include='*.php' . || echo "yo'q"
echo "--- Deserializatsiya"
grep -rn 'unserialize(' --include='*.php' . || echo "yo'q"
echo "--- Zaif tasodifiylik"
grep -rnE '\b(mt_rand|rand|uniqid)\s*\(' --include='*.php' . || echo "yo'q"
echo "--- Ekranlanmagan chiqish"
grep -rnE '<\?=\s*\$(_GET|_POST|_REQUEST)' --include='*.php' . || echo "yo'q"
echo "--- Kodda sir"
grep -rniE '(parol|password|api_key|secret|token)\s*=\s*["'"'"'][^"'"'"']{8,}' \
--include='*.php' --exclude-dir=vendor . || echo "yo'q"
} > natijalar/kod/naqshlar.txt
echo "===> 5. Fayl huquqlari"
find . -type f -perm -o+w -not -path './.git/*' > natijalar/kod/yozilishi-mumkin.txt
echo "===> Tayyor"
===> 4. Xavfli naqshlar
--- SQL birlashtirish
./app/Hisobot/EksportXizmati.php:88: $qatorlar = $pdo->query("SELECT * FROM buyurtmalar WHERE sana >= '$boshlanish'");
--- Zaif tasodifiylik
./app/Auth/TiklashToken.php:24: return md5(uniqid(mt_rand(), true));
--- Kodda sir
./config/tolov.php:12: 'kalit' => 'sk_live_4f8a2b9c1d3e5f7a',
// TiklashToken.php - oldingi (zaif)
public function yarating(): string
{
return md5(uniqid(mt_rand(), true));
}
uniqid() - joriy vaqtga asoslangan, tasodifiy emas.
mt_rand() - Mersenne Twister, kriptografik emas; bir necha
natijadan keyingi qiymatlarni hisoblash mumkin.
md5() - buzilgan xesh funksiyasi.
Natijada tiklash tokenini taxmin qilish mumkin: hujumchi istalgan foydalanuvchi parolini tiklaydi.
// Tuzatilgan
final class TiklashToken
{
private const UZUNLIK = 32;
private const MUDDAT = 1800; // 30 daqiqa
public function yarating(int $foydalanuvchiId): string
{
// Eski tokenlarni bekor qilamiz
$this->baza->bajaring(
'DELETE FROM tiklash_tokenlari WHERE foydalanuvchi_id = :fid',
['fid' => $foydalanuvchiId]
);
$ochiq = bin2hex(random_bytes(self::UZUNLIK));
// Bazada faqat xesh saqlanadi
$this->baza->bajaring(
'INSERT INTO tiklash_tokenlari (foydalanuvchi_id, token_xesh, eskiradi)
VALUES (:fid, :xesh, :eskiradi)',
[
'fid' => $foydalanuvchiId,
'xesh' => hash('sha256', $ochiq),
'eskiradi' => date('Y-m-d H:i:s', time() + self::MUDDAT),
]
);
return $ochiq;
}
public function tekshiring(string $token): ?int
{
$qator = $this->baza->qator(
'SELECT foydalanuvchi_id FROM tiklash_tokenlari
WHERE token_xesh = :xesh AND eskiradi > NOW()',
['xesh' => hash('sha256', $token)]
);
return $qator === null ? null : (int) $qator['foydalanuvchi_id'];
}
}
# Kodda topilgan sir - darhol bekor qiling
# 1. To'lov provayderi panelida kalitni bekor qilish
# 2. Yangi kalit yaratish
# 3. Muhit o'zgaruvchisiga ko'chirish
# 4. Git tarixidan tozalash
git filter-repo --path config/tolov.php --invert-paths
# yoki
bfg --replace-text sirlar.txt
Kalit git tarixida bo'lgan bo'lsa, u:
- Klonlarda qolgan
- Fork larda qolgan
- CI keshida qolgan
- Ehtimol allaqachon skanerlangan
Birinchi qadam har doim: kalitni bekor qilish. Tarixni tozalash - ikkinchi qadam.
5-bosqich: Jarayonlar #
| Savol | Tekshirish usuli |
|---|---|
| Zaxira ishlaydimi? | Tiklash sinovini o'tkazing |
| Jurnal yig'iladimi? | Sinov hodisasini yarating va qidiring |
| Ogohlantirish keladimi? | 10 marta noto'g'ri kirish qiling |
| Ketgan xodim kirishi o'chirilganmi? | Hisoblarni HR ro'yxati bilan solishtiring |
| Yamoqlar o'rnatilganmi? | apt list --upgradable |
| Kim admin? | Huquqlar ro'yxatini chiqaring |
# Faol hisoblar va HR ro'yxatini solishtirish
mysql -N -e "
SELECT pochta FROM dokon.foydalanuvchilar
WHERE rol IN ('admin', 'moderator') AND holat = 'faol'
ORDER BY pochta;" | sort > /tmp/tizim.txt
sort /tmp/hr-xodimlar.txt > /tmp/hr.txt
echo "=== Tizimda bor, HR da yo'q (TEKSHIRING!) ==="
comm -23 /tmp/tizim.txt /tmp/hr.txt
echo "=== HR da bor, tizimda yo'q (normal) ==="
comm -13 /tmp/tizim.txt /tmp/hr.txt
=== Tizimda bor, HR da yo'q (TEKSHIRING!) ===
[email protected] <-- 4 oy oldin ketgan
[email protected] <-- sinov hisobi, o'chirilmagan
[email protected] <-- xizmat hisobi (normal, hujjatlansin)
# Oxirgi 90 kun ichida kirmagan hisoblar
mysql -e "
SELECT pochta, rol, oxirgi_kirish,
DATEDIFF(NOW(), oxirgi_kirish) AS kun
FROM dokon.foydalanuvchilar
WHERE holat = 'faol'
AND (oxirgi_kirish < DATE_SUB(NOW(), INTERVAL 90 DAY) OR oxirgi_kirish IS NULL)
ORDER BY oxirgi_kirish;"
6-bosqich: Hisobot #
# Xavfsizlik auditi hisoboti - dokon.uz
**Sana:** 2026-09-25
**Auditor:** Ichki xavfsizlik jamoasi
**Qamrov:** Veb ilova, API, infratuzilma, kod, jarayonlar
---
## Rahbariyat uchun xulosa
Auditda **14 ta** topilma aniqlandi: 2 ta kritik, 4 ta yuqori,
5 ta o'rta, 3 ta past.
**Eng jiddiy xatar:** parolni tiklash tokeni taxmin qilinadigan
algoritm bilan yaratiladi. Bu hujumchiga istalgan hisobni, shu
jumladan administrator hisobini egallash imkonini beradi.
**Ikkinchi kritik topilma:** to'lov provayderi kaliti kod omborida
ochiq saqlanadi. Kalit bekor qilindi va almashtirildi (24-sentabr).
Kritik topilmalar **7 kun** ichida, yuqori darajadagilar **30 kun**
ichida tuzatilishi tavsiya etiladi.
---
## Topilmalar
| ID | Topilma | Jiddiylik | Holat |
|----|---------|:---------:|-------|
| T-01 | Taxmin qilinadigan parol tiklash tokeni | Kritik | Ochiq |
| T-02 | To'lov kaliti kod omborida | Kritik | Tuzatildi |
| T-03 | Buyurtma hujjatida IDOR | Yuqori | Ochiq |
| T-04 | Narx mijoz so'rovidan olinadi | Yuqori | Ochiq |
| T-05 | Kirishda tezlik cheklovi yo'q | Yuqori | Ochiq |
| T-06 | Chegirma kodida poyga holati | Yuqori | Ochiq |
| T-07 | SQL birlashtirish (eksport moduli) | O'rta | Ochiq |
| T-08 | CSP sarlavhasi yo'q | O'rta | Ochiq |
| T-09 | Foydalanuvchi sanash mumkin | O'rta | Ochiq |
| T-10 | Ketgan xodim hisobi faol | O'rta | Ochiq |
| T-11 | composer.json ochiq | O'rta | Ochiq |
| T-12 | Server versiyasi oshkor | Past | Ochiq |
| T-13 | Manfiy miqdor qabul qilinadi | Past | Ochiq |
| T-14 | Zaxira tiklash sinovi o'tkazilmagan | Past | Ochiq |
---
## T-01: Taxmin qilinadigan parol tiklash tokeni
**Jiddiylik:** Kritik (CVSS 9.1)
**Joy:** `app/Auth/TiklashToken.php:24`
**Turi:** CWE-338, Kriptografik jihatdan zaif generator
### Tavsif
Tiklash tokeni `md5(uniqid(mt_rand(), true))` orqali yaratiladi.
Bu uch komponentning hech biri kriptografik xavfsiz emas:
`uniqid()` joriy vaqtga asoslangan, `mt_rand()` oldindan aytish
mumkin bo'lgan generator, `md5()` buzilgan xesh.
### Ta'siri
Hujumchi bir nechta tokenni kuzatib, generator holatini tiklaydi
va istalgan foydalanuvchi uchun amal qiladigan token yaratadi.
Bu to'liq hisob egallashga olib keladi - shu jumladan
administrator hisobiga.
### Takrorlash
1. Ikkita hisob yarating
2. Ikkalasi uchun ham tiklashni so'rang
3. Tokenlarni solishtiring - vaqtga bog'liq naqsh ko'rinadi
### Tavsiya
Tokenni kriptografik generator bilan yarating:
$token = bin2hex(random_bytes(32));
Qo'shimcha: tokenni bazada **xeshlab** saqlang, 30 daqiqada
eskirtiring, bir marta ishlating.
### Muddat
7 kun (2026-10-02)
### Mas'ul
@aziz
---
## Ustuvorlik rejasi
### Hafta 1 (kritik)
- [ ] T-01: Token generatorini almashtirish
- [x] T-02: Kalitni bekor qilish va ko'chirish
### Hafta 2-4 (yuqori)
- [ ] T-03: Barcha buyurtma yo'llariga huquq tekshiruvi
- [ ] T-04: Narxni serverda hisoblash
- [ ] T-05: Ikki qatlamli tezlik cheklovi
- [ ] T-06: Chegirmani tranzaksiya ichida qo'llash
### Oy 2-3 (o'rta va past)
- [ ] T-07 dan T-14 gacha
### Har bir tuzatish uchun
- [ ] Zaiflikni ko'rsatuvchi test yozilgan
- [ ] Tuzatish amalga oshirilgan
- [ ] Test CI da o'tadi
- [ ] Qayta tekshirish o'tkazilgan
7-bosqich: Qayta tekshirish #
// Har bir topilma uchun regressiya testi
final class AuditRegressiyaTesti extends TestCase
{
/** T-01: Token kriptografik xavfsiz bo'lsin */
public function test_t01_tiklash_tokeni_tasodifiy(): void
{
$tokenlar = [];
for ($i = 0; $i < 100; $i++) {
$tokenlar[] = (new TiklashToken($this->baza))->yarating($i + 1);
}
// Barchasi noyob
$this->assertCount(100, array_unique($tokenlar));
// Uzunlik yetarli
foreach ($tokenlar as $token) {
$this->assertSame(64, strlen($token));
$this->assertMatchesRegularExpression('/^[0-9a-f]{64}$/', $token);
}
// Ochiq token bazada saqlanmaydi
$bazadagi = $this->baza->qiymat('SELECT token_xesh FROM tiklash_tokenlari LIMIT 1');
$this->assertNotContains($bazadagi, $tokenlar);
}
/** T-04: Narx mijozdan olinmaydi */
public function test_t04_narx_serverda_hisoblanadi(): void
{
$mahsulot = $this->mahsulotYarating(narx: 450000);
$this->kiring('[email protected]');
$javob = $this->soragan('POST', '/api/savat', [
'mahsulot_id' => $mahsulot->id,
'miqdor' => 2,
'narx' => 1, // Hujumchi urinishi
]);
$this->assertSame(900000, $javob->json('jami'));
}
/** T-05: Tezlik cheklovi ishlaydi */
public function test_t05_kirishda_cheklov(): void
{
for ($i = 1; $i <= 6; $i++) {
$javob = $this->soragan('POST', '/kirish', [
'pochta' => '[email protected]',
'parol' => "notogri$i",
]);
}
$this->assertSame(429, $javob->kodi());
$this->assertNotEmpty($javob->sarlavha('Retry-After'));
}
/** T-06: Chegirma bir marta qo'llanadi */
public function test_t06_chegirma_takrorlanmaydi(): void
{
$this->chegirmaYarating('YANGI50', foiz: 50, limit: 1);
$this->kiring('[email protected]');
$this->savatgaQoshing(mahsulotId: 1, miqdor: 1);
$birinchi = $this->soragan('POST', '/api/savat/chegirma', ['kod' => 'YANGI50']);
$ikkinchi = $this->soragan('POST', '/api/savat/chegirma', ['kod' => 'YANGI50']);
$this->assertSame(200, $birinchi->kodi());
$this->assertSame(422, $ikkinchi->kodi());
}
/** T-13: Manfiy miqdor rad etiladi */
public function test_t13_manfiy_miqdor(): void
{
$this->kiring('[email protected]');
foreach ([-5, 0, 101, 999999] as $miqdor) {
$javob = $this->soragan('POST', '/api/savat', [
'mahsulot_id' => 1,
'miqdor' => $miqdor,
]);
$this->assertSame(422, $javob->kodi(), "Miqdor: $miqdor");
}
}
}
# Qayta tekshirish
composer test -- --testsuite=audit-regressiya
# Infratuzilmani qayta skanerlash
./infratuzilma-audit.sh
# Sarlavhalarni tekshirish
curl -sSI https://dokon.uz | grep -i content-security-policy
PHPUnit 10.5.0
......... 9 / 9 (100%)
OK (9 tests, 34 assertions)
content-security-policy: default-src 'self'; script-src 'self'; ...
Doimiy audit #
# .github/workflows/haftalik-audit.yml
name: Haftalik xavfsizlik auditi
on:
schedule:
- cron: '0 4 * * 1'
workflow_dispatch:
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Sirlar
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Bog'liqliklar
run: composer audit
- name: Statik tahlil
uses: returntocorp/semgrep-action@v1
with:
config: p/security-audit
- name: Sarlavhalar
run: |
SARLAVHALAR=$(curl -sSI https://dokon.uz)
for s in content-security-policy strict-transport-security \
x-content-type-options x-frame-options; do
if ! echo "$SARLAVHALAR" | grep -qi "^$s"; then
echo "::error::Sarlavha yo'q: $s"
exit 1
fi
done
- name: Regressiya testlari
run: composer test -- --testsuite=audit-regressiya
- name: Natijani xabar qilish
if: failure()
run: |
curl -X POST "$SLACK_URL" \
-d '{"text":"Haftalik audit muvaffaqiyatsiz tugadi"}'
env:
SLACK_URL: ${{ secrets.SLACK_XAVFSIZLIK }}
Bir marta o'tkazilgan audit bir kunlik suratni beradi.
Ertaga:
- Yangi kod yoziladi
- Yangi CVE e'lon qilinadi
- Yangi xodim qo'shiladi
- Yangi bog'liqlik o'rnatiladi
Shuning uchun auditning katta qismini avtomatlashtiring va har hafta ishga tushiring. Qo'lda audit yiliga 1-2 marta, avtomatik audit - har hafta.
Darslik yakuni #
Amaliyot:
- PortSwigger Web Security Academy (bepul, juda sifatli)
- TryHackMe - boshlang'ich uchun qulay yo'llar
- HackTheBox - qiyinroq mashqlar
- OverTheWire - Linux va tarmoq asoslari
- CTF musobaqalari
O'qish:
- OWASP Cheat Sheet Series
- NIST maxsus nashrlari (SP 800 seriyasi)
- CIS Benchmarks
- Zaiflik hisobotlari (HackerOne Hacktivity)
Sertifikatlar:
- CompTIA Security+ - asos
- eJPT, PNPT - amaliy pentest
- OSCP - jiddiy amaliy sertifikat
- CISSP - boshqaruv yo'nalishi
Eng muhimi: o'z loyihangizni himoyalang. Nazariya amaliyotsiz tez unutiladi.
- Sinov muhitini tayyorlang (Docker yoki VM).
- Audit qamrovi hujjatini yozing.
- Infratuzilma audit skriptini ishga tushiring.
- Xavfsizlik sarlavhalarini tekshiring va tuzating.
- Autentifikatsiyani qo'lda sinang (sanash, cheklov).
- IDOR matritsasini tuzing va barcha yo'llarni sinang.
- Biznes mantiqni sinang (narx, miqdor, chegirma).
- Kod tahlilini o'tkazing (sirlar, SAST, naqshlar).
- Jarayonlarni tekshiring (hisoblar, zaxira, jurnal).
- To'liq hisobot yozing: topilma, jiddiylik, tavsiya, muddat.
- Har bir topilma uchun regressiya testi yozing.
- Haftalik avtomatik auditni CI ga qo'shing.
Xulosa #
- Audit qamrovni yozma tasdiqlashdan boshlanadi.
- Bosqichlar: infratuzilma → ilova → kod → jarayon → hisobot.
- Avtomatik skaner yetarli emas - biznes mantiq faqat qo'lda topiladi.
- IDOR ni matritsa usuli bilan qidiring: har resurs, har yo'l.
- Eng ko'p uchraydigan xato: narxni mijozdan olish.
- Poyga holatini
FOR UPDATEva tranzaksiya bilan yoping. - Kodda topilgan sir - avval bekor qiling, keyin tarixni tozalang.
- Jarayon auditi: hisoblar, zaxira, jurnal, yamoqlar.
- Hisobot rahbariyat uchun xulosa bilan boshlansin.
- Har bir topilma uchun regressiya testi yozing.
- Auditning katta qismini avtomatlashtiring va haftalik ishga tushiring.
- Kiberxavfsizlik - bir marta bajariladigan ish emas, doimiy jarayon.
Darslik tugadi. Endi bilimni amalda qo'llang - va har doim faqat o'z tizimingizda yoki yozma ruxsat bilan ishlang.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
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.