Kort sagt: För att förbjuda PHP-körning i uppladdningar tar ni först reda på alla mappar som PHP får skriva i och spärrar sedan i var och en av dem körningen av skript i serverkonfigurationen, inte via .htaccess. I Nginx måste spärren slå till före det allmänna PHP-blocket, i Apache hör den hemma i VirtualHost med AllowOverride None. security.limit_extensions = .php i FPM-poolen och ett test med en ofarlig fil avslutar arbetet.
Varför just nu uppladdningsmapparna räknas
Efter en kritisk sårbarhet som PHP2Shell vill angripare sällan köra kod bara en gång. De vill komma tillbaka, även när servern senare patchas. Den enklaste vägen dit är en webbshell: en liten PHP-fil, utlagd i en skrivbar mapp och senare anropad via webbläsaren.
En patch tar inte bort en sådan fil. Den som från och med den 20 oktober 2026 var online ej patchad bör därför inte bara uppdatera utan också kontrollera om nya PHP-filer ligger någonstans, och i framtiden förhindra att de körs. Hur ni tolkar fynd beskriver PHP-filer i uppladdningsmappen: tolka fynden rätt.
Körspärren tar fasta på det andra villkoret. Den förhindrar inte att en fil läggs ut, men att servern behandlar den som ett program.
Först inventeringen: var får PHP skriva?
De flesta anvisningar nämner bara uppladdningsmappen. I praktiken skriver en PHP-applikation på mycket fler ställen. Varje sådant som är nåbart via webbservern behöver spärren.
| Maptyp | Typiskt innehåll | Varför skrivbar |
|---|---|---|
| Uppladdningar, media | bilder, PDF:er, bilagor | Användare och redaktion laddar upp filer |
| Cache | genererade sidor, miniatyrbilder | Applikationen snabbar upp leveransen |
| Temp, import, export | CSV-filer, mellanlägen | Gränssnitt och datautbyte |
| Backuper i webbroten | .zip, .sql |
Tillägg säkrar ”på plats” |
| Loggar i webbroten | fel- och felsökningsloggar | felkonfigurerade applikationer |
Vilka mappar det är på er server visar en sökning med körtidsanvändarens rättigheter. Den ändrar ingenting:
# Alla mappar under /var/www som PHP-användaren får skriva i
# (anpassa användaren: www-data, nginx, apache eller egen poolanvändare)
sudo -u www-data find /var/www -type d -writable 2>/dev/null | sort
# Ligger det redan PHP-filer i de här mapparna?
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
Returnerar den första sökningen hela webbroten ägs programkoden av körtidsanvändaren. Det bör ni ändra i förväg, som guiden Filrättigheter på webbservern beskriver. Annars finns ingen mapp som inte skulle behöva spärras.
Förbjuda PHP-körning i uppladdningar: Nginx
I Nginx avgör ordningen. Enligt Nginx-dokumentationen kontrolleras reguljära uttryck i konfigurationsfilens ordning, och den första träffen vinner. Står det allmänna blocket location ~ \.php$ före er spärr körs filen. En enkel prefix-location utan ^~ skyddar av samma skäl inte.
Säkert är ett reguljärt uttryck för alla spärrade mappar som står före PHP-blocket. Det täcker även sällan använda ändelser:
server {
# ... Grundkonfiguration ...
# 1. Spärr för skrivbara mappar, MÅSTE stå före PHP-blocket
location ~* ^/(uploads|media|cache|tmp|export)/.*\.(php\d?|phtml|phar|pht|phps)$ {
deny all;
}
# 2. Allmänt PHP-block: lämna bara över existerande 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;
}
}
Anpassa mappnamnen till er inventering. För applikationer med en enda startpunkt är vägen via en tillåtelselista ännu starkare; mönstret visar Konfigurera Nginx för PHP säkert.
Apache och PHP-FPM: spärren på rätt ställe
I Apache hör spärren hemma i serverkonfigurationen eller i VirtualHost. En .htaccess i uppladdningsmappen är olämplig, eftersom var och en som får skriva där kan ändra den. För hela webbroten gäller därför AllowOverride None. Enligt Apache-dokumentationen är AllowOverride bara tillåtet i <Directory>-block utan reguljära uttryck, så ni sätter det på webbroten och spärren via <DirectoryMatch> därunder:
<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örs mod_php fortfarande kompletterar ni i samma block med php_admin_flag engine off. Vid PHP-FPM verkar en andra spärr i poolen: security.limit_extensions anger vilka ändelser FPM överhuvudtaget kör. Enligt PHP-manualen är standard .php .phar; rekommenderat är begränsningen till .php.
; i poolen, t.ex. /etc/php/8.3/fpm/pool.d/seite1.conf
security.limit_extensions = .php
Testa med en ofarlig fil
Om spärren verkar visar bara ett test. Lägg kort en fil som enbart skriver ut en text i varje spärrad mapp, anropa den via domänen och radera den därefter.
- Kontrollera konfigurationen:
nginx -trespektiveapachectl configtest, ladda sedan om. - Skapa testfilen, till exempel
uploads/sperrtest.phpmed innehållet<?php echo 'ausgefuehrt';. - Anropa med
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/uploads/sperrtest.php. Förväntat är403. - Visas i stället
200och texten ”ausgefuehrt” slår spärren inte till. Kontrollera konfiguration och ordning. - Radera testfilen och upprepa testet för varje mapp och varje webbplats.
Hittar ni vid inventeringen redan okända PHP-filer i skrivbara mappar, radera ingenting förhastat. Säkra först tillståndet och loggarna, eftersom filerna är bevismaterial. Hur ni går vidare beskriver Känna igen och ta bort webbshells.
Hur uppladdningsfunktioner byggs säkert i koden, med typkontroll och lagring utanför webbroten, står i guiden Implementera filuppladdningar i PHP säkert.
Slutsats: skriva ja, köra nej
Körspärren i skrivbara mappar är en av de mest verksamma enskilda åtgärderna mot permanenta bakdörrar. Den kostar några få konfigurationsrader och förstör inget hos rent byggda applikationer. Tre saker är avgörande: en fullständig inventering i stället för bara den uppenbara uppladdningsmappen, rätt ordning i Nginx respektive rätt nivå i Apache och ett riktigt test med en ofarlig fil.
Kompletterat med separata ägare för programkoden, security.limit_extensions i poolen och en regelbunden sökning efter nya PHP-filer uppstår ett läge där en utlagd fil visserligen är besvärlig men knappast längre användbar. Det ersätter varken uppdateringen eller spårsökningen men tar ifrån angripare ett av deras viktigaste verktyg.
Hur hjälper PHP SOS konkret?
- Inventering: Vi tar reda på alla skrivbara mappar per webbplats och kontrollerar dem efter befintliga PHP-filer.
- Sätta spärrar: Vi lägger in körspärrarna i Nginx, Apache och PHP-FPM, i rätt ordning och utan beroende av
.htaccess. - Testa: Varje spärr kontrollerar vi med en ofarlig fil och dokumenterar resultatet.
- Sanera: Vid fynd tar vi hand om spårsäkring och borttagning av skadlig kod.
Vanliga frågor
Räcker en .htaccess i uppladdningsmappen för att förbjuda PHP?
Inte tillförlitligt. Den som kan skriva i mappen kan också ändra eller ersätta .htaccess. Spärren hör hemma i serverkonfigurationen eller i VirtualHost, och för webbroten bör AllowOverride None gälla.
Vilka mappar måste jag spärra?
Alla mappar som PHP-användaren får skriva i och som är nåbara via webbservern. Vid sidan av uppladdningsmappar är det ofta cache-, temp-, import-, export- och backupkataloger. Ta reda på dem med en sökning som körtidsanvändaren.
Förstör spärren min webbplats?
I regel inte, eftersom det i uppladdnings- och cachemappar hos rena applikationer inte ligger några skript som anropas direkt. Enskilda tillägg lägger dock PHP-filer där ändå. Testa därför de viktigaste funktionerna efter omställningen.
Skyddar spärren mot PHP2Shell?
Nej. PHP2Shell är en sårbarhet i PHP-tolken som bara stängs av uppdateringen och omstart av alla workers. Spärren förhindrar däremot att en utlagd fil senare anropas via webbläsaren och används som permanent bakdörr.