Aktuálna situácia: PHP2Shell. Dve kritické zraniteľnosti PHP (CVSS 9.2) umožňujú spustenie škodlivého kódu bez prihlásenia. Záplaty od 21. 10. 2026.Čo treba urobiť teraz →

Ako zabrániť Server-Side Request Forgery (SSRF) v PHP

Ako vývojári zabraňujú tomu, aby aplikácia PHP z cudzieho podnetu dotazovala interné systémy: zoznamy povolených cieľov, obmedzenie protokolov, kontrola preloženej adresy a hranice v sieti.

Stav 5 min čítaniaBezpečný vývoj

Stručne: SSRF v PHP zabránite tak, že vaša aplikácia sťahuje len adresy, ktoré sú na pevnom zozname povolených, výlučne cez HTTPS a bez nasledovania presmerovaní. Preložená adresa IP sa skontroluje voči súkromným a rezervovaným rozsahom a potom sa pre spojenie zafixuje. Firewall pre odchádzajúcu prevádzku zabezpečí, že interné systémy zostanú nedosiahnuteľné aj pri chybe v kóde.

Keď vlastný server posiela požiadavky za cudzích

Náhľady odkazov v chate, import obrázka produktu cez URL, webhooky do partnerských systémov, čítačka kanálov v CMS: mnohé aplikácie PHP sťahujú adresy, ktoré zadal používateľ. Je to užitočná funkcia a zároveň dvere dovnútra.

Pri Server-Side Request Forgery, skrátene SSRF, prinúti útočník aplikáciu poslať požiadavku na cieľ podľa vlastného výberu. Háčik: požiadavka prichádza zo samotného servera. Dosiahne tak systémy, ktoré sú zvonka zablokované, napríklad databázy, správcovské rozhrania vo vnútornej sieti, služby počúvajúce len na localhost alebo služby metadát poskytovateľov cloudu.

V OWASP Top 10 z roku 2021 tvorilo SSRF samostatnú kategóriu. V projektoch PHP sa zraniteľnosť často objavuje tam, kde niekto narýchlo postavil funkciu „pridať obrázok cez URL“.

SSRF v PHP: ktoré funkcie sťahujú adresy

Adresy nesťahuje len cURL. Tieto miesta by ste mali mať na očiach:

Funkcia alebo oblasť Prečo je relevantná
cURL (curl_exec()) najčastejšia cesta, možných je veľa protokolov
file_get_contents(), fopen(), copy() s URL používajú wrappery URL, ak je aktívne allow_url_fopen
getimagesize() a knižnice pre obrázky môžu načítať vzdialené súbory
spracovanie XML, klienti SOAP za určitých okolností načítavajú externé zdroje
knižnice HTTP ako Guzzle stavajú na cURL alebo streamoch, rovnaké pravidlá

Ak vaša aplikácia nemusí otvárať vzdialené súbory cez súborové funkcie, vypnite allow_url_fopen na strane servera. Príbuzná téma, vkladanie súborov cez cesty z požiadavky, rieši sprievodca Ako zabrániť Local a Remote File Inclusion.

Obrana v piatich krokoch

OWASP odporúča kombináciu opatrení, ktoré by sa jednotlivo dali obísť, no spolu držia:

  1. Zoznam povolených namiesto voľnej URL: najlepšie je, ak používateľ vyberá len spomedzi známych cieľov, alebo zadá iba identifikátor a aplikácia si adresu zostaví sama.
  2. Povoliť len HTTPS: iné protokoly ako file, gopher alebo ftp v cURL vylúčiť, aj pri presmerovaniach.
  3. Nenasledovať presmerovania: povolená adresa by inak mohla presmerovať na interný cieľ.
  4. Skontrolovať a zafixovať preloženú adresu: preložiť názov hostiteľa, skontrolovať IP voči súkromným rozsahom, rozsahom loopback a link-local a práve túto IP použiť pre spojenie. Inak môže druhé preloženie DNS vrátiť iný cieľ.
  5. Obmedziť sieť: webserver smie smerom von dosiahnuť len ciele, ktoré potrebuje.

Bezpečný vzor s cURL

Nasledujúci príklad zavádza kroky 1 až 4 pre IPv4. Názvy hostiteľov a postup sú príklady; pre IPv6 platia rovnaké kontroly.

<?php
declare(strict_types=1);

function ladeVonPartner(string $url): string
{
    $teile = parse_url($url);
    if (!is_array($teile) || ($teile['scheme'] ?? '') !== 'https'
        || isset($teile['user']) || isset($teile['pass']) || isset($teile['port'])) {
        throw new InvalidArgumentException('Adresse nicht erlaubt.');
    }

    $host = strtolower($teile['host'] ?? '');
    $erlaubt = ['api.partner.example', 'bilder.partner.example'];
    if (!in_array($host, $erlaubt, true)) {
        throw new InvalidArgumentException('Ziel nicht erlaubt.');
    }

    $ip = gethostbyname($host);
    $oeffentlich = filter_var($ip, FILTER_VALIDATE_IP,
        FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE);
    if ($oeffentlich === false) {
        throw new RuntimeException('Ziel löst auf eine nicht erlaubte Adresse auf.');
    }

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER  => true,
        CURLOPT_FOLLOWLOCATION  => false,
        CURLOPT_PROTOCOLS       => CURLPROTO_HTTPS,
        CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTPS,
        CURLOPT_RESOLVE         => [$host . ':443:' . $ip],
        CURLOPT_CONNECTTIMEOUT  => 3,
        CURLOPT_TIMEOUT         => 10,
    ]);
    $antwort = curl_exec($ch);
    if ($antwort === false) {
        throw new RuntimeException('Abruf fehlgeschlagen.');
    }
    return $antwort;
}

Niekoľko detailov je dôležitých. gethostbyname() pri chybe vráti názov hostiteľa; nasledujúca kontrola IP to zachytí. Príznaky FILTER_FLAG_NO_PRIV_RANGE a FILTER_FLAG_NO_RES_RANGE vylučujú podľa príručky PHP okrem iného rozsahy 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8 a 169.254.0.0/16. Od PHP 8.2 existuje navyše FILTER_FLAG_GLOBAL_RANGE, ktorý pripúšťa len globálne platné adresy. CURLOPT_RESOLVE zabezpečí, že cURL použije presne skontrolovanú adresu, pričom zostane zachovaný názov hostiteľa aj kontrola certifikátu.

Dva ďalšie body obmedzujú to, čo sa útočník dozvie zo zraniteľnosti SSRF. Odpovede a chybové hlásenia sťahovaného cieľa nevracajte používateľovi nefiltrované: už rozlíšenie medzi „spojenie odmietnuté“ a „prekročenie času“ prezrádza, aké interné služby existujú. A obmedzte trvanie a veľkosť odpovede, aby sa funkcia nedala použiť na preťaženie vlastného servera. Webhooky na adresy, ktoré zákazníci zadávajú sami, najlepšie odosielajte z fronty a nie počas prebiehajúcej požiadavky.

Dôležité

Ak vaša aplikácia skutočne musí sťahovať ľubovoľné adresy, napríklad pre náhľady odkazov, presuňte túto funkciu do oddelenej služby bez prístupu do vnútornej siete. Zoznam povolených potom nie je možný, o to dôležitejšie je oddelenie siete.

Sieťová úroveň ako záchranná sieť

Kontroly v kóde môžu mať medzery, napríklad keď dve knižnice rozložia URL odlišne. OWASP radí takéto nezrovnalosti vyhodnocovať ako odmietnutie a navyše obmedzovať na úrovni siete. Webserver potrebuje smerom von zvyčajne len málo cieľov: zdroje balíkov, poskytovateľov platieb a dopravy, poštový relay, určité rozhrania.

Firewall pre odchádzajúcu prevádzku pomáha dvojnásobne. Zastaví požiadavky SSRF do vnútornej siete a po vlámaní, napríklad cez nezáplatovanú verziu PHP, sťažuje dosťahovanie ďalších nástrojov. Ako pravidlá zostaviť, opisuje Firewall pre webserver: otvoriť len potrebné porty. Aké spojenia server skutočne vytvára, ukazuje Kontrola odchádzajúcich spojení servera.

V cloudových prostrediach patrí k tomu spevnený variant služby metadát. OWASP uvádza pre AWS prechod na IMDSv2 a vypnutie IMDSv1.

Vyhľadanie SSRF v existujúcom kóde

Rýchlym vstupom je hľadanie miest, kde funkcie sťahovania dostávajú hodnoty z požiadavky:

grep -rnE "(curl_init|file_get_contents|fopen|getimagesize|copy)\s*\(" src/ --include="*.php" | grep -E '\$_(GET|POST|REQUEST)|\$url'
grep -rn "CURLOPT_FOLLOWLOCATION" src/ --include="*.php"

Nálezy sú úlohy na kontrolu. Obzvlášť dôkladne si prezrite funkcie, ktoré používajú administrátori: importy, nastavenia webhookov, kontroly aktualizácií pluginov.

Ľahko sa prehliadnu generátory PDF, ktoré menia HTML so vloženými obrázkami alebo štýlmi na dokumenty. Ak časť tohto HTML pochádza zo vstupov používateľa, napríklad pri faktúrach s voliteľným logom, generátor môže za určitých okolností sťahovať adresy, ktoré určuje používateľ. Skontrolujte tam nastavenia načítavania vzdialených zdrojov a vypnite ho, ak sa nepotrebuje.

Ako konkrétne pomáha PHP SOS?

  • Nájdeme všetky miesta, kde vaša aplikácia sťahuje adresy, aj v pluginoch a knižniciach.
  • Zostavíme centrálnu funkciu sťahovania so zoznamom povolených, obmedzením protokolov a kontrolou IP.
  • Určíme pravidlá pre odchádzajúcu prevádzku a ochránime služby metadát v cloudových prostrediach.
  • Zavedenie preveríme zvonka a zdokumentujeme povolené ciele.

Nezávislú kontrolu vašej aplikácie opisuje Bezpečnostný audit a penetračný test.

Časté otázky

Ktoré funkcie PHP sa dajú zneužiť na SSRF?

Všetky, ktoré sťahujú adresu zo vstupov používateľa: cURL, file_get_contents a fopen s wrappermi URL, funkcie pre obrázky a XML, ktoré načítavajú vzdialené súbory, ako aj knižnice pre webhooky, kanály alebo náhľady odkazov.

Stačí zablokovať interné adresy IP?

Samotné nie. OWASP označuje zoznamy zakázaných hodnôt za náchylné na obídenie a odporúča zoznamy povolených. Aplikácia navyše musí použiť presne tú adresu, ktorú skontrolovala, a nesmie nasledovať presmerovania.

Prečo je SSRF v cloude obzvlášť kritické?

Poskytovatelia cloudu sprístupňujú inštanciám interné služby metadát, cez ktoré sa čiastočne dajú získať prístupové údaje. Ak aplikácia môže tam posielať požiadavky, môže sa útočník cez ňu k týmto údajom dostať. Poskytovatelia ponúkajú spevnené varianty týchto služieb, ktoré by mali byť zapnuté.

Čo prinesie firewall pre odchádzajúcu prevádzku?

Obmedzuje, aké ciele môže server vôbec dosiahnuť. Aj keď zlyhá kontrola v kóde, interné systémy zostanú nedosiahnuteľné. Okrem toho po vlámaní sťažuje dosťahovanie škodlivého kódu a odtok údajov.

Zdroje

Okamžitý kontakt

Každá hodina sa počíta. Napíšte nám hneď.

Stručne opíšte systém, verziu PHP a svoje pozorovanie. Ozveme sa, vyjasníme situáciu a budeme pracovať na diaľku, kým nebude incident uzavretý a zdokumentovaný.

Okamžitá pomoc