Перейти к основному содержанию
Блог

Веб

Раскрытие информации: режим отладки, страницы ошибок и список маршрутов

Режим отладки, stack trace, версия сервера и выданный в браузер список маршрутов дают атакующему карту системы. Как это закрыть.

· 7 мин. чтения

Фото: Tamatak 'v chamatak ki, Public domain · Wikimedia Commons

Раскрытие информации (information disclosure) часто считают «мелкой» уязвимостью: само по себе оно систему не ломает. Но оно даёт атакующему самое ценное — знание о том, как устроена система. Какой фреймворк, какая версия, какие пути к файлам, какие скрытые админ-маршруты — всё это упрощает планирование следующей атаки.

При экспертизе нашего собственного продукта (SaaS-платформы для налогового и финансового учёта) по раскрытию информации было две отдельные находки. Разберём их и другие типичные источники утечек.

1. Список маршрутов в браузере

В проектах на Laravel + Inertia или Vue/React широко используется пакет Ziggy. Он позволяет вызывать именованные маршруты бэкенда в JavaScript как route('users.show', id). Удобно, но в настройках по умолчанию Ziggy встраивает в страницу все маршруты в виде JSON.

В итоге любой посетитель, открыв исходный код страницы, видит:

  • маршруты admin.* и их URL;
  • внутренние API-эндпоинты;
  • маршруты, оставшиеся от тестов, отладки или старых функций;
  • имена параметров (например, {organization}/{user}).

Именно это было зафиксировано в нашей экспертизе. Решение — отдавать в браузер только те маршруты, которые реально нужны фронтенду. В Ziggy это делается через config/ziggy.php:

return [
    'only' => ['home', 'login', 'dashboard', 'invoices.*', 'profile.*'],
    // или: 'except' => ['admin.*', 'debugbar.*', 'horizon.*', 'telescope.*'],
];

Если админка и пользовательский интерфейс живут в одном приложении, используйте группы и передавайте админ-маршруты только на админ-страницы. Помните: скрыть маршрут — не значит защитить его, это лишь уменьшает карту. Каждый маршрут всё равно должен быть защищён авторизацией на сервере.

2. Лишние данные в ответах

Вторая находка — API и Inertia возвращали больше данных, чем нужно. Например, если модель отдаётся напрямую через return $user;, в ответ могут попасть хеш пароля, внутренние идентификаторы, служебные поля или связанные модели. Даже если фронтенд их не показывает, они видны в сетевом ответе.

Решение:

  • заполните в моделях список $hidden (password, remember_token, секреты двухфакторной аутентификации);
  • лучше — возвращайте только нужные поля через API Resource или явный массив;
  • в глобальный share() Inertia кладите не всю модель пользователя, а только нужные поля.
return [
    'id' => $user->id,
    'name' => $user->name,
    'role' => $user->role,
];

3. Режим отладки и stack trace

Если в production остался APP_DEBUG=true, любая ошибка выводит подробную страницу: полные пути к файлам, фрагменты кода, параметры запроса, а иногда и переменные окружения. Это самая тяжёлая форма раскрытия информации.

.env для production:

APP_ENV=production
APP_DEBUG=false

После изменения обновите кеш конфигурации (php artisan config:cache), иначе может продолжать действовать старое значение. Также:

  • Debugbar, Telescope и подобные инструменты в production должны быть отключены или строго защищены;
  • проверьте, что пути /.env, /.git/, /storage/logs/ не открываются через веб;
  • страницы ошибок (404, 500) должны быть вашими простыми шаблонами, без внутренних деталей.

4. Заголовки с версией сервера

Многие серверы сообщают в ответе своё имя и версию:

Server: nginx/1.18.0
X-Powered-By: PHP/8.1.2

Зная версию, атакующему проще искать известные уязвимости именно для неё. Скрыть это просто:

# nginx.conf, в блоке http
server_tokens off;
; php.ini
expose_php = Off

Это не заменяет обновление сервера, но прекращает выдачу лишней информации.

Правило: каждый ответ в production должен содержать только то, что нужно пользователю. Всё остальное — в лог-файле, внутри сервера.

Проверьте сами

Проверки, которые занимают несколько минут:

  1. Откройте исходный код страницы (Ctrl+U) и поищите слова admin, api, debug.
  2. Откройте несуществующий адрес (/test-404-xyz) и посмотрите, нет ли на странице ошибки внутренних деталей.
  3. В DevTools браузера, во вкладке Network, проверьте заголовки ответа: Server, X-Powered-By.
  4. Откройте несколько ответов API и посмотрите, нет ли полей, которые не отображаются на экране.
  5. Попробуйте адреса /.env и /.git/config — оба должны возвращать 404 или 403.

Просмотр заголовков из терминала:

curl -sI https://example.uz | grep -iE 'server|x-powered-by'

Стандарты

В OWASP Top 10 (2021) эти проблемы относятся к A05 «Security Misconfiguration» и A01 «Broken Access Control». Основная категория в CWE — CWE-200 (Exposure of Sensitive Information), для stack trace — CWE-209. Раздел OWASP ASVS об ошибках и логировании требует не выводить подробные ошибки в production.

Итог

Раскрытие информации обычно закрывается несколькими строками конфигурации, но чтобы его найти, нужно посмотреть на систему глазами атакующего. В нашем процессе Claude AI агент быстро просматривает конфигурационные файлы, маршруты и структуру ответов, а специалист подтверждает каждую находку и исправляет её.

Если хотите узнать, не отдаёт ли ваш проект лишнего, оставьте заявку на сканирование. Мы поможем найти и закрыть такие уязвимости до официальной экспертизы.