Aktuel situation: PHP2Shell. To kritiske PHP-sårbarheder (CVSS 9,2) tillader skadelig kode uden login. Rettelser siden 21.10.2026.Hvad der skal gøres nu →

Beskyt adgangsdata og .env-filer rigtigt

Sådan beskytter I databaseadgangskoder, API-nøgler og andre hemmeligheder i PHP-projekter: .env-filer uden for webroot, spærring i webserveren, snævre rettigheder og ordnet udskiftning efter en hændelse.

Status 5 min. læsetidSikker udvikling

Kort sagt: En .env-fil beskytter I ved, at den slet ikke ligger i den offentligt tilgængelige mappe: Webroot peger på en undermappe som public/, konfigurationen ligger ét niveau over. Desuden spærrer webserveren alle filer med punktum først, filen kan kun læses af ejeren og PHP-processen, og den hører aldrig hjemme i Git-repositoryet. Efter et indbrud gælder alle adgangsdata deri som kendte og udskiftes.

Filen med nøglerne til huset

Moderne PHP-projekter gemmer gerne deres hemmeligheder i en fil ved navn .env: databaseadgangskode, adgang til mailserveren, API-nøgler til betalings- og forsendelsestjenester, nøglen, som applikationen signerer cookies med. Frameworks som Laravel og Symfony bruger dette mønster, mange egenudviklinger har overtaget det.

Idéen er god: Konfiguration og kode er adskilt, og hvert miljø får egne værdier. Det bliver farligt, når filen havner i den forkerte mappe. Ligger den i webroot, og spærrer webserveren den ikke, er ét eneste kald i browseren nok til at læse alle adgange på én gang.

Dertil kommer varianter med andre navne: .env.local, .env.production, config.local.php eller filer med adgangsdata til lagertjenester. Det, der her er beskrevet for .env, gælder alle filer, hvori der står hemmeligheder.

Sådanne filer søges løbende af automatiserede scannere. Det er ikke en specialitet hos enkelte angribere, men baggrundsstøj på internettet, ligesom masseskanningerne efter upatchede PHP-versioner.

Hvor .env-filen bør ligge

Den mest virkningsfulde foranstaltning er strukturel: Webserveren må kun levere den mappe, der virkelig skal være offentlig. I Laravel og Symfony er det mappen public/. Alt andet, altså kode, konfiguration, logge og .env, ligger over den og kan slet ikke adresseres via HTTP.

/srv/www/shop/
├── .env              ← ikke tilgængelig
├── config/
├── src/
├── vendor/
└── public/           ← eneste webroot
    ├── index.php
    └── assets/

I praksis peger webroot alligevel ofte på selve projektmappen, f.eks. fordi et hostingpanel foreskriver det, eller fordi en sti ikke blev tilpasset ved flytningen. Kontrollér derfor i webserverkonfigurationen eller i panelet, hvor root hhv. DocumentRoot peger hen.

Beskyt .env-filen: Spærring i webserveren som anden linje

Kan webroot ikke ændres, eller ønsker I en ekstra sikring, spærrer I skjulte filer i webserveren. Mappen .well-known skal her forblive tilgængelig, fordi den bl.a. bruges til udstedelse af certifikater.

# Spær alle filer og mapper med punktum først, undtagen .well-known
location ~ /\.(?!well-known/) {
    deny all;
    return 404;
}
# Spær filer med punktum først
<FilesMatch "^\.">
    Require all denied
</FilesMatch>

Et svar med 404 i stedet for 403 afslører ikke, at filen findes. Om spærringen virker, kontrollerer I udefra:

# Forventet: 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 sidste to linjer er ingen tilfældighed: Kopier som .env.bak eller .env.old opstår ved vedligeholdelsesarbejde og glemmes ofte. Mere om sådanne levn står i Backupfiler i webroot.

Rettigheder, Git og håndtering af kopier

Også uden for webroot gælder princippet om færrest mulige rettigheder. En gennemprøvet fordeling:

  1. Ejer er deploy-brugeren, ikke PHP-processen.
  2. Gruppe er PHP-FPM-poolens gruppe, som kun må læse; rettigheder 640.
  3. Ingen skriveadgang for PHP-processen. En applikation behøver ikke at kunne ændre sine egne adgangsdata.
  4. Ingen rigtige værdier i repositoryet: Kun .env.example med pladsholdere tjekkes ind, den rigtige fil står i .gitignore.
  5. Adskilte værdier pr. miljø: Udvikling, staging og produktion bruger forskellige adgange, så et læk i et testmiljø ikke åbner produktionen.
chown deploy:shop-php /srv/www/shop/.env
chmod 640 /srv/www/shop/.env
# Kontrollér, om filen nogensinde er blevet tjekket ind
git log --all --oneline -- .env

Vær også opmærksom på fejlsider. Frameworks viser i debug-tilstand til dels miljøvariabler og konfigurationsværdier; på et produktivt system skal denne tilstand være slået fra. Kontrollér det efter hvert deployment, for en forkert værdi i selve .env kan tænde den igen.

Giver den sidste kommando fund, står adgangsdata i Git-historikken og gælder som afsløret, selv om filen i dag mangler. Hvorfor det er særligt kildent, når .git-mappen ligger på serveren, beskriver Offentlig .git-mappe: Et undervurderet datalæk. Grundlæggende om rettigheder forklarer vejledningen Filrettigheder på webserveren.

Vigtigt

Testfiler med phpinfo() viser miljøvariabler. Den, der overgiver hemmeligheder som miljøvariabler, afslører dem via en glemt testfil. Baggrunden står i phpinfo()-filer: Hvorfor de skal forsvinde.

Efter et indbrud: Udskift adgangsdata

Ingen spærring beskytter mod en angriber, der allerede udfører kode på serveren. En PHP-proces skal kunne læse sin konfiguration, så indsmuglet kode i samme proces kan det også. Efter PHP2Shell gælder derfor: Kan et indbrud ikke udelukkes, skal alle adgangsdata på serveren behandles som kendte.

En ordnet udskiftning omfatter databaseadgangskoder, mail- og SMTP-adgange, API-nøgler til eksterne tjenester, applikationens signaturnøgler og adgange til lagertjenester. Rækkefølge og tidspunkt bør planlægges: Den, der først udskifter og så rydder serveren op, giver måske angriberen de nye værdier med det samme.

Skaden ved et læk begrænser I allerede på forhånd ved, at hver hemmelighed kun må så meget som nødvendigt. Websitets databasebruger behøver ingen rettigheder til andre databaser. API-nøgler til eksterne tjenester kan hos mange udbydere begrænses til enkelte funktioner eller afsenderadresser, f.eks. oprette forsendelser, men ikke igangsætte udbetalinger. Og hver applikation får egne adgange, i stedet for at flere websites deler den samme mailkonto eller den samme nøgle. Så berører et læk et klart afgrænset område, og udskiftningen forbliver overskuelig.

I containermiljøer hører .env-filen hverken hjemme i imaget eller i et offentligt tilgængeligt registry. Udelukk den via .dockerignore, og overgiv først hemmeligheder ved kørsel via platformens mekanismer.

På længere sigt er det værd at se på centrale secret-lagre, som OWASP anbefaler dem: hemmeligheder ét sted, med adgangslog, regelmæssig udskiftning og så kort gyldighed som muligt.

Hvordan hjælper PHP SOS konkret?

  • Vi kontrollerer udefra, om konfigurationsfiler, kopier og skjulte filer på jeres websites kan hentes.
  • Vi omstiller webroot, webserverspærringer og filrettigheder, så hemmeligheder ikke længere kan nås via HTTP.
  • Vi kontrollerer repositories og deployments for indtjekkede adgangsdata.
  • Efter en hændelse planlægger og ledsager vi udskiftningen af alle berørte adgange i den rigtige rækkefølge.

Disse arbejder er en del af vores serverhærdning til PHP-webservere.

Ofte stillede spørgsmål

Er en .env-fil i webroot automatisk offentlig?

Ikke automatisk, men ofte. Om den kan hentes, afhænger af webserverkonfigurationen. Mange standardkonfigurationer beskytter kun .htaccess-filer, ikke andre filer med punktum først. En test med curl skaber klarhed.

Er miljøvariabler sikrere end en .env-fil?

Ikke principielt. OWASP påpeger, at miljøvariabler kan læses af alle brugerens processer og kan dukke op i logge eller hukommelsesudtræk. De undgår dog en fil i webroot. Bedre er centrale secret-lagre, hvor miljøet understøtter dem.

Hvad gør man, hvis .env-filen kunne hentes?

Betragt alle adgangsdata deri som kendte og udskift dem: database, mail, API'er, betalingstjenester, applikationens nøgler. Kontrollér derefter i adgangsloggene, om filen blev hentet, og inddrag databeskyttelsesrådgiveren, hvis der er personoplysninger.

Hører .env-filen hjemme i Git-repositoryet?

Nej. I repositoryet hører højst en skabelon uden rigtige værdier, f.eks. .env.example. Den rigtige fil udelukkes via .gitignore og stilles separat til rådighed på serveren.

Kan phpinfo() afsløre adgangsdata?

Ja. phpinfo() viser blandt andet miljøvariabler og servervariabler. Ligger hemmeligheder dér, bliver de udskrevet med. Testfiler med phpinfo() hører derfor aldrig hjemme på et tilgængeligt system.

Kilder

Akut kontakt

Hver time tæller. Skriv til os nu.

Beskriv kort system, PHP-version og observation. Vi vender tilbage, afklarer situationen og arbejder på afstand, indtil hændelsen er afsluttet og dokumenteret.

Akut hjælp