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 →

Säkra REST-API:er i PHP

Gränssnitt är ofta sämre skyddade än webbplatsen framför dem. De viktigaste reglerna för REST-API:er i PHP, från objektbehörighet till hastighetsbegränsning.

Aktualitet 5 min läsningSäker utveckling

Kort sagt: För API-säkerheten i PHP räknas framför allt fem punkter: bara HTTPS, autentisering vid varje icke offentlig slutpunkt, behörighetskontroll för varje enskilt objekt, strikta gränser för metod, innehållstyp och storlek på förfrågan samt kortfattade felmeddelanden utan interna detaljer. Därtill kommer hastighetsbegränsning och en logg över säkerhetsrelevanta händelser. Mot sårbarheter i själva PHP-tolken som PHP2Shell hjälper det inte; för det behövs PHP-uppdateringen.

Gränssnittet bakom webbplatsen

Många företag kontrollerade veckan efter den 21 oktober 2026 sina webbplatser. Gränssnitten bakom stod mer sällan på listan. Ändå sker känsliga förlopp just där: Kundportalens app hämtar fakturor, affärssystemet skriver lagersaldon till butiken, en partner rapporterar order via webhook. Ofta byggdes dessa API:er snabbt, för ett enda ändamål, och sågs sedan aldrig över igen.

Ett API har ingen yta som gör fel synliga. En saknad behörighetskontroll märks i vardagen inte av någon så länge alla klienter bara frågar efter det de ska. En angripare provar däremot just det som inte var avsett.

Första steget är därför en inventering. Vilka slutpunkter finns över huvud taget? Ofta hittar man gamla versioner som /api/v1/ som aldrig stängdes av efter övergången till /v2/, testslutpunkter från utvecklingen eller en offentligt hämtbar gränssnittsbeskrivning som listar interna funktioner. Varje slutpunkt som inte längre behövs bör stängas av. Varje som blir kvar behöver en ansvarig.

API-säkerhet i PHP: grundreglerna

OWASP REST Security Cheat Sheet sammanfattar beprövade regler. För PHP-projekt kan de översättas till en kort lista:

  1. Bara HTTPS. Tokens och inloggningsuppgifter får aldrig överföras okrypterat.
  2. Varje slutpunkt kontrollerar själv. Autentiseringen kan ske centralt, beslutet om åtkomst fattas vid slutpunkten.
  3. Behörighet per objekt. Inte bara ”är inloggad” utan ”får just den här posten”.
  4. Fastställ tillåtna metoder. Det som inte uttryckligen är tillåtet avvisas med 405.
  5. Kontrollera innehållstyp och storlek. Fel typ ger 415, för stora förfrågningar 413.
  6. Validera inmatning. Typ, längd, format och värdeintervall, på serversidan.
  7. Inga hemligheter i URL:er. Tokens och nycklar hör hemma i headers, inte i query-strängen.
  8. Kortfattade fel. Inga stacktraces, sökvägar eller SQL-meddelanden till klienten.
  9. Hastighetsbegränsning. För många förfrågningar besvaras med 429.
  10. Avskärma administrationsslutpunkter. Inte offentligt nåbara eller bara med stark inloggning.

Objektbehörighet: det vanligaste felet

Ett exempel gör problemet greppbart. En slutpunkt levererar fakturor under /api/rechnungen/{id}. Det kontrolleras om ett giltigt token finns. Det kontrolleras inte om fakturan tillhör tokenets kund. Den som höjer sitt eget fakturanummer med ett ser grannens.

Lösningen är enkel och måste ändå genomföras på varje ställe: Själva frågan begränsar till det behöriga området.

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

$kundeId = $auth->kundeId();          // från det kontrollerade tokenet
$id = filter_var($routeId, FILTER_VALIDATE_INT);
if ($id === false) {
    http_response_code(400);
    exit;
}

// Behörigheten ligger i frågan: bara egna fakturor
$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);           // avslöja inte om ID:t finns
    exit;
}

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

Frågan med platshållare skyddar samtidigt mot SQL-injektion, se Förhindra SQL-injektion i PHP. Hur PHP tillhandahåller förfrågningsdata som metod, header och body förklarar Superglobals: $_GET, $_POST, $_FILES med flera.

Kontrollera tokens rätt

Många API:er arbetar med JSON Web Tokens. OWASP:s cheat sheet anger tydliga regler för det: Tokens måste vara signerade, osignerade tokens avvisas, och algoritmen för kontrollen fastställs på servern, den hämtas inte från tokenet. Utfärdare, målgrupp och utgångstid hör också till kontrollen. Använd ett underhållet bibliotek i stället för egna implementeringar.

Egna tokens, till exempel för webhooks eller engångslänkar, måste komma från en kryptografiskt säker slumpgenerator och jämföras i konstant tid. Hur det går till i PHP visar Säkra slumptal och tokens i PHP.

Tips

Ge varje klient och varje partner en egen nyckel med exakt de rättigheter den behöver. Då går en läckt nyckel att spärra enskilt utan att avbryta alla andra anslutningar.

Sätta gränser: storlek, typ och tempo

Ett API bör bara ta emot det det förväntar sig. Det börjar med innehållstypen: En slutpunkt som bearbetar JSON avvisar allt annat. Den maximala storleken på en förfrågan begränsar ni på flera nivåer, i webbservern och i PHP via post_max_size. Den gränsen hör också till de övergångsåtgärder som php.net nämnde för PHP2Shell. Hur man väljer den rimligt beskriver Begränsa post_max_size och upload_max_filesize rimligt.

Hastighetsbegränsning skyddar mot att identifierare provas igenom och mot överbelastning. Den går att genomföra i webbservern, i en förkopplad proxy eller i applikationen. Viktigt är att gränser gäller per nyckel eller användare och inte bara per IP-adress.

För API:er som anropas direkt från webbläsaren tillkommer CORS, alltså reglerna för vilka främmande webbplatser som får ställa förfrågningar. Sätt de headerna bara om sådana anrop verkligen är avsedda, och ange de tillåtna ursprungen enskilt i stället för att tillåta varje ursprung. En jokertecken som tillåter alla webbplatser är vid slutpunkter med inloggning nästan alltid ett fel.

Till sist loggen: Misslyckade inloggningar, avvisade tokens och nekade åtkomster hör hemma i loggen, tokens själva gör det inte. Utan dessa poster förblir ett angrepp på API:et osynligt.

Hur hjälper PHP SOS konkret?

  • Vi registrerar alla gränssnitt i era PHP-system, även bortglömda och interna, och kontrollerar vilka som är offentligt nåbara.
  • Vi läser behörighetslogiken och testar målinriktat om främmande poster går att hämta.
  • Vi sätter gränser för storlek, typ och tempo i webbserver och PHP och stämmer av dem med era klienter.
  • För en omfattande kontroll utifrån kombinerar vi det med säkerhetsaudit och penetrationstest.

Slutsats: Ett API är så säkert som dess slarvigaste slutpunkt. Den som kontrollerar behörigheter per objekt, sätter tydliga gränser och håller felen kortfattade stänger de vanligaste luckorna långt innan någon söker efter dem målinriktat.

Vanliga frågor

Räcker en API-nyckel som skydd?

Inte för känsliga data. En API-nyckel identifierar oftast en applikation, inte en användare, och lämnas lätt vidare. OWASP REST Security Cheat Sheet råder att inte använda API-nycklar som enda skydd för känsliga resurser.

Vad är en objektbehörighet och varför saknas den så ofta?

Det avser kontrollen av om den inloggade användaren får se eller ändra just den här posten. Den saknas ofta eftersom utvecklare bara kontrollerar om någon över huvud taget är inloggad. Då räcker det att ändra ett ID i URL:en för att hämta främmande data.

Skyddar ett väl säkrat API mot PHP2Shell?

Nej. PHP2Shell sitter i PHP-tolken och verkar i berörda driftlägen innan er kod över huvud taget körs. Mot det hjälper bara en PHP-uppdatering med omstart. Storleksgränser för förfrågningar är ändå rimliga och hör också till de övergångsåtgärder som php.net har nämnt.

Vilka statuskoder bör ett API returnera vid säkerhetsfel?

Vanliga är 401 utan giltig inloggning, 403 vid saknad behörighet, 405 vid otillåten metod, 413 vid för stor förfrågan, 415 vid fel innehållstyp och 429 vid för många förfrågningar. Själva svaret förblir kortfattat och utan interna detaljer.

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