Kurz gesagt: Eine .env-Datei schützen Sie, indem sie gar nicht erst im öffentlich erreichbaren Verzeichnis liegt: Der Webroot zeigt auf einen Unterordner wie public/, die Konfiguration liegt eine Ebene darüber. Zusätzlich sperrt der Webserver alle Dateien mit Punkt am Anfang, die Datei ist nur für Eigentümer und PHP-Prozess lesbar und gehört nie ins Git-Repository. Nach einem Einbruch gelten alle Zugangsdaten darin als bekannt und werden ausgetauscht.
Die Datei mit den Schlüsseln zum Haus
Moderne PHP-Projekte legen ihre Geheimnisse gern in einer Datei namens .env ab: Datenbankpasswort, Zugang zum Mailserver, API-Schlüssel für Zahlungs- und Versanddienste, der Schlüssel, mit dem die Anwendung Cookies signiert. Frameworks wie Laravel und Symfony nutzen dieses Muster, viele Eigenentwicklungen haben es übernommen.
Die Idee ist gut: Konfiguration und Code sind getrennt, und jede Umgebung bekommt eigene Werte. Gefährlich wird es, wenn die Datei im falschen Verzeichnis landet. Liegt sie im Webroot und sperrt der Webserver sie nicht, genügt ein einziger Aufruf im Browser, um alle Zugänge auf einmal zu lesen.
Dazu kommen Varianten mit anderen Namen: .env.local, .env.production, config.local.php oder Dateien mit Zugangsdaten zu Speicherdiensten. Was hier für .env beschrieben ist, gilt für alle Dateien, in denen Geheimnisse stehen.
Solche Dateien werden laufend von automatisierten Scannern gesucht. Das ist keine Spezialität einzelner Angreifer, sondern Grundrauschen im Internet, ähnlich wie die Massenscans nach ungepatchten PHP-Versionen.
Wo die .env-Datei liegen sollte
Die wirksamste Maßnahme ist strukturell: Der Webserver darf nur den Ordner ausliefern, der wirklich öffentlich sein soll. In Laravel und Symfony ist das der Ordner public/. Alles andere, also Code, Konfiguration, Logs und .env, liegt darüber und ist über HTTP gar nicht adressierbar.
/srv/www/shop/
├── .env ← nicht erreichbar
├── config/
├── src/
├── vendor/
└── public/ ← einziger Webroot
├── index.php
└── assets/
In der Praxis zeigt der Webroot trotzdem oft auf das Projektverzeichnis selbst, etwa weil ein Hosting-Panel das so vorgibt oder weil beim Umzug ein Pfad nicht angepasst wurde. Prüfen Sie deshalb in der Webserver-Konfiguration oder im Panel, wohin root beziehungsweise DocumentRoot zeigt.
.env-Datei schützen: Sperre im Webserver als zweite Linie
Lässt sich der Webroot nicht ändern, oder wollen Sie eine zusätzliche Absicherung, sperren Sie versteckte Dateien im Webserver. Der Ordner .well-known muss dabei erreichbar bleiben, weil er unter anderem für die Ausstellung von Zertifikaten genutzt wird.
# Alle Dateien und Ordner mit Punkt am Anfang sperren, außer .well-known
location ~ /\.(?!well-known/) {
deny all;
return 404;
}
# Dateien mit Punkt am Anfang sperren
<FilesMatch "^\.">
Require all denied
</FilesMatch>
Eine Antwort mit 404 statt 403 verrät nicht, dass die Datei existiert. Ob die Sperre wirkt, prüfen Sie von außen:
# Erwartet: 403 oder 404, niemals 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
Die letzten beiden Zeilen sind kein Zufall: Kopien wie .env.bak oder .env.old entstehen bei Wartungsarbeiten und werden oft vergessen. Mehr zu solchen Überbleibseln steht in Backup-Dateien im Webroot.
Rechte, Git und der Umgang mit Kopien
Auch außerhalb des Webroots gilt das Prinzip der geringsten Rechte. Eine bewährte Aufteilung:
- Eigentümer ist der Deploy-Benutzer, nicht der PHP-Prozess.
- Gruppe ist die Gruppe des PHP-FPM-Pools, die nur lesen darf; Rechte
640. - Kein Schreibzugriff für den PHP-Prozess. Eine Anwendung muss ihre eigenen Zugangsdaten nicht ändern können.
- Keine echten Werte im Repository: Nur
.env.examplemit Platzhaltern wird eingecheckt, die echte Datei steht in.gitignore. - Getrennte Werte je Umgebung: Entwicklung, Staging und Produktion nutzen unterschiedliche Zugänge, damit ein Leck in einer Testumgebung nicht die Produktion öffnet.
chown deploy:shop-php /srv/www/shop/.env
chmod 640 /srv/www/shop/.env
# Prüfen, ob die Datei jemals eingecheckt wurde
git log --all --oneline -- .env
Achten Sie auch auf Fehlerseiten. Frameworks zeigen im Debug-Modus teils Umgebungsvariablen und Konfigurationswerte an; auf einem Produktivsystem muss dieser Modus abgeschaltet sein. Prüfen Sie das nach jedem Deployment, denn ein falscher Wert in der .env selbst kann ihn wieder einschalten.
Liefert der letzte Befehl Treffer, stehen die Zugangsdaten in der Git-Historie und gelten als offengelegt, auch wenn die Datei heute fehlt. Warum das besonders heikel ist, wenn der .git-Ordner auf dem Server liegt, beschreibt Öffentlicher .git-Ordner: Ein unterschätztes Datenleck. Grundsätzliches zu Rechten erklärt der Ratgeber Dateirechte auf dem Webserver.
Testdateien mit phpinfo() zeigen Umgebungsvariablen an. Wer Geheimnisse als Umgebungsvariablen übergibt, verrät sie über eine vergessene Testdatei. Hintergründe stehen in phpinfo()-Dateien: Warum sie verschwinden müssen.
Nach einem Einbruch: Zugangsdaten austauschen
Keine Sperre schützt vor einem Angreifer, der bereits Code auf dem Server ausführt. Ein PHP-Prozess muss seine Konfiguration lesen können, also kann eingeschleuster Code im selben Prozess das auch. Nach PHP2Shell gilt deshalb: Kann ein Einbruch nicht ausgeschlossen werden, sind alle Zugangsdaten auf dem Server als bekannt zu behandeln.
Ein geordneter Austausch umfasst Datenbankpasswörter, Mail- und SMTP-Zugänge, API-Schlüssel externer Dienste, Signaturschlüssel der Anwendung und Zugänge zu Speicherdiensten. Reihenfolge und Zeitpunkt sollten geplant sein: Wer zuerst austauscht und dann den Server bereinigt, gibt dem Angreifer die neuen Werte womöglich gleich mit.
Den Schaden eines Lecks begrenzen Sie schon vorher, indem jedes Geheimnis nur so viel darf wie nötig. Der Datenbankbenutzer der Website braucht keine Rechte auf andere Datenbanken. API-Schlüssel externer Dienste lassen sich bei vielen Anbietern auf einzelne Funktionen oder Absenderadressen beschränken, etwa Sendungen anlegen, aber keine Auszahlungen veranlassen. Und jede Anwendung erhält eigene Zugänge, statt dass mehrere Websites dasselbe Mailkonto oder denselben Schlüssel teilen. Dann betrifft ein Leck einen klar abgegrenzten Bereich, und der Austausch bleibt überschaubar.
In Container-Umgebungen gehört die .env-Datei weder ins Image noch in eine öffentlich erreichbare Registry. Schließen Sie sie per .dockerignore aus und übergeben Sie Geheimnisse erst zur Laufzeit über die Mechanismen der Plattform.
Langfristig lohnt der Blick auf zentrale Secret-Speicher, wie OWASP sie empfiehlt: Geheimnisse an einem Ort, mit Zugriffsprotokoll, regelmäßigem Austausch und möglichst kurzer Gültigkeit.
Wie hilft PHP SOS konkret?
- Wir prüfen von außen, ob Konfigurationsdateien, Kopien und versteckte Dateien Ihrer Websites abrufbar sind.
- Wir stellen Webroot, Webserver-Sperren und Dateirechte so um, dass Geheimnisse nicht mehr über HTTP erreichbar sind.
- Wir prüfen Repositories und Deployments auf eingecheckte Zugangsdaten.
- Nach einem Vorfall planen und begleiten wir den Austausch aller betroffenen Zugänge in der richtigen Reihenfolge.
Diese Arbeiten sind Teil unserer Server-Härtung für PHP-Webserver.
Häufige Fragen
Ist eine .env-Datei im Webroot automatisch öffentlich?
Nicht automatisch, aber häufig. Ob sie abrufbar ist, hängt von der Webserver-Konfiguration ab. Viele Standardkonfigurationen schützen nur .htaccess-Dateien, nicht andere Dateien mit Punkt am Anfang. Ein Test mit curl schafft Klarheit.
Sind Umgebungsvariablen sicherer als eine .env-Datei?
Nicht grundsätzlich. OWASP weist darauf hin, dass Umgebungsvariablen für alle Prozesse des Benutzers lesbar sind und in Logs oder Speicherabbildern auftauchen können. Sie vermeiden aber eine Datei im Webroot. Besser sind zentrale Secret-Speicher, wo die Umgebung sie unterstützt.
Was tun, wenn die .env-Datei abrufbar war?
Alle darin enthaltenen Zugangsdaten als bekannt betrachten und austauschen: Datenbank, Mail, APIs, Zahlungsdienste, Schlüssel der Anwendung. Danach in den Zugriffsprotokollen prüfen, ob die Datei abgerufen wurde, und bei personenbezogenen Daten den Datenschutzbeauftragten einbeziehen.
Gehört die .env-Datei ins Git-Repository?
Nein. Ins Repository gehört höchstens eine Vorlage ohne echte Werte, etwa .env.example. Die echte Datei wird über .gitignore ausgeschlossen und auf dem Server getrennt bereitgestellt.
Kann phpinfo() Zugangsdaten verraten?
Ja. phpinfo() zeigt unter anderem Umgebungsvariablen und Servervariablen an. Liegen Geheimnisse dort, werden sie mit ausgegeben. Testdateien mit phpinfo() gehören deshalb nie auf ein erreichbares System.