Na kratko: Datoteko .env zaščitite tako, da sploh ne leži v javno dosegljivem imeniku: webroot kaže na podmapo, kot je public/, konfiguracija pa leži eno raven više. Poleg tega spletni strežnik blokira vse datoteke s piko na začetku, datoteka je berljiva samo za lastnika in proces PHP ter ne sodi nikoli v repozitorij Git. Po vdoru veljajo vsi dostopni podatki v njej za znane in se zamenjajo.
Datoteka s ključi od hiše
Sodobni projekti PHP svoje skrivnosti radi hranijo v datoteki z imenom .env: geslo baze podatkov, dostop do poštnega strežnika, ključi API za ponudnike plačil in dostave, ključ, s katerim aplikacija podpisuje piškotke. Ogrodja, kot sta Laravel in Symfony, uporabljajo ta vzorec, številni lastni razvoji so ga prevzeli.
Zamisel je dobra: konfiguracija in koda sta ločeni, vsako okolje dobi lastne vrednosti. Nevarno postane, ko datoteka pristane v napačnem imeniku. Če leži v webrootu in je spletni strežnik ne blokira, zadošča en sam klic v brskalniku, da se vsi dostopi preberejo naenkrat.
K temu pridejo različice z drugimi imeni: .env.local, .env.production, config.local.php ali datoteke z dostopnimi podatki do shramb. Kar je tu opisano za .env, velja za vse datoteke, v katerih so skrivnosti.
Takšne datoteke samodejni skenerji iščejo nenehno. To ni posebnost posameznih napadalcev, ampak osnovni šum na internetu, podobno kot množična skeniranja nepopravljenih različic PHP.
Kje naj leži datoteka .env
Najučinkovitejši ukrep je strukturen: spletni strežnik sme dostavljati samo mapo, ki naj bo res javna. Pri Laravelu in Symfonyju je to mapa public/. Vse drugo, torej koda, konfiguracija, dnevniki in .env, leži više in prek HTTP sploh ni naslovljivo.
/srv/www/shop/
├── .env ← nedosegljivo
├── config/
├── src/
├── vendor/
└── public/ ← edini webroot
├── index.php
└── assets/
V praksi webroot kljub temu pogosto kaže na sam imenik projekta, na primer ker to predpiše nadzorna plošča gostovanja ali ker pot ob selitvi ni bila prilagojena. Zato v konfiguraciji spletnega strežnika ali nadzorni plošči preverite, kam kažeta root oziroma DocumentRoot.
Zaščita datoteke .env: blokada v spletnem strežniku kot druga linija
Če webroota ni mogoče spremeniti ali želite dodatno zaščito, skrite datoteke blokirajte v spletnem strežniku. Mapa .well-known pri tem ostane dosegljiva, ker se med drugim uporablja za izdajo potrdil.
# Blokiraj vse datoteke in mape s piko na začetku, razen .well-known
location ~ /\.(?!well-known/) {
deny all;
return 404;
}
# Blokiraj datoteke s piko na začetku
<FilesMatch "^\.">
Require all denied
</FilesMatch>
Odgovor 404 namesto 403 ne izda, da datoteka obstaja. Ali blokada deluje, preverite od zunaj:
# Pričakovano: 403 ali 404, nikoli 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
Zadnji dve vrstici nista naključje: kopije, kot sta .env.bak ali .env.old, nastanejo pri vzdrževalnih delih in jih pogosto pozabijo. Več o takih ostankih je v prispevku Datoteke varnostnih kopij v webrootu.
Pravice, Git in ravnanje s kopijami
Tudi zunaj webroota velja načelo najmanjših pravic. Obnesla se je ta razdelitev:
- Lastnik je uporabnik za razmestitev (deploy), ne proces PHP.
- Skupina je skupina poola PHP-FPM, ki sme samo brati; pravice
640. - Brez pisalnega dostopa za proces PHP. Aplikacija ne potrebuje možnosti spreminjanja lastnih dostopnih podatkov.
- Brez pravih vrednosti v repozitoriju: vloži se samo
.env.examplez nadomestnimi znaki, prava datoteka je v.gitignore. - Ločene vrednosti po okoljih: razvoj, staging in produkcija uporabljajo različne dostope, da uhajanje v testnem okolju ne odpre produkcije.
chown deploy:shop-php /srv/www/shop/.env
chmod 640 /srv/www/shop/.env
# Preverite, ali je bila datoteka kdaj vložena
git log --all --oneline -- .env
Pazite tudi na strani z napakami. Ogrodja v načinu za odpravljanje napak deloma prikažejo spremenljivke okolja in konfiguracijske vrednosti; na produkcijskem sistemu mora biti ta način izklopljen. Preverite to po vsaki razmestitvi, ker ga lahko napačna vrednost v sami datoteki .env spet vklopi.
Če zadnji ukaz vrne zadetke, so dostopni podatki v zgodovini Git in veljajo za razkrite, tudi če datoteke danes ni več. Zakaj je to posebej občutljivo, kadar mapa .git leži na strežniku, opisuje Javna mapa .git: podcenjeno uhajanje podatkov. Osnove o pravicah pojasnjuje vodnik Pravice datotek na spletnem strežniku.
Testne datoteke s phpinfo() prikažejo spremenljivke okolja. Kdor skrivnosti posreduje kot spremenljivke okolja, jih izda prek pozabljene testne datoteke. Ozadje je v prispevku Datoteke phpinfo(): zakaj morajo izginiti.
Po vdoru: zamenjava dostopnih podatkov
Nobena blokada ne ščiti pred napadalcem, ki na strežniku že izvaja kodo. Proces PHP mora svojo konfiguracijo lahko prebrati, torej jo lahko prebere tudi vnesena koda v istem procesu. Po PHP2Shell zato velja: če vdora ni mogoče izključiti, je treba vse dostopne podatke na strežniku obravnavati kot znane.
Urejena zamenjava obsega gesla baze podatkov, dostope do pošte in SMTP, ključe API zunanjih storitev, podpisne ključe aplikacije in dostope do shramb. Vrstni red in čas naj bosta načrtovana: kdor najprej zamenja in šele nato očisti strežnik, napadalcu morda takoj izroči tudi nove vrednosti.
Škodo uhajanja omejite že prej, tako da vsaka skrivnost sme le toliko, kot je nujno. Uporabnik baze podatkov spletne strani ne potrebuje pravic za druge baze. Ključe API zunanjih storitev je pri mnogih ponudnikih mogoče omejiti na posamezne funkcije ali naslove pošiljatelja, na primer ustvarjanje pošiljk, ne pa sprožanje izplačil. In vsaka aplikacija dobi lastne dostope, namesto da več spletnih strani deli isti poštni račun ali isti ključ. Takrat uhajanje zadene jasno omejeno področje, zamenjava pa ostane obvladljiva.
V okoljih z vsebniki datoteka .env ne sodi niti v sliko niti v javno dosegljiv register. Izključite jo prek .dockerignore in skrivnosti posredujte šele med izvajanjem prek mehanizmov platforme.
Dolgoročno se splača pogledati osrednje shrambe skrivnosti, kot jih priporoča OWASP: skrivnosti na enem mestu, z dnevnikom dostopa, rednimi zamenjavami in čim krajšo veljavnostjo.
Kako konkretno pomaga PHP SOS?
- Od zunaj preverimo, ali so konfiguracijske datoteke, kopije in skrite datoteke vaših spletnih strani dosegljive.
- Webroot, blokade spletnega strežnika in pravice datotek prilagodimo tako, da skrivnosti prek HTTP niso več dosegljive.
- Repozitorije in razmestitve preverimo glede vloženih dostopnih podatkov.
- Po incidentu načrtujemo in spremljamo zamenjavo vseh prizadetih dostopov v pravem vrstnem redu.
Ta dela so del našega utrjevanja strežnikov PHP.
Pogosta vprašanja
Ali je datoteka .env v webrootu samodejno javna?
Ne samodejno, a pogosto. Ali je dosegljiva, je odvisno od konfiguracije spletnega strežnika. Mnoge privzete konfiguracije ščitijo samo datoteke .htaccess, ne pa drugih datotek s piko na začetku. Preizkus s curl prinese jasnost.
Ali so spremenljivke okolja varnejše od datoteke .env?
Ne načeloma. OWASP opozarja, da so spremenljivke okolja berljive za vse procese uporabnika in se lahko pojavijo v dnevnikih ali izpisih pomnilnika. Se pa izognejo datoteki v webrootu. Boljši so osrednji shrambi skrivnosti, kjer jih okolje podpira.
Kaj storiti, če je bila datoteka .env dosegljiva?
Vse v njej vsebovane dostopne podatke obravnavajte kot znane in jih zamenjajte: baza podatkov, pošta, API-ji, ponudniki plačil, ključi aplikacije. Nato v dnevnikih dostopa preverite, ali je bila datoteka klicana, in pri osebnih podatkih vključite pooblaščenca za varstvo podatkov.
Ali sodi datoteka .env v repozitorij Git?
Ne. V repozitorij sodi kvečjemu predloga brez pravih vrednosti, na primer .env.example. Prava datoteka se izključi prek .gitignore in na strežniku zagotovi ločeno.
Ali lahko phpinfo() izda dostopne podatke?
Da. phpinfo() med drugim prikaže spremenljivke okolja in strežnika. Če so tam skrivnosti, se izpišejo z njimi. Testne datoteke s phpinfo() zato nikoli ne sodijo na dosegljiv sistem.