Дверь, которой нет

Знаете, любой ресурс в интернете получает "левые" запросы. Просто большинство не смотрит в логи.

Сейчас вот "по нужде" зашел на сервер одного из свежих проектов. Банально - обновить, посмотреть, убедиться что ничего не упало. Заодно глянул кто и насколько был любопытным в плане уязвимостей.

Представляю ТОП-10 левых запросов за неделю с количеством попыток:

cgi-bin/authLogin.cgi - 363 попытки. .env - 230. wp-login.php - 143. .DS_Store - 129. config.json - 99. index_sso.php - 75. php/thinkphp/aaaffff123.php - 75. docker/.env - 68. AwsConfig.json - 66. .env.production - 65.

Ей богу, так и хочется спросить - "ну вот куда вы лезете"? И засмеяться неприятным смехом диснеевского злодея.

Это не атаки конечно - это фон. Боты шарятся по всему интернету и проверяют всех подряд. Ищут QNAP, WordPress, конфиги, переменные окружения. Всё, что не должно быть видно, или должны быть - дырявый как решето phpmyadmin к примеру. :)

Стандартный подход в традиционной разработке - закрыть дверь. .htaccess с deny. location в Nginx. Стучится куда не следует - получает 403. Система говорит: я тебя видела, я тебя отвергаю. Работает. Но атакующий ведь знает, что дверь есть. Просто не может открыть. Пока. И идёт к следующей.

Подумав, я сделал иначе. Убрал вообще двери из стены.

Всё стекается в одну точку. Через .htaccess любой запрос - к чему угодно - идёт на index.php. URI запроса сохраняется как параметр. Файл, к которому обратились, не выполняется. Веб-сервер не ищет его, не проверяет его существование. Просто передаёт управление в роутер.

Прямой вызов PHP-файла не срабатывает. Не потому что защищён. Не потому, что он вне рабоей директории сайта. И не потому что запрет стоит. А потому что файла нет как точки входа. Веб-сервер его не выполняет. Запрос уходит в index.php. И уже роутер решает, существует ли такой маршрут. Если нет - это сигнал.

Модуль не найден - запрос невалиден. Контроллер или экшен отсутствуют - мягкое перенаправление с сохранением URL запроса: на предыдущую страницу, или на главную. Никаких 404 или 403. Просто другая страница. Пользователь думает, что он на одной странице, а на самом деле - на другой. Контент есть. Система работает. Всё нормально.

Это не защита. Это мимикрия. Блокировка - сигнал. Мимикрия - отсутствие сигнала. Ты не знаешь, что тебя отсекли. Ты думаешь, что ты внутри.

Дальше - наблюдение. Любой запрос к несуществующему исполняемому файлу фиксируется. URL и количество попыток - то, что я выше показал. Это не бан. Это фиксация. Я не говорю "ты забанен". Бан провоцирует. Тихое наблюдение - нет.

И ещё. При подозрительных запросах система редиректит на собственный IP того, кто стучится. Сканер ждёт ответ сервера? Да пожалуйста! Рассматривай ответ на здоровье! Вернется? Ну нет проблем - снова получит себя же. Это не защита. Это ловушка для логики.

Массовый подход - охрана. Реагирует на угрозу. Ставит стену. Ждёт, когда постучат. А стучат всегда. Каждый день. Каждый час.

Мой подход - защита на уровне архитектуры. Вместо защиты от угрозы, я просто не даю угрозе появиться как точке входа. Файл, который нельзя выполнить напрямую, не существует как дверь. Его нельзя открыть. Его просто нет. Есть роутер. И роутер решает. Такая вот суперпозиция в квантовом мире WEB.

Охрана отвечает на вопрос "как не пустить". Архитектура - "зачем вообще пускать". Охрана - реакция. Архитектура - среда. Охрана работает, пока стена стоит. Архитектура - тихо решает, что двери не существует. Роутер - не стена, а воронка. Всё стекается в одну точку. Точка решает.

И вопрос. Если это работает в защите - где ещё. Где ещё охрана мешает архитектуре? Где ещё мы ставим стены, вместо того чтобы просто убрать двери? Точного ответа пожалуй нет. Но вопрос стоит задать. Стены дорого. Воронка дешевле. И надёжнее. Стена может упасть. Воронка - нет.

P.S.

И главное - всегда можно втихаря посмеяться над ботом, который анализирует на предмет уязвимости собственный сервер.