В современных проектах на PHP и Node.js все секретные настройки обычно хранятся в одном файле .env: логин и пароль базы данных, данные почтового сервера, ключи платёжных систем, токен Telegram-бота и так далее. Это удобно, потому что код отделён от конфигурации. Но если файл оказался в публичной папке веб-сервера, его можно прочитать как обычный текст, просто набрав в браузере https://example.uz/.env. Один такой запрос отдаёт злоумышленнику почти все ключи вашего сайта.
Почему эта ошибка так распространена
Фреймворки вроде Laravel устроены так, что корень веб-сервера должен указывать только на папку public, а .env лежит уровнем выше. Проблема возникает при переносе на хостинг: разработчик кладёт весь проект в корень сайта и добавляет .htaccess с перенаправлением на public/index.php. В итоге .env тоже оказывается в корне, и в зависимости от настроек сервер может отдать его напрямую. То же самое происходит с копиями вроде .env.backup, .env.old или оставленного редактором .env~ — о них часто просто забывают.
Боты, которые ищут такие файлы, работают без перерыва. Откройте журнал доступа сайта, и вы почти каждый день увидите запросы к /.env, /api/.env, /laravel/.env. Это не значит, что ваш сайт выбрали целью: автоматические сканеры просто перебирают все адреса подряд, поэтому аргумент «мой сайт маленький, кому он нужен» здесь не работает.
Как проверить свой сайт
Проще всего проверить командой curl в терминале. Если код ответа 403 или 404 и в содержимом нет строк вроде DB_PASSWORD, файл закрыт. Если вернулся код 200 и показалось содержимое файла, нужно действовать немедленно. Проверьте отдельно основной домен, версию с www и поддомены — они могут смотреть в разные папки.
curl -s -o /dev/null -w "%{http_code}\n" https://example.uz/.env
curl -s https://example.uz/.env | head -5
# кто запрашивал файл
grep '"GET /.env' access.log | tail -20
Лучшее решение: вынести файл за пределы веб-корня
Никакое правило не надёжнее, чем хранение файла вне корня сайта. Если веб-сервер файл вообще «не видит», он не отдаст его даже при ошибке в настройках. На VPS или если панель позволяет менять папку сайта, направьте корень на папку public проекта. На хостинге sayt.uz эта настройка находится в панели ISPmanager, которая открывается из кабинета sayt.uz; если не знаете, как это сделать, можно обратиться в техническую поддержку.
/home/user/example.uz/
├── .env # недоступен из веба
├── app/
├── vendor/
└── public/ # корень веб-сервера
└── index.php
Если файл обязан остаться в корне
Иногда структура хостинга не позволяет сменить корень. Тогда нужно запретить доступ ко всем файлам, начинающимся с точки, на уровне веб-сервера. Для Apache 2.4 правило ниже записывается в .htaccess и закрывает .env вместе со всеми его копиями. В Nginx добавляется блок location для скрытых файлов, но с исключением для папки .well-known, которая нужна для выпуска сертификатов Let's Encrypt.
# .htaccess (Apache 2.4)
<FilesMatch "^\.env">
Require all denied
</FilesMatch>
# Nginx: внутри блока server { }
location ~ /\.(?!well-known) {
deny all;
return 404;
}
После добавления правила повторите проверку через curl. Изменив конфигурацию Nginx, сначала проверьте синтаксис командой nginx -t, а затем выполните systemctl reload nginx, иначе новое правило не вступит в силу.
Права доступа и Git
Помимо закрытия из веба важны и права на файл на самом сервере. .env должен читаться только пользователем — владельцем сайта и быть полностью закрыт для остальных. Кроме того, файл никогда не должен попадать в Git-репозиторий: в репозиторий кладут .env.example со списком нужных переменных без значений.
chmod 600 .env
echo ".env" >> .gitignore
git rm --cached .env # если файл когда-то случайно закоммитили
Учтите, что git rm --cached убирает файл только из следующих коммитов, а в истории он остаётся. Поэтому пароли, однажды попавшие в репозиторий, нужно считать скомпрометированными.
Что делать, если файл уже утёк
Если проверка показала, что .env открыт, одного закрытия недостаточно: файл мог быть уже скачан. Выполните действия в таком порядке:
- Немедленно закройте файл одним из способов выше и повторите проверку.
- Смените пароль базы данных и запишите новый в
.env. - Обновите в соответствующих кабинетах все ключи: платёжных систем, SMS-сервиса, почты, токены ботов.
- Рассмотрите замену
APP_KEYв Laravel, но заранее изучите, как это повлияет на зашифрованные данные и сессии. - По журналам доступа определите, когда и с каких IP запрашивался файл, и проверьте, не появились ли в базе посторонние пользователи.
Пример: сайт гостиницы в Бухаре
Сайт бронирования небольшой бухарской гостиницы был написан на Laravel и перенесён на хостинг целиком. Однажды администратор заметил, что с почты сайта ушли сотни писем на незнакомые адреса: .env оказался открытым, и с его SMTP-паролем рассылали спам. Разработчик перенёс корень сайта в папку public, сменил пароли почты и базы и добавил дополнительный запрет в .htaccess. С тех пор перед запуском каждого нового проекта он обязательно выполняет проверку через curl.