2026年11月12日
2026年11月12日
Як заборонити виконання PHP у каталозі uploads WordPress
Ця стаття — локалізована версія японського оригіналу. Читати японський оригінал
Вступ
wp-content/uploads/ — це каталог, де WordPress зберігає зображення й інші медіафайли. Якщо в ньому можуть опинитися PHP-файли, які сервер здатен виконувати, зловмисник може завантажити веб-шел (бекдор) і виконати довільний код.
Симптоми та причини
- Сканування на шкідливий код виявило PHP-файли в
wp-content/uploads/ - Плагін безпеки попередив, що «у каталозі uploads можливе виконання PHP»
- Підозрілий файл знайшли за шляхом на кшталт
wp-content/uploads/2024/01/shell.php - Веб-шел потрапив на сервер через вразливість у функції завантаження файлів
Порядок розв’язання
Крок 1. Знайдіть наявні підозрілі PHP-файли
# Знайти всі PHP-файли в каталозі 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
# Переглянути PHP-файли, створені чи змінені нещодавно (протягом 7 днів)
find /var/www/html/wp-content/uploads -name "*.php" -mtime -7
# Перевірити вміст файлів (характерні шаблони шкідливого коду)
grep -rl "eval(base64_decode" /var/www/html/wp-content/uploads/
grep -rl "system\|exec\|passthru\|shell_exec" /var/www/html/wp-content/uploads/
# Видалити підозрілі PHP-файли
find /var/www/html/wp-content/uploads -name "*.php" -delete
find /var/www/html/wp-content/uploads -name "*.phtml" -delete
Крок 2. Заборонте виконання PHP в Apache (.htaccess)
# Створити wp-content/uploads/.htaccess
cat > /var/www/html/wp-content/uploads/.htaccess << 'EOF'
# Повністю заборонити виконання PHP-файлів
<FilesMatch "\.(php|phtml|php3|php4|php5|php7|phar|shtml)$">
Order Deny,Allow
Deny from all
</FilesMatch>
# Вимкнути сам рушій PHP (якщо використовується mod_php)
<IfModule mod_php.c>
php_flag engine off
</IfModule>
# Заборонити також виконання CGI
Options -ExecCGI
RemoveHandler .php .phtml .php5 .phar
# Вимкнути також перегляд вмісту каталогу
Options -Indexes
EOF
chmod 644 /var/www/html/wp-content/uploads/.htaccess
# Перевірка після налаштування
# Створити тестовий PHP-файл і спробувати відкрити його
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
# Якщо повертається 403 — усе вдалося
rm /var/www/html/wp-content/uploads/test_block.php
Крок 3. Заборонте виконання PHP в Nginx
# /etc/nginx/sites-available/example.com
server {
# ... наявні налаштування ...
# Заборонити виконання PHP в каталозі uploads
location ~* /wp-content/uploads/.*\.(php|phtml|php5|phar)$ {
deny all;
access_log off;
log_not_found off;
}
# Записувати перед location для PHP-FPM
location ~ \.php$ {
# Звичайна обробка 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;
}
}
# Перевірити конфігурацію Nginx і застосувати її
sudo nginx -t && sudo systemctl reload nginx
# Перевірка
curl -o /dev/null -s -w "%{http_code}" https://example.com/wp-content/uploads/shell.php
# Якщо повертається 403 — усе вдалося
Крок 4. Заблокуйте завантаження PHP і на боці WordPress
// functions.php: заборонити саме завантаження PHP-файлів
// ① Додати PHP-розширення до списку заборонених для завантаження
add_filter('upload_mimes', function(array $mimes): array {
// Прибрати MIME-типи, пов’язані з PHP (про всяк випадок)
unset($mimes['php'], $mimes['phtml'], $mimes['phar']);
return $mimes;
});
// ② Виявлення PHP у завантажуваних файлах і відмова
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'] = 'Завантаження PHP-файлів заборонено.';
}
// Перевірити також за MIME-типом
if (str_contains($file['type'], 'php')) {
$file['error'] = 'Завантаження PHP-файлів заборонено.';
}
return $file;
});
Крок 5. Налаштуйте регулярний моніторинг
# Скрипт для регулярного моніторингу PHP-файлів в uploads
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 "Попередження: у каталозі uploads виявлено PHP-файли:
$PHP_FILES" | mail -s "[ТЕРМІНОВО] Імовірно, у WordPress встановлено веб-шел" "$ADMIN_EMAIL"
# Автоматичне видалення (використовуйте обережно)
# find "$UPLOADS_DIR" -name "*.php" -delete
fi
EOF
chmod +x /usr/local/bin/check-uploads-php.sh
# Перевіряти щогодини
echo "0 * * * * root /usr/local/bin/check-uploads-php.sh" > /etc/cron.d/wp-uploads-php-check
Важливі зауваження
php_flag engine offу.htaccessдіє лише тоді, коли використовуєтьсяmod_php. Якщо ви працюєте зphp-fpm(FastCGI), скористайтеся директивою<FilesMatch>або блоком location в Nginx- В Nginx, якщо правило-блокування для uploads не записати перед
location ~ \.php$, пріоритет може отримати друге, і PHP виконуватиметься. Обов’язково ставте правило-блокування вище - Деякі плагіни (наприклад, Slider Revolution) можуть розміщувати
.php-файли всередині uploads. Перш ніж видаляти, з’ясуйте призначення файлів, видаліть непотрібні плагіни, а вже потім діймайте решти
Підсумок
Заборона виконання PHP в каталозі uploads складається з п’яти кроків: ① знайти й видалити наявні підозрілі файли за допомогою find wp-content/uploads -name ".php"; ② в Apache додати в uploads/.htaccess блок <FilesMatch "\.(php|phar)$"> Deny from all; ③ в Nginx застосувати deny all у location ~ /wp-content/uploads/.*\.php$; ④ відхиляти саме завантаження PHP за допомогою хука wp_handle_upload_prefilter; ⑤ щогодини перевіряти cron-завданням PHP-файли в uploads.
Маєте запитання щодо WordPress? Видавець сайту перебуває в Японії й відповідає японською. Написати нам (японською)