Есть относительно универсальный вектор защиты своего веб-хостинга (да и наверное всего)
- это read only хранилище везде где можно (в догонку флаг noexec в маунте диска)
- цифровые подписи файлов
к сожалению php ограничен функционал в этом направлении и поддерживает цифровую подпись только у phar сборок, переделать проект на их использование может оказаться не просто (но не невозможно, в некоторых случаях и вовсе автоматом все будет)
- максимально кастриарованное окружение (спасибо docker часто это так и есть) но все же, для работы сайта может совсем не нужны 99% утилит которые установлены в системе, которые мог бы использовать злоумышленник для запуска своего кода (грубый пример, ты запретил запускать неподписанный код, убил bash но злоумышленник использует awk)
- разделяй на модули все, база данных отдельно от бакэнда, бакэнд отдельно от статичных веб файлов веб сервера и т.п.
спасибо докер народ стал этим пользоваться не задумываясь
- отключай интернет, там где он не нужен, буквально, никакого доступа в интернет бакэнду и веб сервисам не требуется, закрывай все фаерволом или даже отдельными сетями
- нестандартное окружение, даже не так - раздавай фейки, метки версий утилит, отдаваемых как либо в паблик пусть будут неправильными
пример - у тебя linux nginx, а ты в заголовках говори что ты windows apache, у тебя последняя версия wordpress, а ты возвращай версию от 2008 года и т.п. автоматические средства анализа хакеров могут на этом споткнуться, понятно что эта защита не идеальная но сильно уменьшает вероятность успешного обнаружения у тебя дыр.
- мониторинг всего нестандартного, процессы с необычными именами и командными строками, добавь ловушку песочницу, как только код злоумышленника в нее попадет - сигнал или даже остановка сервиса и ручные разбирательства
все это нужно чтобы если атакующий проникнет каким то способом внутрь, дальше что либо сделать он уже не сможет, ведь в первую очередь в атаку идут автоматизированные скрипты - залез, огляделся, сигнализировал об успехе... а как сигнализировать если файловая система ro, интернета нет, а подключение к базе данных не на локалхосте и в конфиг файле оказывается переменные называются по другому.