Röviden: A .env fájlt úgy védi, hogy egyáltalán nem a nyilvánosan elérhető könyvtárban van: a webroot egy public/ típusú almappára mutat, a konfiguráció egy szinttel fölötte van. Emellett a webszerver tiltja a ponttal kezdődő összes fájlt, a fájl csak a tulajdonos és a PHP-folyamat számára olvasható, és soha nem kerül a Git-repositoryba. Egy betörés után az összes benne lévő hozzáférési adat ismertnek számít, és kicserélik.
A fájl, amelyben a ház kulcsai vannak
A modern PHP-projektek szívesen tárolják a titkaikat egy .env nevű fájlban: adatbázis-jelszó, hozzáférés a levelezőszerverhez, API-kulcsok fizetési és szállítási szolgáltatásokhoz, az a kulcs, amellyel az alkalmazás a sütiket aláírja. Az olyan keretrendszerek, mint a Laravel és a Symfony, ezt a mintát használják, sok saját fejlesztés átvette.
Az ötlet jó: a konfiguráció és a kód külön van, és minden környezet saját értékeket kap. Veszélyessé akkor válik, ha a fájl rossz könyvtárba kerül. Ha a webrootban van, és a webszerver nem tiltja, egyetlen böngészőbeli hívás elég ahhoz, hogy az összes hozzáférést egyszerre elolvassa.
Ehhez jönnek az eltérő nevű változatok: .env.local, .env.production, config.local.php, vagy tárolószolgáltatások hozzáférési adatait tartalmazó fájlok. Ami itt a .env-re le van írva, az minden olyan fájlra érvényes, amelyben titkok vannak.
Az ilyen fájlokat automatizált szkennerek folyamatosan keresik. Ez nem egyes támadók specialitása, hanem az internet háttérzaja, hasonlóan a nem patchelt PHP-verziók után kutató tömeges szkennelésekhez.
Hol legyen a .env fájl
A leghatékonyabb intézkedés strukturális: a webszerver csak azt a mappát szolgálhatja ki, amelynek valóban nyilvánosnak kell lennie. A Laravelben és a Symfonyban ez a public/ mappa. Minden más, vagyis a kód, a konfiguráció, a naplók és a .env, fölötte van, és HTTP-n keresztül egyáltalán nem címezhető.
/srv/www/shop/
├── .env ← nem érhető el
├── config/
├── src/
├── vendor/
└── public/ ← az egyetlen webroot
├── index.php
└── assets/
A gyakorlatban a webroot ennek ellenére gyakran magára a projektkönyvtárra mutat, például mert egy tárhelypanel így írja elő, vagy mert költözéskor nem igazítottak ki egy útvonalat. Ezért ellenőrizze a webszerver-konfigurációban vagy a panelben, hová mutat a root, illetve a DocumentRoot.
.env fájl védelme: tiltás a webszerverben mint második vonal
Ha a webroot nem módosítható, vagy további biztosítást szeretne, tiltsa le a rejtett fájlokat a webszerverben. A .well-known mappának közben elérhetőnek kell maradnia, mert többek között a tanúsítványok kiállításához használják.
# A ponttal kezdődő összes fájl és mappa tiltása, kivéve a .well-known
location ~ /\.(?!well-known/) {
deny all;
return 404;
}
# A ponttal kezdődő fájlok tiltása
<FilesMatch "^\.">
Require all denied
</FilesMatch>
A 403 helyett 404-es válasz nem árulja el, hogy a fájl létezik. Hogy a tiltás működik-e, kívülről ellenőrizze:
# Várt eredmény: 403 vagy 404, soha nem 200
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.env
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.env.example
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.env.bak
Az utolsó két sor nem véletlen: az olyan másolatok, mint a .env.bak vagy a .env.old, karbantartási munkák során keletkeznek, és gyakran elfelejtik őket. Az ilyen maradványokról többet ír a Mentésfájlok a webrootban.
Jogok, Git és a másolatok kezelése
A webrooton kívül is érvényes a legkisebb jogosultság elve. Egy bevált felosztás:
- A tulajdonos a telepítési felhasználó, nem a PHP-folyamat.
- A csoport a PHP-FPM-pool csoportja, amely csak olvashat; jogok:
640. - Nincs írási hozzáférés a PHP-folyamat számára. Egy alkalmazásnak nem kell tudnia módosítani a saját hozzáférési adatait.
- Nincsenek valódi értékek a repositoryban: csak a helyőrzőket tartalmazó
.env.examplekerül be, a valódi fájl a.gitignore-ban áll. - Környezetenként külön értékek: a fejlesztés, a staging és az éles használat különböző hozzáféréseket használ, hogy egy tesztkörnyezet szivárgása ne nyissa meg az élesét.
chown deploy:shop-php /srv/www/shop/.env
chmod 640 /srv/www/shop/.env
# Ellenőrizni, hogy a fájlt valaha bejegyezték-e
git log --all --oneline -- .env
Ügyeljen a hibaoldalakra is. A keretrendszerek debug módban néha megjelenítenek környezeti változókat és konfigurációs értékeket; éles rendszeren ennek a módnak ki kell lennie kapcsolva. Ellenőrizze ezt minden telepítés után, mert magában a .env-ben egy hibás érték újra bekapcsolhatja.
Ha az utolsó parancs találatokat ad, a hozzáférési adatok a Git-előzményekben vannak, és nyilvánosságra került adatnak számítanak, még ha a fájl ma nincs is meg. Hogy ez miért különösen kényes, ha a .git mappa a szerveren van, azt a Nyilvános .git mappa: egy alábecsült adatszivárgás írja le. A jogosultságok alapjait a Fájljogosultságok a webszerveren útmutató magyarázza.
A phpinfo()-t tartalmazó tesztfájlok megjelenítik a környezeti változókat. Aki a titkokat környezeti változókként adja át, egy elfelejtett tesztfájlon keresztül elárulja őket. A háttér a phpinfo()-fájlok: miért kell eltűnniük cikkben olvasható.
Egy betörés után: a hozzáférési adatok cseréje
Semmilyen tiltás nem véd egy olyan támadó ellen, aki már kódot hajt végre a szerveren. A PHP-folyamatnak el kell tudnia olvasni a konfigurációját, tehát a beinjektált kód ugyanabban a folyamatban ezt is megteheti. A PHP2Shell után ezért ez érvényes: ha egy betörés nem zárható ki, a szerveren lévő összes hozzáférési adatot ismertnek kell tekinteni.
A rendezett csere magában foglalja az adatbázis-jelszavakat, a levelezési és SMTP-hozzáféréseket, a külső szolgáltatások API-kulcsait, az alkalmazás aláíró kulcsait és a tárolószolgáltatások hozzáféréseit. A sorrendet és az időpontot tervezni kell: aki előbb cserél, és csak utána tisztítja meg a szervert, az új értékeket esetleg rögtön a támadónak is odaadja.
Egy szivárgás kárát már előre korlátozza, ha minden titok csak annyit tehet, amennyi szükséges. A weboldal adatbázis-felhasználójának nincs szüksége jogokra más adatbázisokon. A külső szolgáltatások API-kulcsai sok szolgáltatónál egyes funkciókra vagy feladócímekre korlátozhatók, például szállítmányok létrehozására, de kifizetések indítására nem. És minden alkalmazás saját hozzáférést kap, ahelyett hogy több weboldal ugyanazt a levelezőfiókot vagy ugyanazt a kulcsot osztaná meg. Ekkor egy szivárgás egy jól körülhatárolt területet érint, és a csere áttekinthető marad.
Konténerkörnyezetekben a .env fájl sem a képbe, sem nyilvánosan elérhető registrybe nem tartozik. Zárja ki a .dockerignore-ral, és a titkokat csak futásidőben, a platform mechanizmusain keresztül adja át.
Hosszabb távon érdemes a központi secret-tárolókat megnézni, ahogyan az OWASP ajánlja: a titkok egy helyen, hozzáférési naplóval, rendszeres cserével és lehetőleg rövid érvényességgel.
Hogyan segít konkrétan a PHP SOS?
- Kívülről ellenőrizzük, hogy a weboldalai konfigurációs fájljai, másolatai és rejtett fájljai lekérhetők-e.
- A webrootot, a webszerver-tiltásokat és a fájljogokat úgy állítjuk át, hogy a titkok HTTP-n keresztül már ne legyenek elérhetők.
- Ellenőrizzük a repositorykat és a telepítéseket bejegyzett hozzáférési adatok után.
- Egy incidens után megtervezzük és kísérjük az összes érintett hozzáférés cseréjét a helyes sorrendben.
Ezek a munkák a PHP-webszerverek keményítésének részei.
Gyakori kérdések
A webrootban lévő .env fájl automatikusan nyilvános?
Nem automatikusan, de gyakran. Hogy lekérhető-e, a webszerver konfigurációjától függ. Sok alapértelmezett konfiguráció csak a .htaccess fájlokat védi, a ponttal kezdődő többi fájlt nem. Egy curl-lel végzett teszt tisztázza a helyzetet.
A környezeti változók biztonságosabbak, mint egy .env fájl?
Alapvetően nem. Az OWASP rámutat, hogy a környezeti változók a felhasználó minden folyamata számára olvashatók, és megjelenhetnek naplókban vagy memóriaképekben. Elkerülnek viszont egy fájlt a webrootban. Jobbak a központi secret-tárolók, ahol a környezet támogatja őket.
Mit tegyek, ha a .env fájl lekérhető volt?
Az összes benne lévő hozzáférési adatot ismertnek kell tekinteni és ki kell cserélni: adatbázis, levelezés, API-k, fizetési szolgáltatók, az alkalmazás kulcsai. Utána a hozzáférési naplókban ellenőrizze, hogy lekérték-e a fájlt, és személyes adatok esetén vonja be az adatvédelmi tisztviselőt.
A .env fájl a Git-repositoryba tartozik?
Nem. A repositoryba legfeljebb egy valódi értékek nélküli sablon tartozik, például a .env.example. A valódi fájlt a .gitignore kizárja, és a szerveren külön biztosítják.
Elárulhat a phpinfo() hozzáférési adatokat?
Igen. A phpinfo() többek között környezeti és szerverváltozókat jelenít meg. Ha titkok vannak ott, azok is kiíródnak. A phpinfo()-t tartalmazó tesztfájlok ezért soha nem valók elérhető rendszerre.