Aktuel situation: PHP2Shell. To kritiske PHP-sårbarheder (CVSS 9,2) tillader skadelig kode uden login. Rettelser siden 21.10.2026.Hvad der skal gøres nu →

Sikr REST-API'er i PHP

Grænseflader er ofte dårligere beskyttet end websitet foran dem. De vigtigste regler for REST-API'er i PHP, fra objektrettigheder til hastighedsbegrænsning.

Status 5 min. læsetidSikker udvikling

Kort sagt: For API-sikkerheden i PHP tæller først og fremmest fem punkter: kun HTTPS, autentificering ved hvert ikke-offentligt endepunkt, rettighedskontrol for hvert enkelt objekt, strikse grænser for metode, indholdstype og forespørgslens størrelse samt kortfattede fejlmeddelelser uden interne detaljer. Dertil kommer hastighedsbegrænsning og en log over sikkerhedsrelevante hændelser. Mod sårbarheder i selve PHP-fortolkeren som PHP2Shell hjælper det ikke; til det kræves PHP-opdateringen.

Grænsefladen bag websitet

Mange virksomheder har i ugen efter 21.10.2026 kontrolleret deres websites. Grænsefladerne bag stod sjældnere på listen. Og netop dér kører følsomme forløb: Kundeportalens app henter fakturaer, varelagersystemet skriver beholdninger ind i shoppen, en partner melder ordrer via webhook. Ofte blev disse API'er bygget hurtigt, til et enkelt formål, og blev derefter aldrig set på igen.

En API har ingen flade, som gør fejl synlige. En manglende rettighedskontrol falder ingen i øjnene i hverdagen, så længe alle klienter kun forespørger det, de skal. En angriber prøver derimod netop det, der ikke er tiltænkt.

Første trin er derfor en opgørelse. Hvilke endepunkter findes overhovedet? Ofte findes gamle versioner som /api/v1/, der aldrig blev slukket efter omstillingen til /v2/, testendepunkter fra udviklingen eller en offentligt tilgængelig grænsefladebeskrivelse, der opregner interne funktioner. Hvert endepunkt, der ikke længere er brug for, bør slukkes. Hvert, der forbliver, har brug for en ansvarlig.

API-sikkerhed i PHP: grundreglerne

OWASP REST Security Cheat Sheet sammenfatter gennemprøvede regler. For PHP-projekter kan de oversættes til en kort liste:

  1. Kun HTTPS. Tokens og adgangsdata må aldrig overføres ukrypteret.
  2. Hvert endepunkt kontrollerer selv. Autentificeringen kan ske centralt, beslutningen om adgang træffes ved endepunktet.
  3. Rettighed pr. objekt. Ikke blot "er logget ind", men "må netop dette datasæt".
  4. Fastlæg tilladte metoder. Det, der ikke udtrykkeligt er tilladt, afvises med 405.
  5. Kontrollér indholdstype og størrelse. Forkert type giver 415, for store forespørgsler 413.
  6. Valider input. Type, længde, format og værdiområde, på serversiden.
  7. Ingen hemmeligheder i URL'er. Tokens og nøgler hører hjemme i headere, ikke i query-strengen.
  8. Kortfattede fejl. Ingen stacktraces, stier eller SQL-meldinger til klienten.
  9. Hastighedsbegrænsning. For mange forespørgsler besvares med 429.
  10. Afskærm administrationsendepunkter. Ikke offentligt tilgængelige eller kun med stærkt login.

Objektrettighed: den hyppigste fejl

Et eksempel gør problemet håndgribeligt. Et endepunkt leverer fakturaer under /api/rechnungen/{id}. Der kontrolleres, om der foreligger et gyldigt token. Der kontrolleres ikke, om fakturaen hører til tokenets kunde. Den, der forhøjer sit eget fakturanummer med én, ser nabo'ens faktura.

Løsningen er enkel og skal alligevel gennemføres på hvert sted: Selve forespørgslen indskrænker til det berettigede område.

<?php
// Tillad kun metoden GET
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
    http_response_code(405);
    header('Allow: GET');
    exit;
}

$kundeId = $auth->kundeId();          // fra det kontrollerede token
$id = filter_var($routeId, FILTER_VALIDATE_INT);
if ($id === false) {
    http_response_code(400);
    exit;
}

// Rettigheden ligger i forespørgslen: kun egne fakturaer
$stmt = $pdo->prepare('SELECT nummer, betrag, datum FROM rechnungen WHERE id = ? AND kunde_id = ?');
$stmt->execute([$id, $kundeId]);
$rechnung = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$rechnung) {
    http_response_code(404);           // afslør ikke, om ID'et findes
    exit;
}

header('Content-Type: application/json');
echo json_encode($rechnung, JSON_THROW_ON_ERROR);

Forespørgslen med pladsholdere beskytter samtidig mod SQL-injection, se Forhindr SQL-injection i PHP. Hvordan PHP stiller forespørgselsdata som metode, header og body til rådighed, forklarer Superglobals: $_GET, $_POST, $_FILES og co..

Kontrollér tokens rigtigt

Mange API'er arbejder med JSON Web Tokens. OWASP Cheat Sheet nævner hertil klare regler: Tokens skal være signeret, usignerede tokens afvises, og algoritmen til kontrollen fastlægges på serveren og overtages ikke fra tokenet. Udsteder, målgruppe og udløbstid hører ligeledes med til kontrollen. Brug hertil et vedligeholdt bibliotek i stedet for egne implementeringer.

Egne tokens, f.eks. til webhooks eller engangslinks, skal stamme fra en kryptografisk sikker tilfældighedsgenerator og sammenlignes i konstant tid. Hvordan det gøres i PHP, viser Sikre tilfældige tal og tokens i PHP.

Tip

Giv hver klient og hver partner en egen nøgle med netop de rettigheder, den har brug for. Så kan en nøgle, der er sluppet ud, spærres enkeltvis uden at afbryde alle andre tilslutninger.

Sæt grænser: størrelse, type og tempo

En API bør kun modtage det, den forventer. Det begynder med indholdstypen: Et endepunkt, der behandler JSON, afviser alt andet. Den maksimale størrelse på en forespørgsel begrænser I på flere niveauer, i webserveren og i PHP via post_max_size. Denne grænse hører også til de overgangsforanstaltninger, som php.net har nævnt til PHP2Shell. Hvordan man vælger den fornuftigt, beskriver Begræns post_max_size og upload_max_filesize fornuftigt.

Hastighedsbegrænsning beskytter mod gætteri af identifikatorer og mod overbelastning. Den kan gennemføres i webserveren, i en forudgående proxy eller i applikationen. Vigtigt er, at grænser gælder pr. nøgle eller bruger og ikke kun pr. IP-adresse.

For API'er, der kaldes direkte fra browseren, kommer CORS til, altså reglerne for, hvilke fremmede websites der må stille forespørgsler. Sæt kun disse headere, hvis sådanne kald virkelig er tiltænkt, og nævn de tilladte oprindelser enkeltvis i stedet for at tillade enhver oprindelse. En jokertegn, der tillader alle websites, er ved endepunkter med login næsten altid en fejl.

Til sidst loggen: Mislykkede logins, afviste tokens og nægtede adgange hører hjemme i loggen, tokens selv gør ikke. Uden disse poster forbliver et angreb på API'en usynligt.

Hvordan hjælper PHP SOS konkret?

  • Vi registrerer alle grænseflader i jeres PHP-systemer, også glemte og interne, og kontrollerer, hvilke der er offentligt tilgængelige.
  • Vi læser rettighedslogikken og tester målrettet, om fremmede datasæt kan hentes.
  • Vi sætter grænser for størrelse, type og tempo i webserver og PHP og afstemmer dem med jeres klienter.
  • Til en omfattende kontrol udefra kombinerer vi det med sikkerhedsaudit og penetrationstest.

Konklusion: En API er så sikker som sit sjusseligste endepunkt. Den, der kontrollerer rettigheder pr. objekt, sætter klare grænser og holder fejl kortfattede, lukker de hyppigste sårbarheder, længe før nogen søger målrettet efter dem.

Ofte stillede spørgsmål

Er en API-nøgle nok som beskyttelse?

Ikke til følsomme data. En API-nøgle identificerer som regel en applikation, ikke en bruger, og gives let videre. OWASP REST Security Cheat Sheet råder til ikke at bruge API-nøgler som eneste beskyttelse af følsomme ressourcer.

Hvad er en objektrettighed, og hvorfor mangler den så ofte?

Der menes kontrollen af, om den loggede bruger må se eller ændre netop dette datasæt. Den mangler ofte, fordi udviklere kun kontrollerer, om nogen overhovedet er logget ind. Så er det nok at ændre en identifikator i URL'en for at hente fremmede data.

Beskytter en godt sikret API mod PHP2Shell?

Nej. PHP2Shell sidder i PHP-fortolkeren og virker ved berørte driftsformer, før jeres kode overhovedet kører. Mod det hjælper kun en PHP-opdatering med genstart. Størrelsesgrænser for forespørgsler er alligevel fornuftige og hører også til php.nets overgangsforanstaltninger.

Hvilke statuskoder bør en API levere ved sikkerhedsfejl?

Almindelige er 401 uden gyldigt login, 403 ved manglende rettighed, 405 ved ikke tilladt metode, 413 ved for stor forespørgsel, 415 ved forkert indholdstype og 429 ved for mange forespørgsler. Selve svaret forbliver kortfattet og uden interne detaljer.

Kilder

Akut kontakt

Hver time tæller. Skriv til os nu.

Beskriv kort system, PHP-version og observation. Vi vender tilbage, afklarer situationen og arbejder på afstand, indtil hændelsen er afsluttet og dokumenteret.

Akut hjælp