2026年11月12日

2026年11月12日

Cara Melarang Eksekusi PHP di Direktori uploads WordPress

Artikel ini adalah edisi lokal dari artikel asli berbahasa Jepang. Baca artikel asli berbahasa Jepang

Pendahuluan

wp-content/uploads/ adalah direktori tempat WordPress menyimpan media seperti gambar. Jika file PHP berhasil ditempatkan di direktori ini dan bisa dieksekusi, penyerang dapat mengunggah web shell (backdoor) dan menjalankan kode apa pun.

Gejala dan penyebab

  • Pemindaian malware mendeteksi file PHP di dalam wp-content/uploads/
  • Plugin keamanan memperingatkan bahwa "PHP dapat dieksekusi di direktori uploads"
  • File mencurigakan ditemukan di path seperti wp-content/uploads/2024/01/shell.php
  • Web shell terpasang lewat kerentanan pada fitur unggah file

Langkah penyelesaian

Langkah 1: Deteksi file PHP mencurigakan yang sudah ada

# Cari semua file PHP di dalam direktori 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

# Periksa file PHP yang dibuat atau diubah baru-baru ini (dalam 7 hari)
find /var/www/html/wp-content/uploads -name "*.php" -mtime -7

# Periksa isi file (pola khas 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/

# Hapus file PHP yang mencurigakan
find /var/www/html/wp-content/uploads -name "*.php" -delete
find /var/www/html/wp-content/uploads -name "*.phtml" -delete

Langkah 2: Larang eksekusi PHP di Apache (.htaccess)

# Buat wp-content/uploads/.htaccess
cat > /var/www/html/wp-content/uploads/.htaccess << 'EOF'
# Larang sepenuhnya eksekusi file PHP
<FilesMatch "\.(php|phtml|php3|php4|php5|php7|phar|shtml)$">
    Order Deny,Allow
    Deny from all
</FilesMatch>

# Nonaktifkan mesin PHP itu sendiri (jika memakai mod_php)
<IfModule mod_php.c>
    php_flag engine off
</IfModule>

# Larang juga eksekusi CGI
Options -ExecCGI
RemoveHandler .php .phtml .php5 .phar

# Nonaktifkan juga directory listing
Options -Indexes
EOF

chmod 644 /var/www/html/wp-content/uploads/.htaccess
# Pemeriksaan setelah pengaturan
# Buat file PHP uji dan coba akses
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
# Berhasil jika 403 dikembalikan
rm /var/www/html/wp-content/uploads/test_block.php

Langkah 3: Larang eksekusi PHP di Nginx

# /etc/nginx/sites-available/example.com
server {
    # ... konfigurasi yang sudah ada ...

    # Larang eksekusi PHP di direktori uploads
    location ~* /wp-content/uploads/.*\.(php|phtml|php5|phar)$ {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Tulis sebelum location untuk PHP-FPM
    location ~ \.php$ {
        # Pemrosesan PHP biasa
        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;
    }
}
# Periksa konfigurasi Nginx lalu terapkan
sudo nginx -t && sudo systemctl reload nginx

# Pemeriksaan
curl -o /dev/null -s -w "%{http_code}" https://example.com/wp-content/uploads/shell.php
# Berhasil jika 403 dikembalikan

Langkah 4: Blokir juga unggahan PHP dari sisi WordPress

// functions.php: larang unggahan file PHP itu sendiri

// (1) Tambahkan ekstensi PHP ke daftar larangan unggah
add_filter('upload_mimes', function(array $mimes): array {
    // Hapus tipe MIME terkait PHP (untuk berjaga-jaga)
    unset($mimes['php'], $mimes['phtml'], $mimes['phar']);
    return $mimes;
});

// (2) Deteksi dan tolak file PHP yang diunggah
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'] = 'Mengunggah file PHP dilarang.';
    }

    // Periksa juga lewat tipe MIME
    if (str_contains($file['type'], 'php')) {
        $file['error'] = 'Mengunggah file PHP dilarang.';
    }

    return $file;
});

Langkah 5: Atur pemantauan berkala

# Skrip untuk memantau file PHP di dalam uploads secara berkala
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 "Peringatan: file PHP terdeteksi di direktori uploads:
$PHP_FILES" | mail -s "[DARURAT] Kemungkinan web shell terpasang di WordPress" "$ADMIN_EMAIL"

    # Hapus otomatis (gunakan dengan hati-hati)
    # find "$UPLOADS_DIR" -name "*.php" -delete
fi
EOF
chmod +x /usr/local/bin/check-uploads-php.sh

# Periksa setiap satu jam
echo "0 * * * * root /usr/local/bin/check-uploads-php.sh" > /etc/cron.d/wp-uploads-php-check

Catatan penting

  • php_flag engine off di .htaccess hanya berlaku jika memakai mod_php. Jika memakai php-fpm (FastCGI), tangani dengan direktif atau blok location Nginx
  • Pada Nginx, jika aturan pemblokiran untuk uploads tidak ditulis sebelum location ~ \.php$, aturan yang belakangan bisa lebih diutamakan sehingga PHP tetap dapat dieksekusi. Selalu letakkan aturan pemblokiran di posisi atas
  • Beberapa plugin (misalnya Slider Revolution) terkadang menempatkan file .php di dalam uploads. Sebelum menghapus, periksa kegunaannya, dan lakukan penanganan setelah menghapus plugin yang tidak diperlukan

Ringkasan

Melarang eksekusi PHP di direktori uploads dilakukan dengan: (1) mendeteksi dan menghapus file mencurigakan yang ada dengan find wp-content/uploads -name ".php", (2) di Apache, menambahkan Deny from all ke uploads/.htaccess, (3) di Nginx, deny all dengan location ~ /wp-content/uploads/.*\.php$, (4) menolak unggahan PHP itu sendiri dengan hook wp_handle_upload_prefilter, dan (5) memantau file PHP di uploads dengan cron setiap satu jam.

Ada pertanyaan tentang WordPress? Penerbit situs ini berada di Jepang dan membalas dalam bahasa Jepang. Kontak (bahasa Jepang)

お気軽にご相談ください

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