Kort sagt: En .env-fil skyddar ni genom att den inte alls ligger i den offentligt nåbara katalogen: Webbroten pekar på en undermapp som public/, konfigurationen ligger en nivå ovanför. Dessutom spärrar webbservern alla filer med punkt i början, filen är bara läsbar för ägaren och PHP-processen och hör aldrig hemma i Git-repositoryt. Efter ett intrång räknas alla inloggningsuppgifter i den som kända och byts ut.
Filen med nycklarna till huset
Moderna PHP-projekt lägger gärna sina hemligheter i en fil som heter .env: databaslösenord, åtkomst till e-postservern, API-nycklar för betal- och fraktleverantörer, nyckeln som applikationen signerar cookies med. Ramverk som Laravel och Symfony använder det mönstret, och många egenutvecklingar har tagit över det.
Idén är bra: Konfiguration och kod är åtskilda, och varje miljö får egna värden. Farligt blir det när filen hamnar i fel katalog. Ligger den i webbroten och webbservern inte spärrar den räcker ett enda anrop i webbläsaren för att läsa alla åtkomster på en gång.
Dessutom finns varianter med andra namn: .env.local, .env.production, config.local.php eller filer med inloggningsuppgifter till lagringstjänster. Det som här beskrivs för .env gäller alla filer där hemligheter står.
Sådana filer eftersöks ständigt av automatiserade skannrar. Det är ingen specialitet för enskilda angripare utan bakgrundsbrus på internet, liknande massskanningarna efter opatchade PHP-versioner.
Var .env-filen bör ligga
Den mest verksamma åtgärden är strukturell: Webbservern får bara leverera den mapp som verkligen ska vara offentlig. I Laravel och Symfony är det mappen public/. Allt annat, alltså kod, konfiguration, loggar och .env, ligger ovanför och går över HTTP inte alls att adressera.
/srv/www/shop/
├── .env ← inte nåbar
├── config/
├── src/
├── vendor/
└── public/ ← enda webbroten
├── index.php
└── assets/
I praktiken pekar webbroten ändå ofta på själva projektkatalogen, till exempel för att en webbhotellspanel föreskriver det eller för att en sökväg inte anpassades vid flytten. Kontrollera därför i webbserverkonfigurationen eller i panelen vart root respektive DocumentRoot pekar.
Skydda .env-filen: spärr i webbservern som andra linje
Går webbroten inte att ändra, eller vill ni ha ett extra skydd, spärrar ni dolda filer i webbservern. Mappen .well-known måste då förbli nåbar, eftersom den bland annat används för utfärdande av certifikat.
# Spärra alla filer och mappar med punkt i början utom .well-known
location ~ /\.(?!well-known/) {
deny all;
return 404;
}
# Spärra filer med punkt i början
<FilesMatch "^\.">
Require all denied
</FilesMatch>
Ett svar med 404 i stället för 403 avslöjar inte att filen finns. Om spärren fungerar kontrollerar ni utifrån:
# Väntat: 403 eller 404, aldrig 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
De två sista raderna är ingen slump: Kopior som .env.bak eller .env.old uppstår vid underhållsarbeten och glöms ofta bort. Mer om sådana kvarlevor står i Backupfiler i webbroten.
Rättigheter, Git och hantering av kopior
Även utanför webbroten gäller principen om minsta möjliga rättigheter. En beprövad uppdelning:
- Ägare är driftsättningsanvändaren, inte PHP-processen.
- Grupp är PHP-FPM-poolens grupp, som bara får läsa; rättigheter
640. - Ingen skrivåtkomst för PHP-processen. En applikation behöver inte kunna ändra sina egna inloggningsuppgifter.
- Inga riktiga värden i repositoryt: Bara
.env.examplemed platshållare checkas in, den riktiga filen står i.gitignore. - Skilda värden per miljö: Utveckling, staging och produktion använder olika åtkomster så att ett läckage i en testmiljö inte öppnar produktionen.
chown deploy:shop-php /srv/www/shop/.env
chmod 640 /srv/www/shop/.env
# Kontrollera om filen någonsin har checkats in
git log --all --oneline -- .env
Se också upp med felsidor. Ramverk visar i felsökningsläge delvis miljövariabler och konfigurationsvärden; i ett produktionssystem måste det läget vara avstängt. Kontrollera det efter varje driftsättning, för ett felaktigt värde i själva .env kan slå på det igen.
Ger det sista kommandot träffar står inloggningsuppgifterna i Git-historiken och räknas som röjda, även om filen saknas i dag. Varför det är särskilt känsligt när .git-mappen ligger på servern beskriver Offentlig .git-mapp: ett underskattat dataläckage. Grundläggande om rättigheter förklarar guiden Filrättigheter på webbservern.
Testfiler med phpinfo() visar miljövariabler. Den som lämnar över hemligheter som miljövariabler röjer dem via en bortglömd testfil. Bakgrund finns i phpinfo()-filer: varför de måste bort.
Efter ett intrång: byt ut inloggningsuppgifter
Ingen spärr skyddar mot en angripare som redan kör kod på servern. En PHP-process måste kunna läsa sin konfiguration, alltså kan inplanterad kod i samma process göra det också. Efter PHP2Shell gäller därför: Kan ett intrång inte uteslutas ska alla inloggningsuppgifter på servern behandlas som kända.
Ett ordnat utbyte omfattar databaslösenord, e-post- och SMTP-åtkomster, API-nycklar för externa tjänster, applikationens signeringsnycklar och åtkomster till lagringstjänster. Ordning och tidpunkt bör planeras: Den som byter först och sedan rensar servern ger kanske angriparen de nya värdena på köpet.
Skadan av ett läckage begränsar ni redan i förväg genom att varje hemlighet bara får göra så mycket som nödvändigt. Webbplatsens databasanvändare behöver inga rättigheter på andra databaser. API-nycklar för externa tjänster går hos många leverantörer att begränsa till enskilda funktioner eller avsändaradresser, till exempel skapa försändelser men inte initiera utbetalningar. Och varje applikation får egna åtkomster i stället för att flera webbplatser delar samma e-postkonto eller samma nyckel. Då berör ett läckage ett klart avgränsat område, och utbytet förblir överskådligt.
I containermiljöer hör .env-filen varken hemma i imagen eller i ett offentligt nåbart register. Utesluta den via .dockerignore och lämna över hemligheter först vid körtid via plattformens mekanismer.
På sikt är det värt att titta på centrala hemlighetslager, som OWASP rekommenderar: hemligheter på ett ställe, med åtkomstlogg, regelbundet utbyte och så kort giltighet som möjligt.
Hur hjälper PHP SOS konkret?
- Vi kontrollerar utifrån om konfigurationsfiler, kopior och dolda filer på era webbplatser går att hämta.
- Vi ställer om webbrot, webbserverspärrar och filrättigheter så att hemligheter inte längre är nåbara över HTTP.
- Vi kontrollerar repositories och driftsättningar efter incheckade inloggningsuppgifter.
- Efter en incident planerar och följer vi utbytet av alla berörda åtkomster i rätt ordning.
Dessa arbeten är en del av vår serverhärdning för PHP-webbservrar.
Vanliga frågor
Är en .env-fil i webbroten automatiskt offentlig?
Inte automatiskt, men ofta. Om den går att hämta beror på webbserverkonfigurationen. Många standardkonfigurationer skyddar bara .htaccess-filer, inte andra filer med punkt i början. Ett test med curl ger klarhet.
Är miljövariabler säkrare än en .env-fil?
Inte i grunden. OWASP påpekar att miljövariabler är läsbara för alla användarens processer och kan dyka upp i loggar eller minnesavbilder. De undviker dock en fil i webbroten. Bättre är centrala hemlighetslager där miljön stöder det.
Vad gör man om .env-filen gick att hämta?
Betrakta alla inloggningsuppgifter i den som kända och byt ut dem: databas, e-post, API:er, betaltjänster, applikationens nycklar. Kontrollera sedan i åtkomstloggarna om filen har hämtats och involvera vid personuppgifter dataskyddsombudet.
Hör .env-filen hemma i Git-repositoryt?
Nej. I repositoryt hör högst en mall utan riktiga värden hemma, till exempel .env.example. Den riktiga filen utesluts via .gitignore och tillhandahålls separat på servern.
Kan phpinfo() avslöja inloggningsuppgifter?
Ja. phpinfo() visar bland annat miljövariabler och servervariabler. Ligger hemligheter där skrivs de ut med. Testfiler med phpinfo() hör därför aldrig hemma på ett nåbart system.