2026年11月12日

2026年11月12日

PHP-uitvoering in de uploads-map van WordPress blokkeren

Dit artikel is een gelokaliseerde versie van het Japanse origineel. Lees het Japanse origineel

Inleiding

wp-content/uploads/ is de map waarin WordPress media zoals afbeeldingen opslaat. Als er in deze map PHP-bestanden kunnen staan die ook worden uitgevoerd, kan een aanvaller een webshell (backdoor) uploaden en willekeurige code uitvoeren.

Symptomen en oorzaken

  • Een malwarescan heeft PHP-bestanden gevonden in wp-content/uploads/
  • Een beveiligingsplugin waarschuwt dat "PHP in de map uploads kan worden uitgevoerd"
  • Er is een verdacht bestand gevonden met een pad zoals wp-content/uploads/2024/01/shell.php
  • Een webshell is geplaatst via een kwetsbaarheid in een functie voor het uploaden van bestanden

Oplossing

Stap 1: bestaande verdachte PHP-bestanden opsporen

# Zoek alle PHP-bestanden in de map uploads
find /var/www/html/wp-content/uploads -name "*.php" -type f
find /var/www/html/wp-content/uploads -name "*.phtml" -type f
find /var/www/html/wp-content/uploads -name "*.php5" -type f

# Controleer PHP-bestanden die de afgelopen 7 dagen zijn aangemaakt of gewijzigd
find /var/www/html/wp-content/uploads -name "*.php" -mtime -7

# Controleer de inhoud van bestanden (kenmerkende patronen van malware)
grep -rl "eval(base64_decode" /var/www/html/wp-content/uploads/
grep -rl "system\|exec\|passthru\|shell_exec" /var/www/html/wp-content/uploads/

# Verwijder verdachte PHP-bestanden
find /var/www/html/wp-content/uploads -name "*.php" -delete
find /var/www/html/wp-content/uploads -name "*.phtml" -delete

Stap 2: PHP-uitvoering blokkeren in Apache (.htaccess)

# Maak wp-content/uploads/.htaccess aan
cat > /var/www/html/wp-content/uploads/.htaccess << 'EOF'
# Verbied het uitvoeren van PHP-bestanden volledig
<FilesMatch "\.(php|phtml|php3|php4|php5|php7|phar|shtml)$">
    Order Deny,Allow
    Deny from all
</FilesMatch>

# Schakel de PHP-engine zelf uit (bij gebruik van mod_php)
<IfModule mod_php.c>
    php_flag engine off
</IfModule>

# Verbied ook het uitvoeren van CGI
Options -ExecCGI
RemoveHandler .php .phtml .php5 .phar

# Schakel ook de mapweergave uit
Options -Indexes
EOF

chmod 644 /var/www/html/wp-content/uploads/.htaccess
# Controle na het instellen
# Maak een PHP-testbestand aan en probeer het te openen
echo "<?php echo 'test'; ?>" > /var/www/html/wp-content/uploads/test_block.php
curl -o /dev/null -s -w "%{http_code}" https://example.com/wp-content/uploads/test_block.php
# Krijg je 403 terug, dan is het gelukt
rm /var/www/html/wp-content/uploads/test_block.php

Stap 3: PHP-uitvoering blokkeren in Nginx

# /etc/nginx/sites-available/example.com
server {
    # ... je bestaande configuratie ...

    # Verbied het uitvoeren van PHP in de map uploads
    location ~* /wp-content/uploads/.*\.(php|phtml|php5|phar)$ {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Zet dit vóór de location van PHP-FPM
    location ~ \.php$ {
        # Gewone verwerking van PHP
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}
# Controleer de Nginx-configuratie en laad die opnieuw
sudo nginx -t && sudo systemctl reload nginx

# Controle
curl -o /dev/null -s -w "%{http_code}" https://example.com/wp-content/uploads/shell.php
# Krijg je 403 terug, dan is het gelukt

Stap 4: PHP-uploads ook vanuit WordPress blokkeren

// functions.php: verbied het uploaden van PHP-bestanden zelf

// (1) Voeg PHP-extensies toe aan de lijst met verboden uploads
add_filter('upload_mimes', function(array $mimes): array {
    // Verwijder MIME-typen die met PHP te maken hebben (voor de zekerheid)
    unset($mimes['php'], $mimes['phtml'], $mimes['phar']);
    return $mimes;
});

// (2) Herken PHP in geüploade bestanden en weiger ze
add_filter('wp_handle_upload_prefilter', function(array $file): array {
    $dangerous_extensions = ['php', 'phtml', 'php3', 'php4', 'php5', 'phar', 'shtml'];
    $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));

    if (in_array($ext, $dangerous_extensions, true)) {
        $file['error'] = 'Het uploaden van PHP-bestanden is niet toegestaan.';
    }

    // Controleer ook op MIME-type
    if (str_contains($file['type'], 'php')) {
        $file['error'] = 'Het uploaden van PHP-bestanden is niet toegestaan.';
    }

    return $file;
});

Stap 5: periodieke bewaking instellen

# Script dat PHP-bestanden in uploads periodiek bewaakt
cat > /usr/local/bin/check-uploads-php.sh << 'EOF'
#!/bin/bash
UPLOADS_DIR="/var/www/html/wp-content/uploads"
ADMIN_EMAIL="admin@example.com"

PHP_FILES=$(find "$UPLOADS_DIR" -name "*.php" -o -name "*.phtml" -o -name "*.phar" 2>/dev/null)

if [ -n "$PHP_FILES" ]; then
    echo "Waarschuwing: er zijn PHP-bestanden gevonden in de map uploads:
$PHP_FILES" | mail -s "[URGENT] Mogelijk is er een webshell op WordPress geplaatst" "$ADMIN_EMAIL"

    # Automatisch verwijderen (gebruik met voorzichtigheid)
    # find "$UPLOADS_DIR" -name "*.php" -delete
fi
EOF
chmod +x /usr/local/bin/check-uploads-php.sh

# Elk uur controleren
echo "0 * * * * root /usr/local/bin/check-uploads-php.sh" > /etc/cron.d/wp-uploads-php-check

Let op

  • php_flag engine off in .htaccess werkt alleen bij gebruik van mod_php. Gebruik je php-fpm (FastCGI), pak het dan aan met de directive <FilesMatch> of met een location-blok van Nginx.
  • Bij Nginx kan de regel location ~ \.php$ voorrang krijgen en kan PHP toch worden uitgevoerd als je de blokkaderegel voor uploads er niet vóór zet. Zet de blokkaderegel altijd hoger.
  • Sommige plugins (bijvoorbeeld Slider Revolution) plaatsen .php-bestanden in uploads. Controleer vóór het verwijderen waarvoor ze dienen, verwijder niet-gebruikte plugins en pak het dan aan.

Samenvatting

PHP-uitvoering in de map uploads blokkeer je zo: (1) bestaande verdachte bestanden opsporen en verwijderen met find wp-content/uploads -name ".php", (2) bij Apache <FilesMatch "\.(php|phar)$"> Deny from all toevoegen aan uploads/.htaccess, (3) bij Nginx deny all geven met location ~ /wp-content/uploads/.*\.php$, (4) PHP-uploads zelf weigeren met de hook wp_handle_upload_prefilter, en (5) PHP-bestanden in uploads bewaken met een cron-taak die elk uur draait.

Vragen over WordPress? De uitgever van deze site zit in Japan en antwoordt in het Japans. Contact (Japans)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲