Kort sagt: For at forbyde PHP-udførelse i uploads finder I først alle mapper, som PHP må skrive i, og spærrer derefter i hver af dem udførelsen af scripts i serverkonfigurationen, ikke via .htaccess. I Nginx skal spærringen virke før den generelle PHP-blok, i Apache hører den hjemme i VirtualHost med AllowOverride None. security.limit_extensions = .php i FPM-poolen og en test med en harmløs fil afslutter arbejdet.
Hvorfor netop nu upload-mapperne tæller
Efter en kritisk sårbarhed som PHP2Shell vil angribere sjældent kun udføre kode én gang. De vil komme igen, også når serveren senere patches. Den enkleste vej hertil er en webshell: en lille PHP-fil, lagt i en skrivbar mappe og senere kaldt via browseren.
En patch fjerner ikke sådan en fil. Den, der fra den 20. oktober 2026 var online upatchet, bør derfor ikke blot opdatere, men også kontrollere, om der ligger nye PHP-filer et sted, og fremover forhindre, at de udføres. Hvordan I tolker fund, beskriver PHP-filer i upload-mappen: Tolk fundsteder rigtigt.
Udførelsesspærringen sætter ind ved den anden betingelse. Den forhindrer ikke, at en fil lægges ud, men at serveren behandler den som et program.
Først opgørelsen: Hvor må PHP skrive?
De fleste vejledninger nævner kun upload-mappen. I praksis skriver en PHP-applikation mange flere steder. Hver af dem, der kan nås via webserveren, har brug for spærringen.
| Mappetype | Typisk indhold | Hvorfor skrivbar |
|---|---|---|
| Uploads, medier | billeder, PDF'er, bilag | brugere og redaktion uploader filer |
| Cache | genererede sider, miniaturebilleder | applikationen fremskynder leveringen |
| Temp, import, eksport | CSV-filer, mellemtilstande | grænseflader og dataudveksling |
| Backups i webroden | .zip, .sql |
udvidelser sikrer "på stedet" |
| Logs i webroden | fejl- og debuglogs | forkert konfigurerede applikationer |
Hvilke mapper det er på jeres server, viser en søgning med køretidsbrugerens rettigheder. Den ændrer intet:
# Alle mapper under /var/www, som PHP-brugeren må skrive i
# (tilpas brugeren: www-data, nginx, apache eller egen pool-bruger)
sudo -u www-data find /var/www -type d -writable 2>/dev/null | sort
# Ligger der allerede PHP-filer i disse mapper?
sudo -u www-data find /var/www -type d -writable -print0 2>/dev/null \
| xargs -0 -I{} find {} -maxdepth 1 -type f -iname "*.ph*" 2>/dev/null
Returnerer den første søgning hele webroden, tilhører programkoden køretidsbrugeren. Det bør I ændre på forhånd, som vejledningen Filrettigheder på webserveren beskriver. Ellers findes der ingen mappe, som ikke skulle spærres.
Forbyd PHP-udførelse i uploads: Nginx
Ved Nginx afgør rækkefølgen. Ifølge Nginx-dokumentationen kontrolleres regulære udtryk i konfigurationsfilens rækkefølge, og det første match vinder. Står den generelle blok location ~ \.php$ før jeres spærring, udføres filen. En enkel præfiks-location uden ^~ beskytter af samme grund ikke.
Sikkert er et regulært udtryk for alle spærrede mapper, der står før PHP-blokken. Det dækker også sjældent brugte endelser:
server {
# ... grundkonfiguration ...
# 1. Spærring for skrivbare mapper, SKAL stå før PHP-blokken
location ~* ^/(uploads|media|cache|tmp|export)/.*\.(php\d?|phtml|phar|pht|phps)$ {
deny all;
}
# 2. Generel PHP-blok: overdrag kun eksisterende filer
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/seite1.sock;
}
}
Tilpas mappenavnene til jeres opgørelse. Ved applikationer med ét eneste indgangspunkt er vejen via en tilladelsesliste endnu stærkere; mønstret viser Konfigurér Nginx sikkert til PHP.
Apache og PHP-FPM: spærringen det rigtige sted
I Apache hører spærringen hjemme i serverkonfigurationen eller VirtualHost. En .htaccess i upload-mappen er uegnet, fordi enhver kan ændre den, der må skrive dér. For hele webroden gælder derfor AllowOverride None. Ifølge Apache-dokumentationen er AllowOverride kun tilladt i <Directory>-blokke uden regulære udtryk, så I sætter den ved webroden og spærringen via <DirectoryMatch> derunder:
<Directory /var/www/seite1/public>
AllowOverride None
Require all granted
</Directory>
<DirectoryMatch "^/var/www/seite1/public/(uploads|media|cache|tmp|export)/">
<FilesMatch "\.(php\d?|phtml|phar|pht|phps)$">
Require all denied
</FilesMatch>
</DirectoryMatch>
Kører mod_php stadig, supplerer I i den samme blok php_admin_flag engine off. Ved PHP-FPM virker en anden skranke i poolen: security.limit_extensions fastlægger, hvilke endelser FPM overhovedet udfører. Ifølge PHP-manualen er standarden .php .phar; anbefalet er begrænsningen til .php.
; i poolen, f.eks. /etc/php/8.3/fpm/pool.d/seite1.conf
security.limit_extensions = .php
Test med en harmløs fil
Om spærringen virker, viser kun en test. Læg kort en fil i hver spærret mappe, som blot udskriver en tekst, kald den via domænet, og slet den derefter.
- Kontrollér konfigurationen:
nginx -thenholdsvisapachectl configtest, genindlæs derefter. - Opret testfilen, for eksempel
uploads/sperrtest.phpmed indholdet<?php echo 'ausgefuehrt';. - Kald den med
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/uploads/sperrtest.php. Forventet er403. - Dukker
200og teksten "ausgefuehrt" i stedet op, virker spærringen ikke. Kontrollér konfiguration og rækkefølge. - Slet testfilen, og gentag testen for hver mappe og hvert website.
Finder I ved opgørelsen allerede ukendte PHP-filer i skrivbare mapper, så slet intet forhastet. Sikr først tilstanden og logs, for disse filer er bevismidler. Hvordan I så går frem, beskriver Genkend og fjern webshells.
Hvordan upload-funktioner bygges sikkert i koden, med typekontrol og lagring uden for webroden, står i vejledningen Gennemfør filuploads i PHP sikkert.
Konklusion: Skrive ja, udføre nej
Udførelsesspærringen i skrivbare mapper er en af de mest virksomme enkeltforanstaltninger mod varige bagdøre. Den koster få linjer konfiguration og ødelægger intet ved ordentligt byggede applikationer. Afgørende er tre ting: en fuldstændig opgørelse i stedet for kun den åbenlyse upload-mappe, den rigtige rækkefølge i Nginx henholdsvis det rigtige niveau i Apache og en ægte test med en harmløs fil.
Suppleret med adskilte ejere af programkoden, security.limit_extensions i poolen og en regelmæssig søgning efter nye PHP-filer opstår en tilstand, hvor en udlagt fil ganske vist er irriterende, men næppe kan bruges. Det erstatter hverken opdateringen eller sporsøgningen, men fratager angribere et af deres vigtigste værktøjer.
Hvordan hjælper PHP SOS konkret?
- Opgørelse: Vi finder alle skrivbare mapper pr. website og kontrollerer dem for eksisterende PHP-filer.
- Sæt spærringer: Vi indfører udførelsesspærringerne i Nginx, Apache og PHP-FPM, i den rigtige rækkefølge og uden
.htaccess-afhængighed. - Test: Hver spærring kontrollerer vi med en harmløs fil og dokumenterer resultatet.
- Ryd op: Ved fund overtager vi sporsikring og malwarefjernelse.
Ofte stillede spørgsmål
Er en .htaccess i upload-mappen nok til at forbyde PHP?
Ikke pålideligt. Den, der kan skrive i mappen, kan også ændre eller erstatte .htaccess. Spærringen hører hjemme i serverkonfigurationen eller VirtualHost, og for webroden bør AllowOverride None gælde.
Hvilke mapper skal jeg spærre?
Alle mapper, som PHP-brugeren må skrive i, og som kan nås via webserveren. Ud over upload-mapper er det ofte cache-, temp-, import-, eksport- og backupmapper. Find dem med en søgning som køretidsbruger.
Ødelægger spærringen mit website?
Som regel ikke, for i upload- og cache-mapper ligger der ved ordentlige applikationer ingen scripts, der kaldes direkte. Enkelte udvidelser lægger dog alligevel PHP-filer dér. Test derfor de vigtigste funktioner efter omstillingen.
Beskytter spærringen mod PHP2Shell?
Nej. PHP2Shell er en sårbarhed i PHP-fortolkeren, som kun lukkes af opdateringen og genstart af alle workers. Spærringen forhindrer dog, at en udlagt fil senere kaldes via browseren og bruges som varig bagdør.