Накратко: За да забраните изпълнението на PHP в качените файлове, първо установете всички папки, в които PHP може да пише, и след това във всяка от тях блокирайте изпълнението на скриптове в конфигурацията на сървъра, не чрез .htaccess. В Nginx блокирането трябва да действа преди общия PHP блок, в Apache принадлежи във VirtualHost с AllowOverride None. security.limit_extensions = .php в пула на FPM и тест с безвреден файл завършват работата.
Защо точно сега папките за качване имат значение
След критична уязвимост като PHP2Shell атакуващите рядко искат да изпълнят код само веднъж. Те искат да се върнат, дори сървърът да бъде пачнат по-късно. Най-простият път за това е уеб шел: малък PHP файл, оставен в папка с право за писане и извикан по-късно през браузъра.
Пачът не премахва такъв файл. Който след 20 октомври 2026 г. е бил онлайн непачнат, затова трябва не само да актуализира, но и да провери дали някъде има нови PHP файлове, и занапред да попречи те да се изпълняват. Как да тълкувате находките, описва PHP файлове в папката за качване: правилно тълкуване на находките.
Блокирането на изпълнението се насочва към второто условие. То не пречи файлът да бъде оставен, но пречи сървърът да го третира като програма.
Първо инвентаризация: къде може PHP да пише?
Повечето ръководства посочват само папката за качване. На практика едно PHP приложение пише на много повече места. Всяко от тях, което е достъпно през уеб сървъра, се нуждае от блокиране.
| Вид папка | Типично съдържание | Защо е с право за писане |
|---|---|---|
| Качвания, медия | изображения, PDF, прикачени файлове | потребители и редакция качват файлове |
| Кеш | генерирани страници, умалени изображения | приложението ускорява връщането |
| Temp, импорт, експорт | CSV файлове, междинни състояния | интерфейси и обмен на данни |
| Резервни копия в уеб корена | .zip, .sql |
разширенията запазват „на място“ |
| Логове в уеб корена | логове за грешки и отстраняване | неправилно конфигурирани приложения |
Кои папки са това на Вашия сървър, показва търсене с правата на потребителя на изпълнението. То не променя нищо:
# Всички папки под /var/www, в които потребителят на PHP може да пише
# (адаптирайте потребителя: www-data, nginx, apache или собствен потребител на пул)
sudo -u www-data find /var/www -type d -writable 2>/dev/null | sort
# Има ли вече PHP файлове в тези папки?
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
Ако първото търсене върне целия уеб корен, програмният код принадлежи на потребителя на изпълнението. Това трябва да промените предварително, както описва ръководството Права върху файловете на уеб сървъра. Иначе няма папка, която да не трябва да бъде блокирана.
Забрана за изпълнение на PHP в качените файлове: Nginx
При Nginx редът решава. Според документацията на Nginx регулярните изрази се проверяват в реда на конфигурационния файл и първото съвпадение печели. Ако общият блок location ~ \.php$ стои пред Вашето блокиране, файлът се изпълнява. Обикновено префиксно location без ^~ по същата причина не защитава.
Сигурен е един регулярен израз за всички блокирани папки, който стои пред PHP блока. Той покрива и рядко използвани разширения:
server {
# ... основна конфигурация ...
# 1. Блокиране за папки с право за писане, ТРЯБВА да стои пред PHP блока
location ~* ^/(uploads|media|cache|tmp|export)/.*\.(php\d?|phtml|phar|pht|phps)$ {
deny all;
}
# 2. Общ PHP блок: предавайте само съществуващи файлове
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;
}
}
Адаптирайте имената на папките към Вашата инвентаризация. При приложения с една-единствена входна точка пътят чрез списък с разрешени е още по-силен; модела показва Сигурна конфигурация на Nginx за PHP.
Apache и PHP-FPM: блокирането на правилното място
В Apache блокирането принадлежи в конфигурацията на сървъра или във VirtualHost. .htaccess в папката за качване е неподходящ, защото всеки, който може да пише там, може да го промени. За целия уеб корен затова важи AllowOverride None. Според документацията на Apache AllowOverride е позволено само в блокове <Directory> без регулярни изрази, затова го задайте на уеб корена, а блокирането чрез <DirectoryMatch> под него:
<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>
Ако още работи mod_php, допълнете в същия блок php_admin_flag engine off. При PHP-FPM втора преграда действа в пула: security.limit_extensions определя кои разширения FPM изобщо изпълнява. Според ръководството на PHP стойността по подразбиране е .php .phar; препоръчва се ограничаване до .php.
; в пула, напр. /etc/php/8.3/fpm/pool.d/seite1.conf
security.limit_extensions = .php
Тестване с безвреден файл
Дали блокирането действа, показва само тест. Поставете за кратко във всяка блокирана папка файл, който само извежда текст, извикайте го през домейна и го изтрийте след това.
- Проверете конфигурацията:
nginx -tреспективноapachectl configtest, след това презаредете. - Създайте тестов файл, например
uploads/sperrtest.phpсъс съдържание<?php echo 'ausgefuehrt';. - Извикайте с
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/uploads/sperrtest.php. Очаква се403. - Ако вместо това се появи
200и текстът „ausgefuehrt“, блокирането не действа. Проверете конфигурацията и реда. - Изтрийте тестовия файл и повторете теста за всяка папка и всеки сайт.
Ако при инвентаризацията вече намерите непознати PHP файлове в папки с право за писане, не изтривайте нищо прибързано. Първо запазете състоянието и логовете, защото тези файлове са доказателствен материал. Как да продължите тогава, описва Разпознаване и премахване на уеб шелове.
Как функциите за качване се изграждат сигурно в кода, с проверка на типа и съхранение извън уеб корена, е описано в ръководството Сигурна реализация на качване на файлове в PHP.
Извод: писане да, изпълнение не
Блокирането на изпълнението в папки с право за писане е една от най-ефективните единични мерки срещу трайни задни врати. То струва няколко реда конфигурация и при чисто изградени приложения не чупи нищо. Решаващи са три неща: пълна инвентаризация вместо само очевидната папка за качване, правилният ред в Nginx респективно правилното ниво в Apache и истински тест с безвреден файл.
Допълнено с отделни собственици за програмния код, security.limit_extensions в пула и редовно търсене на нови PHP файлове, се стига до състояние, в което оставен файл е досаден, но едва ли още използваем. Това не замества нито актуализацията, нито търсенето на следи, но отнема на атакуващите един от най-важните им инструменти.
Как помага PHP SOS конкретно?
- Инвентаризация: установяваме всички папки с право за писане за всеки сайт и ги проверяваме за налични PHP файлове.
- Задаване на блокирания: вписваме блокиранията на изпълнението в Nginx, Apache и PHP-FPM, в правилния ред и без зависимост от
.htaccess. - Тестване: всяко блокиране проверяваме с безвреден файл и документираме резултата.
- Почистване: при находки поемаме запазването на следите и премахването на зловреден софтуер.
Често задавани въпроси
Достатъчен ли е .htaccess в папката за качване, за да се забрани PHP?
Не надеждно. Който може да пише в папката, може да промени или замени и .htaccess. Блокирането принадлежи в конфигурацията на сървъра или във VirtualHost, а за уеб корена трябва да важи AllowOverride None.
Кои папки трябва да блокирам?
Всички папки, в които потребителят на PHP може да пише и които са достъпни през уеб сървъра. Освен папките за качване това често са директории за кеш, временни файлове, импорт, експорт и резервни копия. Установете ги чрез търсене като потребителя на изпълнението.
Ще счупи ли блокирането моя сайт?
По правило не, защото в папките за качване и кеш при чисти приложения няма скриптове, които да се извикват директно. Отделни разширения обаче все пак оставят там PHP файлове. Затова тествайте най-важните функции след прехода.
Защитава ли блокирането от PHP2Shell?
Не. PHP2Shell е уязвимост в интерпретатора на PHP, която се затваря само чрез актуализация и рестартиране на всички worker процеси. Блокирането обаче предотвратява по-късно оставен файл да бъде извикан през браузъра и използван като трайна задна врата.