Actuele situatie: PHP2Shell. Twee kritieke PHP-kwetsbaarheden (CVSS 9.2) maken schadelijke code zonder inloggen mogelijk. Patches sinds 21-10-2026.Wat u nu moet doen →

PHP-uitvoering in uploadmappen verbieden

Een webshell heeft twee dingen nodig: een map waarin ze kan worden geschreven en een server die haar uitvoert. Zo ontneemt u haar het tweede, en wel in elke beschrijfbare map, niet alleen in uploads.

Stand 6 min. leestijdHardening en configuratie

Kort gezegd: Om PHP-uitvoering in uploads te verbieden, stelt u eerst alle mappen vast waarin PHP mag schrijven en blokkeert u daarna in elk daarvan de uitvoering van scripts in de serverconfiguratie, niet via .htaccess. In Nginx moet de blokkade vóór het algemene PHP-blok gelden, in Apache hoort ze in de VirtualHost met AllowOverride None. security.limit_extensions = .php in de FPM-pool en een test met een onschuldig bestand ronden het werk af.

Waarom juist nu de uploadmappen tellen

Na een kritieke kwetsbaarheid als PHP2Shell willen aanvallers zelden maar één keer code uitvoeren. Ze willen terugkomen, ook als de server later wordt gepatcht. De eenvoudigste weg daarvoor is een webshell: een klein PHP-bestand, neergezet in een beschrijfbare map en later via de browser aangeroepen.

Een patch verwijdert zo'n bestand niet. Wie vanaf 20 oktober 2026 ongepatcht online was, moet daarom niet alleen updaten, maar ook controleren of er ergens nieuwe PHP-bestanden staan, en in de toekomst voorkomen dat ze worden uitgevoerd. Hoe u vondsten duidt, beschrijft PHP-bestanden in de uploadmap: vondsten juist duiden.

De uitvoeringsblokkade pakt de tweede voorwaarde aan. Ze voorkomt niet dat een bestand wordt neergezet, maar wel dat de server het als programma behandelt.

Eerst de inventarisatie: waar mag PHP schrijven?

De meeste handleidingen noemen alleen de uploadmap. In de praktijk schrijft een PHP-applicatie op veel meer plaatsen. Elke daarvan die via de webserver bereikbaar is, heeft de blokkade nodig.

Maptype Typische inhoud Waarom beschrijfbaar
Uploads, media Afbeeldingen, pdf's, bijlagen Gebruikers en redactie uploaden bestanden
Cache gegenereerde pagina's, miniaturen Applicatie versnelt de uitlevering
Temp, import, export CSV-bestanden, tussenstanden Koppelingen en gegevensuitwisseling
Back-ups in de webroot .zip, .sql Uitbreidingen maken „ter plekke” back-ups
Logs in de webroot Fout- en debuglogs verkeerd geconfigureerde applicaties

Welke mappen dat op uw server zijn, toont een zoekopdracht met de rechten van de runtimegebruiker. Ze wijzigt niets:

# Alle mappen onder /var/www waarin de PHP-gebruiker mag schrijven
# (gebruiker aanpassen: www-data, nginx, apache of eigen poolgebruiker)
sudo -u www-data find /var/www -type d -writable 2>/dev/null | sort
# Staan er in deze mappen al PHP-bestanden?
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

Geeft de eerste zoekopdracht de gehele webroot terug, dan is de programmacode eigendom van de runtimegebruiker. Dat moet u eerst wijzigen, zoals de gids Bestandsrechten op de webserver beschrijft. Anders is er geen map die niet zou moeten worden geblokkeerd.

PHP-uitvoering in uploads verbieden: Nginx

Bij Nginx bepaalt de volgorde. Volgens de Nginx-documentatie worden reguliere expressies gecontroleerd in de volgorde van het configuratiebestand en wint de eerste treffer. Staat het algemene blok location ~ \.php$ vóór uw blokkade, dan wordt het bestand uitgevoerd. Een eenvoudige prefix-location zonder ^~ beschermt om dezelfde reden niet.

Veilig is een reguliere expressie voor alle geblokkeerde mappen die vóór het PHP-blok staat. Ze dekt ook zelden gebruikte extensies:

server {
    # ... basisconfiguratie ...

    # 1. Blokkade voor beschrijfbare mappen, MOET vóór het PHP-blok staan
    location ~* ^/(uploads|media|cache|tmp|export)/.*\.(php\d?|phtml|phar|pht|phps)$ {
        deny all;
    }

    # 2. Algemeen PHP-blok: alleen bestaande bestanden doorgeven
    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;
    }
}

Pas de mapnamen aan uw inventarisatie aan. Bij applicaties met één enkel ingangspunt is de weg via een toegestane lijst nog sterker; het patroon toont Nginx veilig configureren voor PHP.

Apache en PHP-FPM: de blokkade op de juiste plek

In Apache hoort de blokkade in de serverconfiguratie of de VirtualHost. Een .htaccess in de uploadmap is ongeschikt, omdat iedereen die daar mag schrijven haar kan wijzigen. Voor de gehele webroot geldt daarom AllowOverride None. Volgens de Apache-documentatie is AllowOverride alleen toegestaan in <Directory>-blokken zonder reguliere expressies, dus stelt u het in bij de webroot en de blokkade via <DirectoryMatch> daaronder:

<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>

Draait nog mod_php, vul dan in hetzelfde blok php_admin_flag engine off aan. Bij PHP-FPM werkt een tweede hindernis in de pool: security.limit_extensions bepaalt welke extensies FPM als script uitvoert. Volgens de PHP-handleiding is de standaard .php .phar; aanbevolen wordt de beperking tot .php.

; in de pool, bijv. /etc/php/8.3/fpm/pool.d/seite1.conf
security.limit_extensions = .php

Testen met een onschuldig bestand

Of de blokkade werkt, toont alleen een test. Zet in elke geblokkeerde map kort een bestand dat slechts een tekst uitvoert, roep het op via het domein en verwijder het daarna.

  1. Configuratie controleren: nginx -t respectievelijk apachectl configtest, daarna opnieuw laden.
  2. Testbestand aanmaken, bijvoorbeeld uploads/sperrtest.php met de inhoud <?php echo 'ausgefuehrt';.
  3. Oproepen met curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/uploads/sperrtest.php. Verwacht wordt 403.
  4. Verschijnt in plaats daarvan 200 en de tekst „ausgefuehrt”, dan werkt de blokkade niet. Configuratie en volgorde controleren.
  5. Testbestand verwijderen en de test voor elke map en elke website herhalen.
Belangrijk

Vindt u bij de inventarisatie al onbekende PHP-bestanden in beschrijfbare mappen, verwijder dan niets overhaast. Stel eerst de toestand en de logs veilig, want deze bestanden zijn bewijsmateriaal. Hoe u daarna te werk gaat, beschrijft Webshells herkennen en verwijderen.

Hoe uploadfuncties in de code veilig worden gebouwd, met typecontrole en opslag buiten de webroot, staat in de gids Bestandsuploads in PHP veilig implementeren.

Conclusie: schrijven ja, uitvoeren nee

De uitvoeringsblokkade in beschrijfbare mappen is een van de meest werkzame afzonderlijke maatregelen tegen blijvende achterdeuren. Ze kost enkele regels configuratie en breekt bij zuiver gebouwde applicaties niets. Beslissend zijn drie dingen: een volledige inventarisatie in plaats van alleen de voor de hand liggende uploadmap, de juiste volgorde in Nginx respectievelijk het juiste niveau in Apache en een echte test met een onschuldig bestand.

Aangevuld met gescheiden eigenaren voor de programmacode, security.limit_extensions in de pool en een regelmatige zoektocht naar nieuwe PHP-bestanden ontstaat een toestand waarin een neergezet bestand weliswaar vervelend, maar nauwelijks nog bruikbaar is. Dat vervangt noch de update noch het sporenonderzoek, maar ontneemt aanvallers een van hun belangrijkste hulpmiddelen.

Hoe helpt PHP SOS concreet?

  • Inventarisatie: wij stellen alle beschrijfbare mappen per website vast en controleren ze op aanwezige PHP-bestanden.
  • Blokkades instellen: wij nemen de uitvoeringsblokkades op in Nginx, Apache en PHP-FPM, in de juiste volgorde en zonder afhankelijkheid van .htaccess.
  • Testen: elke blokkade controleren wij met een onschuldig bestand en documenteren wij het resultaat.
  • Opschonen: bij vondsten nemen wij sporenborging en verwijdering van malware over.

Veelgestelde vragen

Is een .htaccess in de uploadmap genoeg om PHP te verbieden?

Niet betrouwbaar. Wie in de map kan schrijven, kan ook de .htaccess wijzigen of vervangen. De blokkade hoort in de serverconfiguratie of de VirtualHost, en voor de webroot moet AllowOverride None gelden.

Welke mappen moet ik blokkeren?

Alle mappen waarin de PHP-gebruiker mag schrijven en die via de webserver bereikbaar zijn. Naast uploadmappen zijn dat vaak cache-, temp-, import-, export- en back-upmappen. Stel ze vast met een zoekopdracht als runtimegebruiker.

Breekt de blokkade mijn website?

Meestal niet, want in upload- en cachemappen staan bij zuivere applicaties geen scripts die rechtstreeks worden aangeroepen. Enkele uitbreidingen zetten daar echter wel PHP-bestanden neer. Test daarom na de omschakeling de belangrijkste functies.

Beschermt de blokkade tegen PHP2Shell?

Nee. PHP2Shell is een kwetsbaarheid in de PHP-interpreter die alleen wordt gesloten door de update en de herstart van alle workers. De blokkade voorkomt wel dat een neergezet bestand later via de browser wordt aangeroepen en als blijvende achterdeur dient.

Bronnen

Direct contact

Elk uur telt. Schrijf ons nu.

Beschrijf kort het systeem, de PHP-versie en wat u opmerkt. Wij nemen contact op, brengen de situatie in kaart en werken op afstand tot het incident is afgerond en gedocumenteerd.

Directe hulp