Aktuellt läge: PHP2Shell. Två kritiska PHP-sårbarheter (CVSS 9,2) tillåter skadlig kod utan inloggning. Patchar sedan den 21 oktober 2026.Vad som bör göras nu →

Förhindra Server-Side Request Forgery (SSRF) i PHP

Hur utvecklare förhindrar att en PHP-applikation på uppdrag av främlingar frågar efter interna system: tillåtelselistor, protokollbegränsning, kontroll av den upplösta adressen och gränser i nätverket.

Aktualitet 5 min läsningSäker utveckling

Kort sagt: SSRF i PHP förhindrar ni genom att er applikation bara hämtar adresser som står på en fast tillåtelselista, uteslutande via HTTPS och utan att följa omdirigeringar. Den upplösta IP-adressen kontrolleras mot privata och reserverade områden och hålls sedan fast för anslutningen. En brandvägg för utgående trafik ser till att interna system förblir onåbara även vid ett fel i koden.

När den egna servern ställer förfrågningar åt främlingar

Länkförhandsvisningar i en chatt, import av en produktbild via URL, webhooks till partnersystem, en flödesläsare i CMS:et: Många PHP-applikationer hämtar adresser som en användare har angett. Det är en nyttig funktion och samtidigt en dörr inåt.

Vid Server-Side Request Forgery, kort SSRF, får en angripare applikationen att skicka en förfrågan till ett mål efter eget val. Poängen: Förfrågan kommer från servern själv. Den når därmed system som är spärrade utifrån, till exempel databaser, administrationsgränssnitt i det interna nätet, tjänster som bara lyssnar på localhost eller molnleverantörers metadatatjänster.

I OWASP Top 10 från 2021 var SSRF en egen kategori. I PHP-projekt dyker sårbarheten ofta upp där någon snabbt har byggt en funktion för att ”lägga till bild via URL”.

SSRF i PHP: vilka funktioner som hämtar adresser

Det är inte bara cURL som hämtar adresser. Följande ställen bör ni ha uppsikt över:

Funktion eller område Varför relevant
cURL (curl_exec()) vanligaste vägen, många protokoll möjliga
file_get_contents(), fopen(), copy() med URL använder URL-wrappers när allow_url_fopen är aktivt
getimagesize() och bildbibliotek kan ladda fjärrfiler
XML-bearbetning, SOAP-klienter laddar under vissa omständigheter externa resurser
HTTP-bibliotek som Guzzle bygger på cURL eller streams, samma regler

Behöver er applikation inte öppna fjärrfiler via filfunktioner, stäng av allow_url_fopen på serversidan. Ett närliggande ämne, inkludering av filer via sökvägar från förfrågan, behandlar guiden Förhindra local och remote file inclusion.

Försvaret i fem steg

OWASP rekommenderar en kombination av åtgärder som var för sig skulle kunna kringgås men tillsammans håller:

  1. Tillåtelselista i stället för fri URL: Bäst är att användaren bara väljer bland kända mål, eller bara anger en identifierare, och applikationen bygger adressen själv.
  2. Tillåt bara HTTPS: Uteslut andra protokoll som file, gopher eller ftp i cURL, även för omdirigeringar.
  3. Följ inga omdirigeringar: En tillåten adress kan annars omdirigera till ett internt mål.
  4. Kontrollera och håll fast den upplösta adressen: Slå upp värdnamnet, kontrollera IP-adressen mot privata områden, loopback och link-local-områden och använd exakt den IP-adressen för anslutningen. Annars kan en andra DNS-uppslagning ge ett annat mål.
  5. Begränsa nätverket: Webbservern får nå utåt bara de mål den behöver.

Ett säkert mönster med cURL

Följande exempel genomför steg 1 till 4 för IPv4. Värdnamn och förlopp är exempel; för IPv6 gäller samma kontroller.

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

Några detaljer är viktiga. gethostbyname() returnerar vid fel värdnamnet; den efterföljande IP-kontrollen fångar upp det. Flaggorna FILTER_FLAG_NO_PRIV_RANGE och FILTER_FLAG_NO_RES_RANGE utesluter enligt PHP-manualen bland annat områdena 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8 och 169.254.0.0/16. Sedan PHP 8.2 finns dessutom FILTER_FLAG_GLOBAL_RANGE, som bara tillåter globalt giltiga adresser. CURLOPT_RESOLVE ser till att cURL använder exakt den kontrollerade adressen, medan värdnamn och certifikatkontroll bevaras.

Ytterligare två punkter begränsar vad en angripare lär sig av en SSRF-sårbarhet. Returnera inte det hämtade målets svar och felmeddelanden ofiltrerat till användaren: Redan skillnaden mellan ”anslutning nekad” och ”tidsgräns överskriden” avslöjar vilka interna tjänster som finns. Och begränsa körtid och storlek på svaret så att funktionen inte kan användas för att överbelasta den egna servern. Webhooks till adresser som kunder själva anger skickar ni bäst från en kö och inte under den pågående förfrågan.

Viktigt

Måste er applikation verkligen hämta godtyckliga adresser, till exempel för länkförhandsvisningar, lägg ut den funktionen i en separat tjänst utan tillträde till det interna nätet. En tillåtelselista är då inte möjlig, nätseparationen desto viktigare.

Nätverksnivån som skyddsnät

Kodkontroller kan ha luckor, till exempel när två bibliotek delar upp en URL olika. OWASP råder att behandla sådana inkonsekvenser som avvisning och dessutom begränsa på nätverksnivå. En webbserver behöver utåt oftast bara få mål: paketkällor, betal- och fraktleverantörer, e-postrelä, bestämda gränssnitt.

En brandvägg för utgående trafik hjälper dubbelt. Den stoppar SSRF-förfrågningar in i det interna nätet, och den försvårar efter ett intrång, till exempel via en opatchad PHP-version, att ytterligare verktyg laddas ned. Hur ni bygger upp reglerna beskriver Brandvägg för webbservrar: öppna bara nödvändiga portar. Vilka anslutningar en server faktiskt bygger upp visar Kontrollera en servers utgående anslutningar.

I molnmiljöer hör den härdade varianten av metadatatjänsten dit. OWASP nämner för AWS övergången till IMDSv2 och avstängning av IMDSv1.

Spåra upp SSRF i befintlig kod

En snabb ingång är sökningen efter ställen där hämtningsfunktioner får värden från förfrågan:

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äffar är kontrolluppdrag. Särskilt grundligt bör ni titta på funktioner som administratörer använder: importer, webhook-inställningar, uppdateringskontroller för tillägg.

Lätt att förbise är PDF-generatorer som omvandlar HTML med inbäddade bilder eller stilmallar till dokument. Kommer en del av den HTML-koden från användarinmatning, till exempel vid fakturor med fritt valbar logotyp, hämtar generatorn under vissa omständigheter adresser som användaren bestämmer. Kontrollera där inställningarna för att ladda fjärrresurser och stäng av det om det inte behövs.

Hur hjälper PHP SOS konkret?

  • Vi hittar alla ställen där er applikation hämtar adresser, även i tillägg och bibliotek.
  • Vi bygger en central hämtningsfunktion med tillåtelselista, protokollbegränsning och IP-kontroll.
  • Vi fastställer regler för utgående trafik och skyddar metadatatjänster i molnmiljöer.
  • Vi kontrollerar genomförandet utifrån och dokumenterar tillåtna mål.

En oberoende granskning av er applikation beskriver säkerhetsaudit och penetrationstest.

Vanliga frågor

Vilka PHP-funktioner kan missbrukas för SSRF?

Alla som hämtar en adress från användarinmatning: cURL, file_get_contents och fopen med URL-wrappers, bild- och XML-funktioner som laddar fjärrfiler samt bibliotek för webhooks, flöden eller länkförhandsvisningar.

Räcker det att spärra interna IP-adresser?

Inte ensamt. OWASP betecknar spärrlistor som lätta att kringgå och rekommenderar tillåtelselistor. Dessutom måste applikationen använda exakt den adress den har kontrollerat och får inte följa omdirigeringar.

Varför är SSRF särskilt kritiskt i molnet?

Molnleverantörer ger instanser interna metadatatjänster via vilka inloggningsuppgifter delvis går att hämta. Kan en applikation skicka förfrågningar dit kan en angripare nå dessa data genom den. Leverantörerna erbjuder härdade varianter av dessa tjänster som bör vara aktiverade.

Vad ger en brandvägg för utgående trafik?

Den begränsar vilka mål servern över huvud taget kan nå. Även om en kontroll i koden felar förblir interna system då onåbara. Dessutom försvårar den efter ett intrång att skadlig kod laddas ned och att data läcker ut.

Källor

Direktkontakt

Varje timme räknas. Skriv till oss nu.

Beskriv kort system, PHP-version och observation. Vi hör av oss, klarlägger läget och arbetar på distans tills incidenten är avslutad och dokumenterad.

Direkthjälp