Asosiy matnga o'tish
Blog

Veb

SSRF: server sizning nomingizdan so'rov yuborganda

URL bo'yicha rasm yuklash, webhook va havola preview'i serverni ichki tarmoqqa yo'naltirishi mumkin. SSRF qanday ishlaydi, 169.254.169.254, DNS rebinding, tekshirish va tuzatish.

· 10 daq. o'qish

Foto: Raysonho @ Open Grid Scheduler / Grid Engine, CC0 · Wikimedia Commons

Server-Side Request Forgery (SSRF) — hujumchi sizning serveringizni o'zi tanlagan manzilga so'rov yuborishga majbur qiladigan zaiflik. Tashqaridan qaraganda funksiya beozor ko'rinadi: "Rasmni URL orqali yuklash", "Webhook manzilini kiriting", "Havolaning oldindan ko'rinishi". Lekin agar server berilgan URL'ni tekshirmasdan ochsa, hujumchi uni tashqi sayt o'rniga http://127.0.0.1:6379, ichki admin panel yoki bulut metadata xizmatiga yo'naltirishi mumkin.

Muammoning og'irligi shundaki, server odatda tarmoqda imtiyozli joyda turadi: u ichki xizmatlarni ko'radi, firewall ichida, ko'pincha "ichkaridan kelgan so'rovga ishoniladi" degan taxmin bilan sozlangan tizimlar orasida. SSRF bu ishonchni hujumchiga topshiradi.

SSRF qayerda paydo bo'ladi

Foydalanuvchi URL kiritadigan yoki URL bilvosita serverga yetib boradigan har qanday joy:

  • URL orqali rasm yoki fayl import qilish — avatar, mahsulot rasmi, hujjat.
  • Webhook'lar — foydalanuvchi o'z manzilini kiritadi, server unga hodisalarni yuboradi.
  • Havola preview'i — chat yoki postda havola qo'yilganda server sarlavha va rasmni oladi.
  • HTML'dan PDF yasash — generator HTML ichidagi <img>, <link>, <iframe> manbalarini server tomonda yuklaydi.
  • Integratsiyalar — "API manzilingizni kiriting", RSS import, iCal sinxronizatsiyasi.
  • XML ishlov berish — tashqi entity'lar yoqilgan bo'lsa (XXE), parser ham so'rov yuboradi.
  • Proksi yoki "redirect" endpoint'lari — /fetch?url=..., /image-proxy?src=....

Hujumchi nimaga erishishi mumkin

  1. Ichki xizmatlarga kirish. 127.0.0.1 dagi Redis, Elasticsearch, Memcached, boshqaruv paneli yoki faqat ichki tarmoqqa ochiq API. Ko'pchilik ichki xizmatlarda autentifikatsiya umuman yo'q.
  2. Bulut metadata. Bulut provayderlarida http://169.254.169.254/ manzilida instansiya metadata xizmati ishlaydi. U yerdan instansiya haqidagi ma'lumot, ba'zi sozlamalarda esa vaqtinchalik kirish kalitlari olinishi mumkin.
  3. Ichki tarmoqni skanerlash. Javob vaqti va xato turlari orqali qaysi ichki manzillar va portlar ochiqligini aniqlash.
  4. Boshqa protokollar. Agar HTTP kutubxonasi file://, gopher:// yoki dict:// sxemalarini qo'llasa, mahalliy fayllarni o'qish yoki ichki xizmatlarga xom buyruq yuborish mumkin bo'lib qoladi.
  5. Tashqi hujumlar uchun "niqob". So'rovlar sizning serveringiz IP manzilidan chiqadi.

Hujumchi javobni ko'ra oladigan holat (to'liq SSRF) eng xavfli. Lekin javob ko'rinmasa ham (blind SSRF), ichki xizmatlarda holatni o'zgartiradigan so'rovlar baribir yuboriladi.

Nima uchun bu ekspertiza uchun muhim

SSRF OWASP Top 10 (2021) ro'yxatida alohida toifa — A10 "Server-Side Request Forgery" — sifatida kiritilgan va CWE-918 deb tasniflanadi. OWASP ASVS ham server tomonidan yuboriladigan so'rovlar uchun manzillar allowlist'ini talab qiladi. Ekspertizada URL qabul qiladigan har bir maydon odatda ichki manzillar, metadata manzili va muqobil IP yozuvlari bilan sinab ko'riladi. Bunday topilma ko'pincha yuqori xavf darajasida baholanadi, chunki u tashqi perimetrni chetlab o'tadi.

O'zingiz qanday tekshirishingiz mumkin

1. URL qabul qiladigan joylarni toping

Kod bazasida tashqi so'rov yuboradigan chaqiruvlarni qidiring:

# PHP / Laravel
grep -rnE "Http::(get|post|send)|file_get_contents\(|curl_init|fopen\(\s*\\\$|new Client\(" app/

# Node
grep -rnE "axios\.(get|post)|fetch\(|got\(|http\.request|https\.get" src/

Har birida URL qayerdan kelishini kuzating. Agar u foydalanuvchidan, bazadagi foydalanuvchi sozlamasidan yoki uchinchi tomon javobidan kelsa — bu SSRF nomzodi.

2. Nazorat ostidagi qabul qiluvchi bilan sinang

O'z serveringizda yoki test so'rovlarini qayd qiladigan xizmatda manzil oching va uni ilovaga bering. So'rov kelsa, server haqiqatan tashqariga murojaat qilyapti — endi ichki manzillarni sinash mumkin.

3. Ichki manzillarni sinang (faqat o'z test muhitingizda)

http://127.0.0.1/
http://localhost:6379/
http://169.254.169.254/
http://[::1]/
http://0.0.0.0/
http://2130706433/          (127.0.0.1 ning o'nlik yozuvi)
http://127.1/
file:///etc/passwd

Javob vaqtidagi farq, xato matnlari ("connection refused" va "timeout" farqi) yoki javob tarkibi zaiflikni ko'rsatadi.

4. Redirect'larni tekshiring

O'z serveringizda 302 bilan http://127.0.0.1/ ga yo'naltiradigan sahifa qiling. Agar ilova faqat boshlang'ich URL'ni tekshirib, keyin redirect'ga avtomatik ergashsa, himoya chetlab o'tiladi.

Nima uchun "oddiy tekshiruv" ishlamaydi

Ko'p dasturchilar birinchi navbatda shunday yozadi:

if (str_contains($url, 'localhost') || str_contains($url, '127.0.0.1')) {
    abort(422);
}

Bu deyarli foydasiz. IP manzil ko'p shaklda yozilishi mumkin (127.1, 2130706433, 0x7f000001, [::ffff:127.0.0.1]), istalgan domen 127.0.0.1 ga resolve qilinishi mumkin, redirect esa tekshiruvdan keyin manzilni o'zgartiradi.

DNS rebinding

Hatto domenni resolve qilib, IP'ni tekshirish ham yetarli bo'lmasligi mumkin. Hujumchi o'z domenining DNS yozuvini juda qisqa TTL bilan boshqaradi: birinchi so'rovda (sizning tekshiruvingiz) u ochiq IP qaytaradi, ikkinchi so'rovda (haqiqiy ulanish) esa 127.0.0.1. Tekshiruv va ulanish orasida manzil o'zgaradi.

Yechim — bir marta resolve qilish, IP'ni tekshirish va aynan shu IP'ga ulanish (IP pinning).

SSRF'ga qarshi to'g'ri savol "URL'da nima yozilgan?" emas, "server aslida qaysi IP'ga ulanyapti?".

Qanday tuzatish

Umumiy tamoyillar

  1. Allowlist, iloji bo'lsa. Agar ilova faqat bir nechta ma'lum xizmatlarga murojaat qilishi kerak bo'lsa, faqat ularning domenlariga ruxsat bering.
  2. Faqat http va https. Boshqa sxemalarni rad eting.
  3. Resolve qilingan barcha IP'larni tekshiring. Xususiy (10/8, 172.16/12, 192.168/16), loopback (127/8, ::1), link-local (169.254/16, fe80::/10), 0.0.0.0/8, multicast va zaxiralangan diapazonlarni bloklang.
  4. IP'ni mahkamlang va tekshirilgan IP'ga ulaning.
  5. Redirect'larni o'chiring yoki har birini qayta tekshiring.
  6. Cheklovlar: qisqa timeout, javob hajmiga limit, kutilgan Content-Type.
  7. Xom javob va xato matnini foydalanuvchiga qaytarmang.

Laravel

use Illuminate\Support\Facades\Http;

function safeFetch(string $url)
{
    $parts = parse_url($url);
    if (!in_array($parts['scheme'] ?? '', ['http', 'https'], true) || empty($parts['host'])) {
        throw new InvalidArgumentException('Invalid URL');
    }

    $host = $parts['host'];
    $ips = gethostbynamel($host) ?: [];
    if (!$ips) {
        throw new InvalidArgumentException('Unresolvable host');
    }

    foreach ($ips as $ip) {
        if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
            throw new InvalidArgumentException('Blocked address');
        }
    }

    $port = $parts['port'] ?? ($parts['scheme'] === 'https' ? 443 : 80);

    return Http::timeout(5)
        ->withOptions([
            'allow_redirects' => false,
            'curl' => [
                CURLOPT_RESOLVE   => ["{$host}:{$port}:{$ips[0]}"],
                CURLOPT_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS,
            ],
        ])
        ->get($url);
}

CURLOPT_RESOLVE cURL'ni tekshirilgan IP'ga ulanishga majbur qiladi va DNS rebinding'ni yopadi. gethostbynamel faqat IPv4 qaytaradi; IPv6 kerak bo'lsa, dns_get_record bilan AAAA yozuvlarini ham tekshiring. PHP 8.2+ da FILTER_FLAG_GLOBAL_RANGE bayrog'i ham bor, u faqat global manzillarni o'tkazadi.

Node

import dns from 'node:dns/promises';
import ipaddr from 'ipaddr.js';
import axios from 'axios';
import http from 'node:http';
import https from 'node:https';

async function resolveSafe(hostname) {
  const records = await dns.lookup(hostname, { all: true });
  for (const { address } of records) {
    if (ipaddr.process(address).range() !== 'unicast') {
      throw new Error('Blocked address');
    }
  }
  return records[0];
}

export async function safeFetch(rawUrl) {
  const url = new URL(rawUrl);
  if (!['http:', 'https:'].includes(url.protocol)) throw new Error('Invalid scheme');

  const pinned = await resolveSafe(url.hostname);
  const lookup = (_h, opts, cb) =>
    opts?.all
      ? cb(null, [{ address: pinned.address, family: pinned.family }])
      : cb(null, pinned.address, pinned.family);
  const agentOpts = { lookup };

  return axios.get(url.href, {
    timeout: 5000,
    maxRedirects: 0,
    maxContentLength: 5 * 1024 * 1024,
    httpAgent: new http.Agent(agentOpts),
    httpsAgent: new https.Agent(agentOpts),
  });
}

ipaddr.js da range() ochiq internet manzillari uchun unicast qaytaradi; private, loopback, linkLocal va boshqalar bloklanadi. Maxsus lookup funksiyasi ulanishni tekshirilgan IP'ga mahkamlaydi.

Tarmoq va infratuzilma darajasida

Kod darajasidagi himoya xato qilishi mumkin, shuning uchun ikkinchi qatlam kerak:

  • Chiquvchi trafikni cheklang (egress). Tashqi URL'larni yuklaydigan jarayonni alohida worker yoki konteynerga ajrating va unga ichki tarmoqqa chiqishni firewall bilan taqiqlang.
  • Ichki xizmatlarda ham autentifikatsiya. Redis'da parol, ichki API'larda token. "Faqat ichkaridan ochiq" — himoya emas.
  • Bulut metadata. Agar bulutda bo'lsangiz, metadata xizmatining token talab qiladigan versiyasini yoqing (masalan, AWS'da IMDSv2) va instansiyaga minimal huquqli rol bering.
  • Keraksiz xizmatlarni o'chiring va ular 0.0.0.0 emas, 127.0.0.1 da tinglashiga ishonch hosil qiling. Batafsil: ochiq portlar va server hardening.

Webhook'lar uchun alohida

  • Webhook manzilini saqlashda ham, har bir yuborishda ham tekshiring — DNS yozuvi keyinchalik o'zgarishi mumkin.
  • Javob tanasini foydalanuvchiga ko'rsatmang, faqat holat kodini qayd qiling.
  • Yuboriladigan so'rovlarni imzolang, shunda qabul qiluvchi ularning haqiqiyligini tekshira oladi.

Qisqa checklist

  • URL qabul qiladigan barcha funksiyalar ro'yxati tuzilgan: import, webhook, preview, PDF, integratsiyalar.
  • Faqat http/https sxemalariga ruxsat berilgan.
  • Resolve qilingan barcha IP'lar xususiy, loopback, link-local va zaxiralangan diapazonlarga qarshi tekshiriladi.
  • Ulanish tekshirilgan IP'ga mahkamlangan (DNS rebinding yopilgan).
  • Redirect'lar o'chirilgan yoki har biri qayta tekshiriladi.
  • Timeout, javob hajmi va Content-Type cheklangan.
  • Xom javob va xato tafsilotlari foydalanuvchiga qaytarilmaydi.
  • Tashqi so'rov yuboruvchi jarayon ichki tarmoqqa chiqa olmaydi.
  • Ichki xizmatlar autentifikatsiya talab qiladi, metadata xizmati himoyalangan.

Xulosa

SSRF mahsulotdagi eng foydali funksiyalar — import, webhook, preview — ichida yashiringan bo'ladi. Uni satrlarni qora ro'yxat bilan filtrlash orqali yopib bo'lmaydi: IP'ni resolve qilish, tekshirish, mahkamlash va redirect'larni nazorat qilish kerak, tarmoq darajasida esa chiquvchi trafikni cheklash zarur. Bu ishlar loyiha boshida unchalik qiyin emas, lekin ekspertizada topilsa, arxitekturani shoshilinch o'zgartirishga to'g'ri keladi.

URL bilan ishlaydigan funksiyalaringizni ekspertizadan oldin tekshirmoqchimisiz? Skanerlash uchun ariza qoldiring — Claude AI agenti tashqi so'rov yuboradigan joylarni kod bo'ylab topadi, mutaxassisimiz esa ularni sinab, teshiklarni yopishga yordam beradi.