18-bo‘lim
Xavfsizlik va ishonchlilik
OWASP Top 10, xavfsiz kod yozish, sirlarni boshqarish, xatolarga chidamlilik va ishonchlilik naqshlari.
Ushbu bo‘lim mundarijasi
- Xavfsizlik prinsiplari
- OWASP Top 10
- 1. Kirish nazorati buzilishi
- 2. Kriptografik nosozliklar
- 3. Inyeksiya
- 4. Xavfsiz bo'lmagan dizayn
- 5. Noto'g'ri sozlama
- 6. Zaif komponentalar
- 7. Autentifikatsiya nosozliklari
- 8. Ma'lumot yaxlitligi nosozliklari
- 9. Jurnal va monitoring yetishmasligi
- 10. SSRF
- Sirlarni boshqarish
- Ishonchlilik naqshlari
- Qayta urinish
- Vaqt chegarasi
- Yuk to'kish
- Xatolarga chidamlilik
- Xavfsizlik tekshiruv ro'yxati
- Fayl yuklash
- Xulosa
Xavfsizlik - alohida bosqich emas, u har bir qarorning qismi. Ishonchlilik ham xuddi shunday: tizim nosozlikka tayyor bo'lishi kerak.
Xavfsizlik prinsiplari #
OWASP Top 10 #
1. Kirish nazorati buzilishi #
// XAVFLI: foydalanuvchi boshqaning buyurtmasini ko'ra oladi
public function korsating(int $id): Buyurtma
{
return $this->repozitoriy->toping($id);
}
GET /api/buyurtmalar/1043 ← boshqa mijozning buyurtmasi
// XAVFSIZ
public function korsating(int $id, Foydalanuvchi $joriy): Buyurtma
{
$buyurtma = $this->repozitoriy->toping($id)
?? throw new TopilmadiIstisnosi();
if (!$this->ruxsat->korishiMumkinmi($joriy, $buyurtma)) {
throw new RuxsatYoq();
}
return $buyurtma;
}
Insecure Direct Object Reference - identifikatorni o'zgartirib, boshqaning ma'lumotini ko'rish.
Har bir resurs uchun so'rang: "bu foydalanuvchi shu ma'lumotni ko'rishga haqlimi?"
Tekshiruvni markazlashtiring - har bir kontrollerda takrorlash xavfli.
// Markazlashtirilgan huquq siyosati
final class BuyurtmaSiyosati
{
public function korishiMumkinmi(Foydalanuvchi $f, Buyurtma $b): bool
{
return $f->id === $b->mijozId
|| $f->rolBormi(Rol::Admin)
|| $f->rolBormi(Rol::Operator);
}
public function bekorQilaOladimi(Foydalanuvchi $f, Buyurtma $b): bool
{
if (!$this->korishiMumkinmi($f, $b)) {
return false;
}
return $b->holat()->bekorQilishMumkinmi();
}
}
2. Kriptografik nosozliklar #
// XAVFLI
$xesh = md5($parol);
$xesh = sha1($parol);
$xesh = hash('sha256', $parol);
// XAVFSIZ
$xesh = password_hash($parol, PASSWORD_DEFAULT);
if (password_verify($parol, $xesh)) {
if (password_needs_rehash($xesh, PASSWORD_DEFAULT)) {
$yangiXesh = password_hash($parol, PASSWORD_DEFAULT);
$this->foydalanuvchilar->parolYangilang($id, $yangiXesh);
}
}
SHA-256 tez ishlash uchun yaratilgan - videokartada soniyasiga milliardlab xesh hisoblanadi.
Parol uchun ataylab sekin algoritm kerak: bcrypt, argon2,
scrypt. Ular tuz qo'shadi va hisoblash narxini oshiradi.
// Maxfiy ma'lumotni shifrlash
final class Shifrlovchi
{
public function __construct(private string $kalit) {}
public function shifrlang(string $matn): string
{
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$shifr = sodium_crypto_secretbox($matn, $nonce, $this->kalit);
return base64_encode($nonce . $shifr);
}
public function ochiring(string $shifrlangan): string
{
$malumot = base64_decode($shifrlangan, true)
?: throw new ShifrlashXatosi('Noto\'g\'ri format');
$nonce = substr($malumot, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$shifr = substr($malumot, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
return sodium_crypto_secretbox_open($shifr, $nonce, $this->kalit)
?: throw new ShifrlashXatosi('Ochib bo\'lmadi');
}
}
// HECH QACHON
function shifrlash(string $matn, string $kalit): string
{
$natija = '';
for ($i = 0; $i < strlen($matn); $i++) {
$natija .= chr(ord($matn[$i]) ^ ord($kalit[$i % strlen($kalit)]));
}
return $natija;
}
Kriptografiya - o'nlab yillik tadqiqot sohasi. Sinovdan o'tgan
kutubxonalarni ishlating: libsodium, OpenSSL.
3. Inyeksiya #
// SQL inyeksiya
$sql = "SELECT * FROM mahsulotlar WHERE nomi = '{$_GET['q']}'";
// XAVFSIZ
$stmt = $pdo->prepare('SELECT * FROM mahsulotlar WHERE nomi = ?');
$stmt->execute([$_GET['q']]);
// Buyruq inyeksiyasi
system("convert {$fayl} -resize 200x200 {$natija}");
// XAVFSIZ
$jarayon = new Process(['convert', $fayl, '-resize', '200x200', $natija]);
$jarayon->run();
// XSS
echo "<div>Salom, {$foydalanuvchi->ism}!</div>";
// XAVFSIZ
echo '<div>Salom, ' . htmlspecialchars($foydalanuvchi->ism, ENT_QUOTES, 'UTF-8') . '!</div>';
| Kontekst | Usul |
|---|---|
| HTML matn | htmlspecialchars() |
| HTML atribut | htmlspecialchars() + qo'shtirnoq |
| JavaScript | json_encode() |
| URL | urlencode() |
| CSS | Umuman foydalanuvchi ma'lumotini qo'ymang |
// JavaScript ichida
echo '<script>const ism = ' . json_encode($ism, JSON_HEX_TAG | JSON_HEX_AMP) . ';</script>';
// Shablon dvigateli avtomatik qochiradi
// Twig
{{ foydalanuvchi.ism }} {# avtomatik qochiriladi #}
{{ matn|raw }} {# ehtiyot bo'ling! #}
4. Xavfsiz bo'lmagan dizayn #
// Xavfsiz bo'lmagan dizayn: parolni tiklash tokeni bashorat qilinadi
$token = md5($foydalanuvchi->email . time());
// XAVFSIZ
$token = bin2hex(random_bytes(32));
$xesh = hash('sha256', $token);
$this->repozitoriy->tokenSaqlang($foydalanuvchi->id, $xesh, '+1 hour');
// Foydalanuvchiga $token yuboriladi, bazada $xesh saqlanadi
Yangi imkoniyat loyihalayotganda so'rang:
- Nimani himoya qilamiz? (ma'lumot, pul, obro')
- Kimdan? (tashqi hujumchi, ichki foydalanuvchi, bot)
- Qanday hujum mumkin? (STRIDE modeli)
- Qanday to'samiz?
- Qolgan xavf qabul qilinadimi?
STRIDE: Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege.
5. Noto'g'ri sozlama #
// Ishlab chiqarish sozlamalari
ini_set('display_errors', '0');
ini_set('log_errors', '1');
error_reporting(E_ALL);
// Sessiya
ini_set('session.cookie_httponly', '1');
ini_set('session.cookie_secure', '1');
ini_set('session.cookie_samesite', 'Lax');
ini_set('session.use_strict_mode', '1');
# Xavfsizlik sarlavhalari
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none'" always;
# Server ma'lumotini yashirish
server_tokens off;
# Maxfiy fayllarga kirishni to'sish
location ~ /\.(env|git|htaccess) {
deny all;
return 404;
}
| Xato | To'g'ri |
|---|---|
Admin panel /admin standart parol bilan | Kuchli parol + 2FA |
Baza root foydalanuvchisi ilova uchun | Cheklangan huquqli foydalanuvchi |
| Xatolar ekranda ko'rsatiladi | Jurnalga yoziladi |
| Katalog ro'yxati yoqilgan | O'chirilgan |
| Ishlab chiqish vositalari prod da | Olib tashlangan |
6. Zaif komponentalar #
composer audit
npm audit
Found 3 security vulnerability advisories affecting 2 packages:
Package: guzzlehttp/guzzle
Severity: high
CVE: CVE-2026-1234
Affected: >=7.0.0,<7.8.2
Title: Cookie headers leaked on cross-domain redirect
Package: symfony/http-kernel
Severity: medium
CVE: CVE-2026-5678
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 5
labels: ["bogliqliklar", "xavfsizlik"]
Zamonaviy loyihada kodning 80-90% - tashqi kutubxonalar.
Har bir kutubxona:
- O'z zaifliklariga ega bo'lishi mumkin
- O'z bog'liqliklarini olib keladi
- Egasi almashishi mumkin
Qoidalar:
- Yangi kutubxona qo'shishdan oldin o'ylang - kerakmi?
composer.lockni Git ga kiriting- Muntazam audit qiling
- Ishlatilmagan bog'liqliklarni olib tashlang
7. Autentifikatsiya nosozliklari #
final class KirishServisi
{
private const MAKS_URINISH = 5;
private const BLOK_MUDDATI = 900; // 15 daqiqa
public function kiring(string $login, string $parol, string $ip): Sessiya
{
if ($this->urinishlar->bloklanganmi($ip, $login)) {
throw new JudaKopUrinish(self::BLOK_MUDDATI);
}
$foydalanuvchi = $this->foydalanuvchilar->loginBoyicha($login);
// Vaqt hujumidan himoya: foydalanuvchi topilmasa ham xesh hisoblanadi
$xesh = $foydalanuvchi?->parolXesh
?? '$2y$12$soxta.xesh.vaqt.hujumidan.himoya.uchun.qollaniladi';
if (!password_verify($parol, $xesh) || $foydalanuvchi === null) {
$this->urinishlar->yozing($ip, $login, muvaffaqiyat: false);
// Bir xil xabar - qaysi maydon noto'g'ri ekani oshkor bo'lmasin
throw new NotogriMalumot();
}
if (!$foydalanuvchi->faolmi()) {
throw new HisobBloklangan();
}
$this->urinishlar->tozalang($ip, $login);
session_regenerate_id(true); // sessiya fiksatsiyasidan himoya
return $this->sessiyalar->yarating($foydalanuvchi);
}
}
YOMON: "Bunday email topilmadi"
YOMON: "Parol noto'g'ri"
YAXSHI: "Email yoki parol noto'g'ri"
Birinchi ikkitasi hujumchiga qaysi emaillar ro'yxatdan o'tganini aniqlash imkonini beradi.
Xuddi shu qoida parolni tiklashda ham amal qiladi:
"Agar bu email ro'yxatdan o'tgan bo'lsa, xat yuborildi"
8. Ma'lumot yaxlitligi nosozliklari #
// Webhook imzosini tekshirish
public function webhookQabulQiling(Sorov $sorov): Javob
{
$imzo = $sorov->sarlavha('X-Webhook-Imzo');
$tana = $sorov->xomTana();
$kutilgan = hash_hmac('sha256', $tana, $this->sir);
if (!hash_equals($kutilgan, $imzo ?? '')) {
$this->jurnal->warning('Noto\'g\'ri webhook imzosi', [
'ip' => $sorov->ip(),
]);
return new Javob(401);
}
// ...
}
hash_equals ishlatingif ($kutilgan === $imzo) { } // vaqt hujumiga ochiq
if (hash_equals($kutilgan, $imzo)) { } // doimiy vaqtda solishtiradi
Oddiy === birinchi farqda to'xtaydi. Hujumchi javob vaqtini
o'lchab, imzoni belgi-belgi topishi mumkin.
9. Jurnal va monitoring yetishmasligi #
// Xavfsizlik hodisalarini alohida yozing
$this->xavfsizlikJurnali->warning('kirish_muvaffaqiyatsiz', [
'login' => $login,
'ip' => $ip,
'agent' => $foydalanuvchiAgenti,
'vaqt' => time(),
]);
$this->xavfsizlikJurnali->critical('huquq_oshirish_urinishi', [
'foydalanuvchi_id' => $joriy->id,
'sorov_resurs' => $resurs,
'ip' => $ip,
]);
| Hodisa | Nima uchun |
|---|---|
| Muvaffaqiyatsiz kirish urinishlari | Kuch bilan hujum |
| Huquq oshirish urinishlari | IDOR sinovi |
| Ko'p 404 xatolar | Katalog skanerlash |
| Odatiy bo'lmagan vaqtdagi faollik | O'g'irlangan hisob |
| Katta hajmdagi ma'lumot yuklash | Ma'lumot o'g'irlash |
| Admin amallari | Audit izi |
10. SSRF #
// XAVFLI: foydalanuvchi istalgan manzilga so'rov yuborishi mumkin
$rasm = file_get_contents($_POST['rasm_url']);
rasm_url=http://169.254.169.254/latest/meta-data/ ← bulut metama
rasm_url=http://localhost:6379/ ← ichki Redis
rasm_url=file:///etc/passwd ← fayl tizimi
// XAVFSIZ
final class TashqiRasmYuklovchi
{
private const RUXSAT_SXEMALAR = ['http', 'https'];
public function yuklang(string $url): string
{
$qismlar = parse_url($url) ?: throw new NotogriUrl($url);
if (!in_array($qismlar['scheme'] ?? '', self::RUXSAT_SXEMALAR, true)) {
throw new NotogriUrl('Faqat HTTP va HTTPS');
}
$ip = gethostbyname($qismlar['host']);
if ($this->ichkiManzilmi($ip)) {
throw new NotogriUrl('Ichki manzillarga ruxsat yo\'q');
}
return $this->http->get($url, [
'timeout' => 5,
'max_redirects' => 2,
'max_hajm' => 5 * 1024 * 1024,
]);
}
private function ichkiManzilmi(string $ip): bool
{
return !filter_var($ip, FILTER_VALIDATE_IP, [
'flags' => FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE,
]);
}
}
Sirlarni boshqarish #
# .gitignore
.env
.env.*
!.env.example
*.pem
*.key
config/sirlar.php
# .env.example - qiymatlarsiz
APP_MUHIT=production
APP_KALIT=
DB_HOST=127.0.0.1
DB_BAZA=dokon
DB_FOYDALANUVCHI=
DB_PAROL=
TOLOV_API_KALIT=
- Darhol sirni almashtiring - u allaqachon oshkor
- Tarixdan o'chiring:
git filter-repo --path .env --invert-paths - Force push va jamoani ogohlantirish
- Jurnalarni tekshiring - ishlatilganmi?
Tarixdan o'chirish yetarli emas - repozitoriy klonlangan bo'lishi mumkin.
# Sirlarni skanerlash
gitleaks detect --source . --verbose
trufflehog filesystem .
# CI da avtomatik tekshiruv
- name: Sirlarni skanerlash
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Ishonchlilik naqshlari #
final class ZanjirUzgich
{
private const XATO_CHEGARASI = 5;
private const OCHIQ_MUDDATI = 30;
public function __construct(
private KeshInterfeysi $kesh,
private string $nom,
) {}
public function bajaring(callable $amal, ?callable $zaxira = null): mixed
{
if ($this->ochiqmi()) {
if ($zaxira !== null) {
return $zaxira();
}
throw new XizmatMavjudEmas($this->nom);
}
try {
$natija = $amal();
$this->kesh->ochiring("uzgich:{$this->nom}:xatolar");
return $natija;
} catch (Throwable $xato) {
$xatolar = (int) $this->kesh->oshiring("uzgich:{$this->nom}:xatolar");
if ($xatolar >= self::XATO_CHEGARASI) {
$this->kesh->saqlang("uzgich:{$this->nom}:ochiq", true, self::OCHIQ_MUDDATI);
}
throw $xato;
}
}
private function ochiqmi(): bool
{
return (bool) $this->kesh->oling("uzgich:{$this->nom}:ochiq");
}
}
$tavsiyalar = $uzgich->bajaring(
amal: fn () => $this->tavsiyaXizmati->oling($mijozId),
zaxira: fn () => $this->ommaboppMahsulotlar(), // zaxira variant
);
Qayta urinish #
final class QaytaUrinish
{
public function bajaring(callable $amal, int $urinishlar = 3): mixed
{
$oxirgiXato = null;
for ($i = 1; $i <= $urinishlar; $i++) {
try {
return $amal();
} catch (VaqtinchalikXato $xato) {
$oxirgiXato = $xato;
if ($i < $urinishlar) {
// Eksponensial kechikish + tasodifiy qo'shimcha
$kutish = (2 ** $i) + random_int(0, 1000) / 1000;
usleep((int) ($kutish * 1_000_000));
}
}
}
throw $oxirgiXato;
}
}
// Vaqtinchalik: tarmoq, timeout, 503
// Doimiy: 400, 401, 404, validatsiya
if ($xato->kod() === 400) {
throw $xato; // qayta urinish yordam bermaydi
}
Tasodifiy qo'shimcha (jitter) muhim: usiz barcha mijozlar bir vaqtda qayta urinadi va serverni yana qulatadi.
Vaqt chegarasi #
$javob = $this->http->get($url, [
'connect_timeout' => 3,
'timeout' => 10,
]);
Tashqi xizmat javob bermasa, sizning jarayoningiz cheksiz kutadi.
Bir necha yuz shunday so'rov - barcha PHP jarayonlari band bo'ladi va sayt butunlay ishlamay qoladi.
Har bir tashqi chaqiruvda vaqt chegarasi bo'lsin.
Yuk to'kish #
final class YukNazoratchisi
{
private const MAKS_NAVBAT = 100;
public function qabulQilaOlamizmi(): bool
{
return $this->navbat->uzunligi() < self::MAKS_NAVBAT;
}
}
if (!$nazoratchi->qabulQilaOlamizmi()) {
return new Javob(503, ['Retry-After' => '30']);
}
Yuk juda katta bo'lsa, so'rovlarning bir qismini rad eting.
90% foydalanuvchi tez javob olishi, 100% foydalanuvchi 30 soniya kutib xato olishidan yaxshiroq.
Xatolarga chidamlilik #
// Zaxira variant bilan ishlash
public function tavsiyalarOling(int $mijozId): array
{
try {
return $this->uzgich->bajaring(
fn () => $this->tavsiyaXizmati->oling($mijozId)
);
} catch (Throwable $xato) {
$this->jurnal->warning('Tavsiya xizmati ishlamadi', [
'xato' => $xato->getMessage(),
]);
// Sayt ishlashda davom etadi
return $this->kesh->oling('ommabop_mahsulotlar') ?? [];
}
}
| Qism | Nosozlikda |
|---|---|
| To'lov | Xato ko'rsating - noto'g'ri ishlash xavfli |
| Tavsiyalar | Zaxira ro'yxat ko'rsating |
| Sharhlar | Bo'sh bo'lim ko'rsating |
| Statistika | Jimgina o'tkazib yuboring |
Har bir tashqi bog'liqlik uchun so'rang: "u ishlamasa nima bo'ladi?"
Xavfsizlik tekshiruv ro'yxati #
| Talab | Bajarildi |
|---|---|
| Barcha so'rovlar parametrlangan | |
| Chiqish kontekstga mos qochirilgan | |
| Har bir resursda huquq tekshiruvi | |
Parollar password_hash bilan | |
| HTTPS majburiy, HSTS yoqilgan | |
| Xavfsizlik sarlavhalari sozlangan | |
| CSRF himoyasi barcha formalarda | |
| Kirish urinishlari cheklangan | |
Sirlar .env da, Git da emas | |
| Bog'liqliklar audit qilingan | |
| Xato xabarlari ma'lumot bermaydi | |
| Fayl yuklash tekshirilgan | |
| Xavfsizlik hodisalari jurnalga yoziladi | |
| Zaxira nusxa sinovdan o'tgan | |
| Vaqt chegaralari o'rnatilgan |
Fayl yuklash #
final class FaylYuklovchi
{
private const RUXSAT_TURLAR = ['image/jpeg', 'image/png', 'image/webp'];
private const MAKS_HAJM = 5 * 1024 * 1024;
public function yuklang(YuklanganFayl $fayl): string
{
if ($fayl->hajm() > self::MAKS_HAJM) {
throw new FaylJudaKatta(self::MAKS_HAJM);
}
// MIME turini fayl mazmuni bo'yicha aniqlash (nom bo'yicha emas!)
$tur = (new finfo(FILEINFO_MIME_TYPE))->file($fayl->vaqtinchalikYol());
if (!in_array($tur, self::RUXSAT_TURLAR, true)) {
throw new NotogriFaylTuri($tur);
}
// Rasm haqiqatan rasmmi?
if (@getimagesize($fayl->vaqtinchalikYol()) === false) {
throw new NotogriFaylTuri('Rasm emas');
}
// Yangi nom - foydalanuvchi nomini ishlatmang
$nom = bin2hex(random_bytes(16)) . '.' . $this->kengaytma($tur);
// Veb-ildizdan tashqarida saqlang
$fayl->kochiring(self::YUKLAMALAR_YOLI . '/' . $nom);
return $nom;
}
}
rasm.php.jpg ← ba'zi serverlarda PHP sifatida bajariladi
rasm.jpg\0.php ← null bayt hujumi
../../../etc/passwd ← yo'l o'tish
Qoidalar:
- MIME turini mazmun bo'yicha aniqlang
- Foydalanuvchi bergan nomni ishlatmang
- Fayllarni veb-ildizdan tashqarida saqlang
- Ularni PHP orqali bering, to'g'ridan-to'g'ri emas
- Rasm bo'lsa - qayta yarating (metama va yashirin kod yo'qoladi)
- Loyihangizda IDOR zaifligini qidiring.
- Markazlashtirilgan huquq siyosati klassini yozing.
- Barcha SQL so'rovlarni tekshiring - parametrlanganmi?
- Chiqish qochirishni tekshiring - XSS xavfi bormi?
composer auditishga tushiring va zaifliklarni tuzating.- Xavfsizlik sarlavhalarini qo'shing va tekshiring.
- Kirish urinishlarini cheklovchi kod yozing.
gitleaksbilan repozitoriyni skanerlang.- Zanjir uzgich naqshini amalga oshiring.
- Xavfsiz fayl yuklovchi yozing.
Xulosa #
- Prinsiplar: eng kam huquq, chuqur himoya, xavfsiz standart, hech kimga ishonmang.
- IDOR - eng ko'p uchraydigan zaiflik; huquq tekshiruvini markazlashtiring.
- Parollar uchun
password_hash, hech qachon MD5 yoki SHA. - O'z kriptografiyangizni yozmang.
- Inyeksiyaga qarshi: parametrlangan so'rovlar va kontekstga mos qochirish.
- Xato xabarlari ma'lumot bermasin.
hash_equalsbilan imzolarni solishtiring.- Bog'liqliklar - eng katta hujum yuzasi; muntazam audit qiling.
- Sir Git ga tushsa - darhol almashtiring.
- Zanjir uzgich kaskadli nosozlikning oldini oladi.
- Vaqt chegarasisiz tashqi chaqiruv - kutilgan nosozlik.
- Har bir bog'liqlik uchun so'rang: "u ishlamasa nima bo'ladi?"
- Fayl yuklash - eng xavfli imkoniyat, alohida e'tibor talab qiladi.
Keyingi bo'limda hujjatlar va qo'llab-quvvatlashni ko'ramiz.
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.