Veb
Host header injection: oddiy ko'rinadigan, lekin jiddiy zaiflik
Ilova Host yoki X-Forwarded-Host headeriga ishonsa, parol tiklash havolalari begona domenga yo'naltirilishi mumkin. Real holat, tekshirish usuli va Laravel hamda nginx'da tuzatish.
· 7 daq. o'qish

Host header injection — ko'p dasturchilar e'tibor bermaydigan zaiflik. Kodda SQL yoki XSS kabi ko'zga tashlanadigan xato yo'q, hamma narsa odatdagidek ishlaydi. Lekin ilova so'rovdagi Host yoki X-Forwarded-Host headeriga ko'r-ko'rona ishonsa, hujumchi ilova yaratadigan havolalarni o'z domeniga yo'naltira oladi.
Bu zaiflik o'z mahsulotimiz — soliq-moliya SaaS platformasi — ekspertizasida topilgan edi. Quyida u qanday ishlashi, qanday tekshirilishi va qanday yopilganini ko'rsatamiz.
Muammo qayerdan kelib chiqadi
Ilovalar ko'pincha to'liq (absolyut) URL yasaydi: email'dagi havolalar, redirect'lar, canonical teglar, fayl manzillari. Buning uchun ular joriy so'rovdan domen nomini oladi. Framework domenni Host headeridan, ilova proksi orqasida bo'lsa esa X-Forwarded-Host headeridan o'qiydi.
Muammo shundaki, bu headerlarni mijoz o'zi yuboradi. Agar ilova "proksi qo'shgan bo'lsa kerak" deb X-Forwarded-Host ga ishonsa, istalgan odam o'zi xohlagan domenni ko'rsata oladi.
Real holat: parol tiklash havolasi
Bizning holatda ilova barcha X-Forwarded-* headerlariga ishonib qolgan edi. Hujum ssenariysi quyidagicha ko'rinadi:
- Hujumchi parolni tiklash formasiga qurbonning email manzilini kiritadi.
- So'rovga
X-Forwarded-Host: attacker.exampleheaderini qo'shadi. - Ilova tiklash havolasini shu domen bilan yasaydi:
https://attacker.example/reset-password/<token>. - Qurbon haqiqiy saytdan kelgan haqiqiy xatni oladi. Havolani bossa, maxfiy token hujumchi serveriga boradi.
- Hujumchi token bilan haqiqiy saytda parolni almashtiradi.
Xat rasmiy manzildan keladi, matn to'g'ri, faqat havoladagi domen boshqa. Shuning uchun bu zaiflik jiddiy hisoblanadi.
Boshqa oqibatlar ham bo'lishi mumkin: keshlanadigan sahifalarda begona domen havolalari bo'lib qolishi (cache poisoning), redirect'larning begona saytga yo'naltirilishi.
Nima uchun bu zaiflik uzoq vaqt sezilmay qoladi? Chunki odatiy foydalanishda Host har doim to'g'ri keladi va testlarda ham hamma narsa ishlaydi. Muammo faqat kimdir headerni ataylab o'zgartirganda ko'rinadi. Proksi orqasidagi ilovalarda esa dasturchilar ko'pincha "hammasiga ishon" sozlamasini sayt to'g'ri ishlashi uchun qo'yib qo'yadi va keyin unutadi.
Mijoz yuborgan har qanday header — foydalanuvchi kiritgan ma'lumot.
Hostham bundan mustasno emas.
Qanday tekshirish mumkin
Eng oddiy tekshiruv — begona domen bilan so'rov yuborib, u javobda paydo bo'ladimi, ko'rish:
curl -si https://your-domain.uz/login \
-H "X-Forwarded-Host: attacker.example" | grep -i attacker
curl -si https://your-domain.uz/login \
-H "Host: attacker.example" | grep -i attacker
Shuningdek:
- Parolni tiklash formasini
X-Forwarded-Hostbilan yuboring va kelgan xatdagi havolani tekshiring (o'zingizning test akkauntingizda). Locationheaderli redirect javoblarini ko'ring.X-Forwarded-Server,X-Host,Forwardedkabi muqobil headerlarni ham sinab ko'ring.
Agar javobda yoki xatda attacker.example chiqsa, zaiflik bor.
Laravel'da tuzatish
1. Proksiga ishonchni cheklang
Laravel TrustProxies middleware'i qaysi proksilarga va qaysi headerlarga ishonishni belgilaydi. Bizda muammo shu yerda edi: barcha headerlarga ishonilgan. Tuzatish — faqat X-Forwarded-For, Proto va Port ga ishonish, X-Forwarded-Host ni esa e'tiborsiz qoldirish.
Laravel 11+ da bootstrap/app.php:
use Illuminate\Http\Request;
->withMiddleware(function (Middleware $middleware) {
$middleware->trustProxies(
at: ['127.0.0.1'],
headers: Request::HEADER_X_FORWARDED_FOR
| Request::HEADER_X_FORWARDED_PORT
| Request::HEADER_X_FORWARDED_PROTO
);
})
at ga faqat haqiqiy proksi manzilini yozing, '*' emas.
2. Production'da root URL'ni majburlang
Havolalar so'rovdan emas, konfiguratsiyadan yasalishi uchun AppServiceProvider::boot() ga qo'shing:
use Illuminate\Support\Facades\URL;
if ($this->app->isProduction()) {
URL::forceRootUrl(config('app.url'));
URL::forceScheme('https');
}
.env dagi APP_URL to'g'ri domen bilan to'ldirilgan bo'lishi shart.
3. Ruxsat etilgan hostlar
Qo'shimcha qatlam sifatida TrustHosts middleware'ini yoqing — u faqat ruxsat etilgan domenlardan kelgan so'rovlarni qabul qiladi:
$middleware->trustHosts(at: ['your-domain.uz']);
nginx'da tuzatish
Ilova darajasidagi himoya bilan birga veb-server ham begona Host bilan kelgan so'rovlarni ilovaga yetkazmasligi kerak.
default_server
nginx so'rovni server_name bo'yicha mos server blokiga yuboradi. Mos blok topilmasa, so'rov default_server ga tushadi — agar u belgilanmagan bo'lsa, birinchi blokka, ya'ni ko'pincha asosiy saytingizga. Shuning uchun alohida "tutib qoluvchi" blok qo'shing:
server {
listen 80 default_server;
listen 443 ssl default_server;
server_name _;
ssl_reject_handshake on;
return 444;
}
server {
listen 443 ssl;
server_name your-domain.uz;
# ... asosiy sayt
}
return 444 ulanishni javobsiz yopadi, ssl_reject_handshake (nginx 1.19.4+) esa noma'lum domen uchun TLS ulanishni rad etadi.
Proksiga uzatiladigan headerlar
Agar nginx ilovaga proksi qilsa, mijoz yuborgan X-Forwarded-Host ni o'tkazib yubormang va Host ni server qiymati bilan yuboring:
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host "";
Tuzatishdan keyin
Yuqoridagi curl buyruqlarini qayta ishga tushiring: begona Host bilan so'rov nginx tomonidan rad etilishi, X-Forwarded-Host esa havolalarga hech qanday ta'sir qilmasligi kerak. Parol tiklash xatini ham qayta tekshiring.
Xulosa
Host header injection kodda ko'rinmaydi — u ishonch sozlamalarida yashaydi. Tuzatish qisqa: proksiga ishonchni cheklash, root URL'ni majburlash va nginx'da default_server qo'shish. Lekin buni oldindan bilish va tekshirish kerak.
Saytingiz begona headerlarga ishonmayotganini tekshirmoqchimisiz? Skanerlash uchun so'rov qoldiring — Claude AI agenti va mutaxassisimiz konfiguratsiyangizni ko'rib chiqib, topilgan teshiklarni yopishga yordam beramiz.


