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

Серверы

Управление секретами и ключами: .env, токены и ротация

Где хранить .env, API-токены, пароли от базы и ключи шифрования, кто должен иметь к ним доступ и когда их менять — практическое руководство.

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

Фото: plenty.r. from Frankfurt am Main, CC BY-SA 2.0 · Wikimedia Commons

Любое веб- и мобильное приложение работает с секретами: пароль от базы данных, APP_KEY, токен SMS- или платёжного провайдера, пароль SMTP, ключи внешних API. Каким бы аккуратным ни был код, одного утёкшего токена может хватить для входа в систему. Поэтому перед экспертизой секреты нужно проверять не по принципу «в коде их нет», а отвечая на вопросы: где они лежат, кто их видит, когда их меняли.

Где живут секреты

Начните с инвентаризации. Обычно секреты находятся:

  • в файле .env на сервере;
  • в репозитории и его истории (включая старые коммиты);
  • в настройках CI/CD и логах сборки;
  • в резервных копиях (в архив попадает и .env);
  • в логах приложения (вместе с телом запроса или заголовками);
  • в сборке мобильного приложения (строки внутри APK/IPA);
  • в рабочих чатах и документах.

Составьте простую таблицу для каждого секрета: название, к какой системе даёт доступ, у кого есть, когда последний раз менялся.

1. .env не должен попадать в репозиторий

Проверьте, что .env есть в .gitignore, но этого мало — файл мог быть закоммичен раньше. Просканируйте историю:

gitleaks detect --source . --log-opts="--all"

Если в истории найден настоящий секрет, удалить его из истории недостаточно: копии репозитория могут уже быть в других местах. Правильное решение — заменить секрет (ротация). В .env.example должны быть только имена ключей и пустые или примерные значения.

2. .env не должен открываться из браузера

В Laravel и других фреймворках корнем веб-сервера должен быть каталог public/. Если корень настроен неверно, https://site.uz/.env скачивается напрямую. Дополнительная защита в Nginx:

location ~ /\.(?!well-known) {
    deny all;
}

Проверка: curl -I https://site.uz/.env и curl -I https://site.uz/.git/config — оба должны вернуть 403 или 404.

3. Права на файлы

.env должны читать только пользователь, под которым работает приложение, и пользователь деплоя:

chown deploy:www-data .env
chmod 640 .env

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

4. Принцип наименьших привилегий

Каждый токен должен уметь только то, что нужно:

  • приложение подключается к базе не под root или суперпользователем, а под пользователем с правами только на свою базу;
  • ключи внешних API по возможности ограничены по IP или домену;
  • там, где нужно только чтение, не выдаются права на запись;
  • для теста и production — разные ключи.

Тогда даже при утечке одного ключа ущерб будет ограничен.

5. В логах не должно быть секретов

Логи ошибок часто записывают полное тело запроса: пароль, OTP-код, заголовок Authorization. Настройте уровень логирования для production, маскируйте чувствительные поля и проверьте, что storage/logs не открывается из браузера. APP_DEBUG=false в Laravel — тоже часть этого пункта: отладочная страница может показать переменные окружения.

6. Не храните секреты в мобильном приложении

Распаковать APK или IPA и посмотреть строки внутри несложно. Поэтому не встраивайте в приложение серверные секретные ключи (секретный ключ платёжного провайдера, админский токен) — они должны быть только на бэкенде. По итогам мобильной экспертизы нашего собственного продукта мы убрали хранение endpoint'ов открытыми строками, включили минификацию R8 и Dart --obfuscate, а пользовательские токены перенесли в Keystore/Keychain через flutter_secure_storage. Обфускация усложняет анализ, но не защищает секрет — секрета в приложении не должно быть вовсе.

7. Ротация: когда и как

Ротация — замена секрета новым и отзыв старого. Обязательно выполняйте её, если:

  • секрет засветился в репозитории, логе или чате;
  • из команды ушёл сотрудник, у которого был доступ;
  • на сервере или компьютере сотрудника замечено что-то подозрительное;
  • перед экспертизой, если секреты давно не менялись.

Порядок безопасной ротации:

  1. Создайте новый ключ (в панели провайдера или новый пароль).
  2. Запишите новое значение в .env и перезагрузите приложение (php artisan config:cache, перезапуск PHP-FPM и queue worker'ов).
  3. Проверьте, что приложение работает.
  4. Отзовите старый ключ на стороне провайдера.
  5. Обновите дату в таблице.

Удаление секрета не делает его безопасным. Утёкший секрет обезвреживается только заменой.

Отдельно про APP_KEY

В Laravel APP_KEY используется для cookie, сессий и данных, зашифрованных через Crypt. Если просто заменить его, активные сессии и зашифрованные поля перестанут читаться. Начиная с Laravel 11 есть переменная APP_PREVIOUS_KEYS: укажите в ней старый ключ, и приложение сможет читать старые данные, а новые шифровать новым ключом.

8. Резервные копии

Архивы резервных копий часто содержат весь каталог проекта, включая .env. Храните их вне веб-корня, шифруйте и ограничивайте доступ. Проверьте, что в public/ не остались файлы вроде backup.zip или site.tar.gz.

Краткий чек-лист

  • .env нет в репозитории и его истории.
  • /.env и /.git/config не открываются из браузера.
  • Права на .env — 640, владелец верный.
  • Приложение подключается к базе под ограниченным пользователем.
  • В логах нет паролей, токенов и OTP.
  • В мобильной сборке нет серверных секретов.
  • Для каждого секрета известны владелец и дата последней ротации.

Вывод

Управление секретами начинается не со сложных инструментов, а с порядка: инвентаризация, наименьшие привилегии, закрытие открытых мест и регулярная ротация. Эти пункты дают спокойствие и на экспертизе, и в повседневной работе.

Перед экспертизой Sipar проверяет настройки сервера, репозиторий и сборки в том числе на секреты и закрывает найденные места. Оставьте заявку на сканирование.