Aktuālā situācija: PHP2Shell. Divas kritiskas PHP ievainojamības (CVSS 9.2) ļauj izpildīt ļaunprātīgu kodu bez pieteikšanās. Ielāpi kopš 21.10.2026.Kas jādara tagad →

Server-Side Request Forgery (SSRF) novēršana PHP

Kā izstrādātāji novērš, ka PHP lietojumprogramma svešu personu uzdevumā vaicā iekšējās sistēmas: atļauju saraksti, protokolu ierobežojums, atrisinātās adreses pārbaude un tīkla robežas.

Aktuāls uz 5 min lasīšanas laiksDroša izstrāde

Īsi sakot: SSRF PHP novērš, panākot, ka jūsu lietojumprogramma atver tikai adreses, kas ir fiksētā atļauju sarakstā, vienīgi pa HTTPS un nesekojot pāradresācijām. Atrisinātā IP adrese tiek pārbaudīta pret privātajiem un rezervētajiem diapazoniem un pēc tam savienojumam nofiksēta. Ugunsmūris izejošajai satiksmei nodrošina, ka iekšējās sistēmas paliek nesasniedzamas arī tad, ja kodā ir kļūda.

Kad paša serveris svešiem uzdod pieprasījumus

Saišu priekšskatījumi tērzētavā, produkta attēla imports pēc URL, webhook uz partneru sistēmām, barotņu lasītājs CMS: daudzas PHP lietojumprogrammas atver adreses, ko norādījis lietotājs. Tā ir noderīga funkcija un reizē durvis uz iekšpusi.

Server-Side Request Forgery, saīsināti SSRF, gadījumā uzbrucējs panāk, ka lietojumprogramma nosūta pieprasījumu uz viņa izvēlētu mērķi. Triks: pieprasījums nāk no paša servera. Tādējādi tiek sasniegtas sistēmas, kas no ārpuses ir slēgtas, piemēram, datubāzes, administrēšanas saskarnes iekšējā tīklā, pakalpojumi, kas klausās tikai localhost, vai mākoņa sniedzēju metadatu pakalpojumi.

OWASP Top 10 2021. gada izdevumā SSRF bija sava kategorija. PHP projektos ievainojamība bieži parādās tur, kur kāds steigā izveidojis funkciju „pievienot attēlu pēc URL".

SSRF PHP: kuras funkcijas atver adreses

Adreses atver ne tikai cURL. Šīs vietas jums jāpatur acīs:

Funkcija vai joma Kāpēc svarīga
cURL (curl_exec()) biežākais ceļš, iespējami daudzi protokoli
file_get_contents(), fopen(), copy() ar URL izmanto URL apvalkus, ja allow_url_fopen ir aktīvs
getimagesize() un attēlu bibliotēkas var ielādēt attālus failus
XML apstrāde, SOAP klienti zināmos apstākļos ielādē ārējus resursus
HTTP bibliotēkas, piemēram, Guzzle balstās uz cURL vai straumēm, tie paši noteikumi

Ja jūsu lietojumprogrammai nav jāatver attālie faili ar failu funkcijām, izslēdziet allow_url_fopen servera pusē. Radniecīgu tēmu, failu iekļaušanu pēc ceļiem no pieprasījuma, aplūko ceļvedis Local un Remote File Inclusion novēršana.

Aizsardzība piecos soļos

OWASP iesaka pasākumu kombināciju, kur katru atsevišķi varētu apiet, bet kopā tie notur:

  1. Atļauju saraksts, nevis brīvs URL: vislabāk lietotājs izvēlas tikai no zināmiem mērķiem vai norāda tikai identifikatoru, un lietojumprogramma adresi izveido pati.
  2. Atļaut tikai HTTPS: citus protokolus, piemēram, file, gopher vai ftp, cURL izslēgt, arī pāradresācijām.
  3. Nesekot pāradresācijām: atļauta adrese citādi var novirzīt uz iekšēju mērķi.
  4. Pārbaudīt un nofiksēt atrisināto adresi: atrisināt hostvārdu, pārbaudīt IP pret privātajiem, loopback un link-local diapazoniem un savienojumam izmantot tieši šo IP. Citādi otra DNS atrisināšana var dot citu mērķi.
  5. Ierobežot tīklu: tīmekļa serveris uz āru drīkst sasniegt tikai tos mērķus, kas tam vajadzīgi.

Drošs paraugs ar cURL

Turpmākais piemērs īsteno 1. līdz 4. soli IPv4. Hostvārdi un gaita ir piemēri; IPv6 ir spēkā tās pašas pārbaudes.

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

Daži sīkumi ir svarīgi. gethostbyname() kļūdas gadījumā atdod hostvārdu; nākamā IP pārbaude to uztver. Karogi FILTER_FLAG_NO_PRIV_RANGE un FILTER_FLAG_NO_RES_RANGE saskaņā ar PHP rokasgrāmatu cita starpā izslēdz diapazonus 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8 un 169.254.0.0/16. Kopš PHP 8.2 ir arī FILTER_FLAG_GLOBAL_RANGE, kas pieļauj tikai globāli derīgas adreses. CURLOPT_RESOLVE nodrošina, ka cURL izmanto tieši pārbaudīto adresi, kamēr hostvārds un sertifikāta pārbaude tiek saglabāti.

Divi citi punkti ierobežo to, ko uzbrucējs no SSRF ievainojamības var uzzināt. Neatdodiet atvērtā mērķa atbildes un kļūdu ziņojumus lietotājam nefiltrētus: jau starpība starp „savienojums noraidīts" un „laika pārsniegšana" izpauž, kādi iekšējie pakalpojumi pastāv. Un ierobežojiet atbildes darbības laiku un izmēru, lai funkcija nederētu paša servera pārslogošanai. Webhook uz adresēm, ko klienti ievada paši, labāk sūtīt no rindas, nevis notiekošā pieprasījuma laikā.

Svarīgi

Ja jūsu lietojumprogrammai tiešām jāatver patvaļīgas adreses, piemēram, saišu priekšskatījumiem, šo funkciju izceliet atsevišķā pakalpojumā bez piekļuves iekšējam tīklam. Atļauju saraksts tad nav iespējams, un tīkla nodalīšana ir vēl svarīgāka.

Tīkla līmenis kā drošības tīkls

Koda pārbaudēs var būt nepilnības, piemēram, ja divas bibliotēkas URL sadala atšķirīgi. OWASP iesaka šādas nesakritības vērtēt kā noraidījumu un papildus ierobežot tīkla līmenī. Tīmekļa serverim uz āru parasti vajag tikai nedaudz mērķu: pakotņu avoti, maksājumu un piegādes pakalpojumu sniedzēji, pasta relejs, noteiktas saskarnes.

Ugunsmūris izejošajai satiksmei palīdz divkārši. Tas aptur SSRF pieprasījumus uz iekšējo tīklu, un tas pēc ielaušanās, piemēram, caur neielāpotu PHP versiju, apgrūtina citu rīku lejupielādi. Kā noteikumus veidot, apraksta Ugunsmūris tīmekļa serverim: atvērt tikai nepieciešamos portus. Kādus savienojumus serveris patiešām veido, parāda Servera izejošo savienojumu pārbaude.

Mākoņa vidēs klāt nāk metadatu pakalpojuma nostiprinātais variants. OWASP AWS gadījumā min pāreju uz IMDSv2 un IMDSv1 izslēgšanu.

SSRF atklāšana esošajā kodā

Ātrs sākums ir to vietu meklēšana, kur atvēršanas funkcijas saņem vērtības no pieprasījuma:

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"

Trāpījumi ir pārbaudes uzdevumi. Īpaši rūpīgi aplūkojiet funkcijas, ko lieto administratori: importus, webhook iestatījumus, spraudņu atjauninājumu pārbaudes.

Viegli pārskatāmi ir PDF ģeneratori, kas HTML ar iegultiem attēliem vai stila lapām pārvērš dokumentos. Ja daļa šī HTML nāk no lietotāju ievades, piemēram, rēķinos ar brīvi izvēlētu logotipu, ģenerators zināmos apstākļos atver adreses, ko nosaka lietotājs. Pārbaudiet tur iestatījumus attālo resursu ielādei un izslēdziet to, ja tas nav vajadzīgs.

Kā PHP SOS palīdz konkrēti?

  • Mēs atrodam visas vietas, kur jūsu lietojumprogramma atver adreses, arī spraudņos un bibliotēkās.
  • Mēs izveidojam centrālu atvēršanas funkciju ar atļauju sarakstu, protokolu ierobežojumu un IP pārbaudi.
  • Mēs nosakām noteikumus izejošajai satiksmei un aizsargājam metadatu pakalpojumus mākoņa vidēs.
  • Mēs pārbaudām ieviešanu no ārpuses un dokumentējam atļautos mērķus.

Neatkarīgu jūsu lietojumprogrammas pārbaudi apraksta drošības audits un penetrācijas tests.

Biežāk uzdotie jautājumi

Kuras PHP funkcijas var tikt ļaunprātīgi izmantotas SSRF?

Visas, kas atver adresi no lietotāja ievades: cURL, file_get_contents un fopen ar URL apvalkiem, attēlu un XML funkcijas, kas ielādē attālus failus, kā arī bibliotēkas webhook, barotnēm vai saišu priekšskatījumiem.

Vai pietiek ar iekšējo IP adrešu bloķēšanu?

Pati par sevi nē. OWASP bloķēšanas sarakstus dēvē par apejamiem un iesaka atļauju sarakstus. Papildus lietojumprogrammai jāizmanto tieši tā adrese, ko tā pārbaudījusi, un jāatsakās sekot pāradresācijām.

Kāpēc SSRF mākonī ir īpaši kritiska?

Mākoņa sniedzēji instancēm nodrošina iekšējus metadatu pakalpojumus, caur kuriem daļēji iespējams iegūt piekļuves datus. Ja lietojumprogramma tur var sūtīt pieprasījumus, uzbrucējs caur to var sasniegt šos datus. Sniedzēji piedāvā šo pakalpojumu nostiprinātus variantus, kas jāieslēdz.

Ko dod ugunsmūris izejošajai satiksmei?

Tas ierobežo, kurus mērķus serveris vispār var sasniegt. Pat ja pārbaude kodā neizdodas, iekšējās sistēmas paliek nesasniedzamas. Turklāt tas pēc ielaušanās apgrūtina ļaunprātīga koda lejupielādi un datu aizplūšanu.

Avoti

Tūlītējs kontakts

Katra stunda ir svarīga. Rakstiet mums tūlīt.

Īsi aprakstiet sistēmu, PHP versiju un novēroto. Mēs sazināsimies, noskaidrosim situāciju un strādāsim attālināti, līdz incidents ir slēgts un dokumentēts.

Tūlītēja palīdzība