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 →

Sådan skaber PHP en webside: forespørgslens vej

Hvad der sker mellem klik og færdig side: webserver, SAPI, compiler, OPcache og Zend VM i syv trin, og hvorfor PHP2Shell sætter ind netop i dette forløb.

Status 4 min. læsetidPHP-viden

Kort sagt: Når en browser anmoder om en PHP-side, modtager webserveren forespørgslen og giver den videre til PHP via en grænseflade (SAPI). PHP oversætter scriptet til bytekode, udfører den i Zend Engine og returnerer resultatet, som regel HTML, til webserveren. Derefter ryddes forespørgslens tilstand op, så den næste starter rent.

Hvad sker der, når nogen åbner jeres hjemmeside?

For de besøgende er det et klik. På serveren afvikles mange trin i løbet af millisekunder. Den, der kender forløbet, forstår bedre, hvorfor opdateringer, genstarter og konfiguration er så vigtige, og hvorfor en sårbarhed i selve PHP vejer tungere end en sårbarhed i et plugin.

PHP-manualen nævner tre bestanddele, som er nødvendige for et PHP-website: PHP-fortolkeren (som CGI eller servermodul), en webserver og en browser. Fortolkeren er det program, der læser og udfører PHP-kode. Hvordan den er forbundet med webserveren, afgør driftsformen.

Hvordan fungerer PHP? Syv trin i en forespørgsel

  1. Forespørgsel: Browseren sender en HTTP-forespørgsel, f.eks. GET /kontakt.php, til serveren.
  2. Webserver: Apache, Nginx eller LiteSpeed modtager forespørgslen. Statiske filer som billeder leverer de selv. Til .php-filer kalder de PHP.
  3. Overdragelse via SAPI: Server-grænsefladen (SAPI) overdrager forespørgselsdata som headere, parametre og formulardata til PHP. Ved PHP-FPM sker det via FastCGI-protokollen, ved mod_php direkte i Apache-processen. Detaljer under SAPI forklaret.
  4. Forberede forespørgslen: PHP lægger forespørgselsdata i variabler som $_GET, $_POST, $_COOKIE og $_FILES og reserverer hukommelse til forespørgslen.
  5. Oversætte: Scriptet opdeles i byggesten (tokens), heraf opstår et abstrakt syntakstræ (AST) og heraf opcodes, en slags maskinsprog til PHP. Er OPcache aktiv, springes dette trin over, hvis scriptet allerede ligger i cachen.
  6. Udføre: Den virtuelle maskine i Zend Engine afvikler opcodes, spørger databaser, læser filer og producerer outputtet.
  7. Svar og oprydning: Outputtet går via SAPI tilbage til webserveren og derfra til browseren. Bagefter frigiver PHP forespørgslens hukommelse og nulstiller tilstanden.

AST'et findes siden PHP 7. Ifølge den tilhørende RFC genererede parseren tidligere opcodes direkte under indlæsningen; opdelingen i tre faser gjorde compileren lettere at vedligeholde.

Et eksempel: Hvad scriptet ser af forespørgslen

Det følgende harmløse script viser, hvilke oplysninger PHP får fra forespørgslen, og i hvilken driftsform det kører:

<?php
header('Content-Type: text/plain; charset=utf-8');

echo 'Betriebsart (SAPI): ' . PHP_SAPI . "\n";
echo 'PHP-Version: ' . PHP_VERSION . "\n";
echo 'Methode: ' . ($_SERVER['REQUEST_METHOD'] ?? '-') . "\n";
echo 'Speicher in dieser Anfrage: ' . memory_get_usage() . " Bytes\n";

På en server med PHP-FPM udskriver PHP_SAPI værdien fpm-fcgi, under Apache med mod_php apache2handler. Læg kun sådanne kontrolfiler ud kortvarigt og aldrig permanent i den offentlige mappe, for versionsoplysninger hjælper også angribere med at orientere sig.

Hvor bytekode-cachen og JIT kommer ind i billedet

Oversættelsen i trin 5 koster tid. OPcache gemmer ifølge manualen forkompileret bytekode i den delte hukommelse og sparer dermed PHP for at indlæse og opdele scripts ved hver forespørgsel. Siden PHP 8.0 kan en JIT-compiler desuden generere ægte maskinkode ud fra opcodes. Ifølge JIT-RFC'en er den en næsten selvstændig del af OPcache.

Fase Resultat Caches?
Lexing token-strøm nej
Parsing abstrakt syntakstræ (AST) nej
Kompilering opcodes (op-arrays pr. fil og funktion) ja, i OPcache
JIT (valgfri) maskinkode ja, i OPcache-hukommelsen
Udførelse sidens output nej

Cachen angår kun den oversatte kode. Data fra den enkelte forespørgsel, f.eks. formularindtastninger eller session-værdier, deles ikke via OPcache.

Hvorfor PHP2Shell sætter ind netop i dette forløb

De to PHP2Shell-sårbarheder angår ikke en applikation, men selve forløbet. Ved CVE-2026-109618 kan en out-of-memory-tilstand afbryde PHP, mens forespørgselsdata kun er delvis forberedt, altså i trin 4. Ved den efterfølgende oprydning kan ugyldige data så blive behandlet som gyldige.

Ved CVE-2026-109619 kan en forespørgsels interne tilstand blive bestående, efter at hukommelsen er frigivet. En senere forespørgsel i den samme worker kan udnytte den, før den nulstilles. Det angår trin 7, oprydningen. Baggrund findes på siden CVE-2026-109619 og i indlægget om forespørgslens livscyklus.

Heraf følger: Beskyttelsesforanstaltninger i applikationskoden, f.eks. sikkerhedsplugins, virker først i trin 6. Ved mod_php blev der ifølge PHP-teamet endda vist en exploit, før der overhovedet kører applikationskode. Effektivt er kun PHP-opdateringen til 8.5.12, 8.4.27, 8.3.36 eller 8.2.35 og en genstart af alle PHP-processer, fordi langlivede workere ellers fortsat udfører den gamle kode.

Hvordan hjælper PHP SOS konkret?

  • Gøre forløbet synligt: Vi finder ud af, hvilken driftsform, hvilken konfiguration og hvilken cache der faktisk er aktive på jeres server.
  • Opdatere korrekt: Vi indspiller PHP-opdateringen og kontrollerer via starttidspunkterne, at ingen gammel proces kører mere.
  • Sikre lagene: Som led i serverhærdningen begrænser vi forespørgselsstørrelser, hukommelse og rettigheder der, hvor de virker: før applikationskoden.
  • Undersøge for spor: Ved servere, der har været tilgængelige uden beskyttelse, søger vi efter tegn på et indbrud.

Ofte stillede spørgsmål

Oversættes PHP-koden på ny ved hvert kald?

Uden cache ja: PHP opdeler scriptet, bygger et syntakstræ og genererer opcodes ud fra det. Med aktiv OPcache ligger opcodes i den delte hukommelse og genbruges, så længe filen ikke er ændret.

Hvad bliver tilbage i hukommelsen efter en forespørgsel?

Grundlæggende ryddes en forespørgsels tilstand op til sidst, så den næste forespørgsel starter rent. Kun ting som OPcache eller persistente forbindelser er langlivede. Netop ved denne oprydning sætter CVE-2026-109619 ind.

Hvorfor skal PHP genstartes efter en opdatering?

Ved PHP-FPM og mod_php kører processerne vedvarende og har den gamle programkode indlæst. Nye filer på disken ændrer intet ved det. Først en genstart indlæser den rettede kode.

Er en webserver uden PHP mere sikker?

Den har mindre angrebsflade, fordi ingen programlogik reagerer på forespørgsler. For rent statisk indhold er det en reel mulighed. Til shops, formularer og logins har man dog brug for et serverside-sprog, og så tæller vedligeholdelsen af det.

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