Trenutno stanje: PHP2Shell. Dve kritični ranljivosti PHP (CVSS 9,2) omogočata izvedbo škodljive kode brez prijave. Popravki od 21. 10. 2026.Kaj je zdaj treba storiti →

Preprečevanje Server-Side Request Forgery (SSRF) v PHP

Kako razvijalci preprečijo, da bi aplikacija PHP po naročilu tujcev poizvedovala po notranjih sistemih: dovoljeni seznami, omejitev protokolov, preverjanje razrešenega naslova in meje v omrežju.

Stanje 5 min branjaVaren razvoj

Na kratko: SSRF v PHP preprečite tako, da vaša aplikacija pridobiva samo naslove s stalnega dovoljenega seznama, izključno prek HTTPS in brez sledenja preusmeritvam. Razrešeni naslov IP se preveri proti zasebnim in rezerviranim območjem in nato za povezavo zadrži. Požarni zid za odhodni promet poskrbi, da notranji sistemi ostanejo nedosegljivi tudi ob napaki v kodi.

Kadar lasten strežnik pošilja zahteve za tujce

Predogledi povezav v klepetu, uvoz slike izdelka prek URL, webhooki k partnerskim sistemom, bralnik virov v CMS: številne aplikacije PHP pridobivajo naslove, ki jih je vnesel uporabnik. To je uporabna funkcija in hkrati vrata navznoter.

Pri Server-Side Request Forgery, na kratko SSRF, napadalec aplikacijo prisili, da pošlje zahtevo na cilj po njegovi izbiri. Poanta: zahteva prihaja od samega strežnika. Tako doseže sisteme, ki so od zunaj zaprti, na primer baze podatkov, upravljalske vmesnike v notranjem omrežju, storitve, ki poslušajo samo na localhost, ali storitve z metapodatki ponudnikov oblaka.

V OWASP Top 10 iz leta 2021 je bil SSRF lastna kategorija. V projektih PHP se ranljivost pogosto pojavi tam, kjer je nekdo hitro zgradil funkcijo „dodaj sliko prek URL“.

SSRF v PHP: katere funkcije pridobivajo naslove

Naslove ne pridobiva samo cURL. Na naslednja mesta bodite pozorni:

Funkcija ali področje Zakaj je pomembno
cURL (curl_exec()) najpogostejša pot, mogočih je veliko protokolov
file_get_contents(), fopen(), copy() z URL uporabljajo ovojnice URL, če je allow_url_fopen aktiven
getimagesize() in knjižnice za slike lahko naložijo oddaljene datoteke
obdelava XML, odjemalci SOAP včasih naložijo zunanje vire
knjižnice HTTP, kot je Guzzle temeljijo na cURL ali tokovih, enaka pravila

Če vaša aplikacija ne potrebuje odpiranja oddaljenih datotek prek datotečnih funkcij, allow_url_fopen izklopite na strežniku. Sorodno temo, vključevanje datotek prek poti iz zahteve, obravnava vodnik Preprečevanje Local in Remote File Inclusion.

Obramba v petih korakih

OWASP priporoča kombinacijo ukrepov, ki bi jih vsakega posebej lahko obšli, skupaj pa držijo:

  1. Dovoljeni seznam namesto prostega URL: Najbolje je, da uporabnik izbira samo med znanimi cilji ali navede le oznako, naslov pa aplikacija sestavi sama.
  2. Dovolite samo HTTPS: druge protokole, kot so file, gopher ali ftp, v cURL izključite, tudi za preusmeritve.
  3. Ne sledite preusmeritvam: dovoljen naslov sicer lahko preusmeri na notranji cilj.
  4. Razrešeni naslov preverite in zadržite: razrešite ime gostitelja, IP preverite proti zasebnim območjem, območju povratne zanke (loopback) in območjem link-local ter za povezavo uporabite natanko ta IP. Sicer lahko drugo razreševanje DNS vrne drug cilj.
  5. Omejite omrežje: spletni strežnik sme navzven doseči samo cilje, ki jih potrebuje.

Varen vzorec s cURL

Naslednji primer izvaja korake od 1 do 4 za IPv4. Imena gostiteljev in potek so primeri; za IPv6 veljajo enaka preverjanja.

<?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;
}

Nekaj podrobnosti je pomembnih. gethostbyname() ob napaki vrne ime gostitelja; naknadno preverjanje IP to ujame. Zastavici FILTER_FLAG_NO_PRIV_RANGE in FILTER_FLAG_NO_RES_RANGE po priročniku PHP med drugim izključita območja 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8 in 169.254.0.0/16. Od PHP 8.2 obstaja dodatno FILTER_FLAG_GLOBAL_RANGE, ki dopušča samo globalno veljavne naslove. CURLOPT_RESOLVE poskrbi, da cURL uporabi natanko preverjeni naslov, ime gostitelja in preverjanje potrdila pa ostaneta.

Dve nadaljnji točki omejita, kaj se napadalec nauči iz ranljivosti SSRF. Odgovorov in sporočil o napakah pridobljenega cilja ne vračajte uporabniku nefiltrirano: že razlika med „povezava zavrnjena“ in „časovna omejitev“ izda, katere notranje storitve obstajajo. In omejite trajanje ter velikost odgovora, da funkcija ni uporabna za preobremenitev lastnega strežnika. Webhooke na naslove, ki jih stranke vnesejo same, najbolje pošiljajte iz čakalne vrste in ne med tekočo zahtevo.

Pomembno

Če mora vaša aplikacija res pridobivati poljubne naslove, na primer za predoglede povezav, to funkcijo prestavite v ločeno storitev brez dostopa do notranjega omrežja. Dovoljeni seznam takrat ni mogoč, ločitev omrežja pa je toliko pomembnejša.

Omrežna raven kot varnostna mreža

Preverjanja v kodi imajo lahko vrzeli, na primer če dve knjižnici URL razčlenita različno. OWASP svetuje, da se take neskladnosti obravnavajo kot zavrnitev, in dodatno omejitev na omrežni ravni. Spletni strežnik navzven večinoma potrebuje le nekaj ciljev: vire paketov, ponudnike plačil in dostave, poštni relay, določene vmesnike.

Požarni zid za odhodni promet pomaga dvojno. Ustavi zahteve SSRF v notranje omrežje in po vdoru, na primer prek nepopravljene različice PHP, oteži nalaganje nadaljnjih orodij. Kako zgradite pravila, opisuje Požarni zid za spletni strežnik: odprite samo potrebna vrata. Katere povezave strežnik dejansko vzpostavlja, pokaže Preverjanje odhodnih povezav strežnika.

V okoljih oblaka sodi zraven utrjena različica storitve z metapodatki. OWASP za AWS navaja prehod na IMDSv2 in izklop IMDSv1.

Iskanje SSRF v obstoječi kodi

Hiter začetek je iskanje mest, kjer funkcije za pridobivanje prejmejo vrednosti iz zahteve:

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"

Zadetki so naloge za preverjanje. Še posebej temeljito poglejte funkcije, ki jih uporabljajo skrbniki: uvoze, nastavitve webhookov, preverjanja posodobitev vtičnikov.

Zlahka se spregledajo generatorji PDF, ki HTML z vključenimi slikami ali slogovnimi listi pretvorijo v dokumente. Če del tega HTML izvira iz uporabniških vnosov, na primer pri računih s prosto izbranim logotipom, generator morda pridobiva naslove, ki jih določi uporabnik. Tam preverite nastavitve za nalaganje oddaljenih virov in jih izklopite, če jih ne potrebujete.

Kako konkretno pomaga PHP SOS?

  • Poiščemo vsa mesta, kjer vaša aplikacija pridobiva naslove, tudi v vtičnikih in knjižnicah.
  • Zgradimo osrednjo funkcijo za pridobivanje z dovoljenim seznamom, omejitvijo protokolov in preverjanjem IP.
  • Določimo pravila za odhodni promet in zaščitimo storitve z metapodatki v okoljih oblaka.
  • Izvedbo preverimo od zunaj in dokumentiramo dovoljene cilje.

Neodvisen pregled vaše aplikacije opisuje Varnostni pregled in penetracijski test.

Pogosta vprašanja

Katere funkcije PHP je mogoče zlorabiti za SSRF?

Vse, ki pridobivajo naslov iz uporabniških vnosov: cURL, file_get_contents in fopen z ovojnicami URL, funkcije za slike in XML, ki nalagajo oddaljene datoteke, ter knjižnice za webhooke, vire (feed) ali predoglede povezav.

Ali zadošča blokiranje notranjih naslovov IP?

Samo po sebi ne. OWASP črne sezname označuje kot lahko obvozne in priporoča dovoljene sezname. Poleg tega mora aplikacija uporabiti natanko naslov, ki ga je preverila, in ne sme slediti preusmeritvam.

Zakaj je SSRF v oblaku posebej kritičen?

Ponudniki oblaka instancam dajejo na voljo notranje storitve z metapodatki, prek katerih je deloma mogoče pridobiti dostopne podatke. Če lahko aplikacija tja pošilja zahteve, napadalec prek nje te podatke doseže. Ponudniki ponujajo utrjene različice teh storitev, ki naj bodo vklopljene.

Kaj prinese požarni zid za odhodni promet?

Omeji, katere cilje strežnik sploh lahko doseže. Tudi če preverjanje v kodi odpove, notranji sistemi ostanejo nedosegljivi. Poleg tega po vdoru oteži nalaganje škodljive kode in odtekanje podatkov.

Viri

Takojšnji stik

Vsaka ura šteje. Pišite nam zdaj.

Na kratko opišite sistem, različico PHP in opažanje. Odzovemo se, razjasnimo stanje in delamo na daljavo, dokler incident ni zaključen in dokumentiran.

Takojšnja pomoč