Εν ολίγοις: Ένα αρχείο .env το προστατεύετε αν δεν βρίσκεται καν στον δημόσια προσβάσιμο φάκελο: το webroot δείχνει σε έναν υποφάκελο όπως το public/, η διαμόρφωση βρίσκεται ένα επίπεδο πιο πάνω. Επιπλέον ο διακομιστής ιστού αποκλείει όλα τα αρχεία που αρχίζουν με τελεία, το αρχείο είναι αναγνώσιμο μόνο από τον κάτοχο και τη διεργασία PHP και δεν ανήκει ποτέ στο αποθετήριο Git. Μετά από μια εισβολή, όλα τα στοιχεία πρόσβασης που περιέχει θεωρούνται γνωστά και αντικαθίστανται.
Το αρχείο με τα κλειδιά του σπιτιού
Τα σύγχρονα έργα PHP αποθηκεύουν τα μυστικά τους με προτίμηση σε ένα αρχείο με όνομα .env: κωδικός βάσης δεδομένων, πρόσβαση στον διακομιστή αλληλογραφίας, κλειδιά API για υπηρεσίες πληρωμών και αποστολών, το κλειδί με το οποίο η εφαρμογή υπογράφει cookies. Frameworks όπως το Laravel και το Symfony χρησιμοποιούν αυτό το πρότυπο, και πολλές εσωτερικές υλοποιήσεις το έχουν υιοθετήσει.
Η ιδέα είναι καλή: η διαμόρφωση και ο κώδικας είναι διαχωρισμένα και κάθε περιβάλλον παίρνει δικές του τιμές. Επικίνδυνο γίνεται όταν το αρχείο καταλήξει στον λάθος φάκελο. Αν βρίσκεται στο webroot και ο διακομιστής ιστού δεν το αποκλείει, αρκεί μία μόνο κλήση στον browser για να διαβαστούν όλες οι προσβάσεις μονομιάς.
Προστίθενται παραλλαγές με άλλα ονόματα: .env.local, .env.production, config.local.php ή αρχεία με στοιχεία πρόσβασης σε υπηρεσίες αποθήκευσης. Όσα περιγράφονται εδώ για το .env ισχύουν για όλα τα αρχεία όπου αποθηκεύονται μυστικά.
Τέτοια αρχεία αναζητούνται διαρκώς από αυτοματοποιημένους σαρωτές. Αυτό δεν είναι ιδιαιτερότητα μεμονωμένων επιτιθέμενων, αλλά θόρυβος βάσης του διαδικτύου, παρόμοιος με τις μαζικές σαρώσεις για εκδόσεις PHP χωρίς patch.
Πού πρέπει να βρίσκεται το αρχείο .env
Το πιο αποτελεσματικό μέτρο είναι δομικό: ο διακομιστής ιστού επιτρέπεται να παραδίδει μόνο τον φάκελο που πρέπει πραγματικά να είναι δημόσιος. Στο Laravel και στο Symfony αυτός είναι ο φάκελος public/. Όλα τα υπόλοιπα, δηλαδή κώδικας, διαμόρφωση, αρχεία καταγραφής και .env, βρίσκονται πιο πάνω και δεν είναι καθόλου διευθυνσιοδοτήσιμα μέσω HTTP.
/srv/www/shop/
├── .env ← μη προσβάσιμο
├── config/
├── src/
├── vendor/
└── public/ ← το μοναδικό webroot
├── index.php
└── assets/
Στην πράξη το webroot δείχνει παρ' όλα αυτά συχνά στον ίδιο τον φάκελο του έργου, για παράδειγμα επειδή ένα πάνελ φιλοξενίας το επιβάλλει ή επειδή σε μια μετεγκατάσταση δεν προσαρμόστηκε μια διαδρομή. Ελέγξτε γι' αυτό στη διαμόρφωση του διακομιστή ιστού ή στο πάνελ πού δείχνει το root ή το DocumentRoot.
Προστασία του αρχείου .env: ο αποκλεισμός στον διακομιστή ιστού ως δεύτερη γραμμή
Αν το webroot δεν μπορεί να αλλάξει, ή θέλετε πρόσθετη ασφάλεια, αποκλείστε τα κρυφά αρχεία στον διακομιστή ιστού. Ο φάκελος .well-known πρέπει να παραμείνει προσβάσιμος, επειδή χρησιμοποιείται μεταξύ άλλων για την έκδοση πιστοποιητικών.
# Αποκλεισμός όλων των αρχείων και φακέλων που αρχίζουν με τελεία, εκτός του .well-known
location ~ /\.(?!well-known/) {
deny all;
return 404;
}
# Αποκλεισμός αρχείων που αρχίζουν με τελεία
<FilesMatch "^\.">
Require all denied
</FilesMatch>
Μια απάντηση 404 αντί για 403 δεν αποκαλύπτει ότι το αρχείο υπάρχει. Το αν λειτουργεί ο αποκλεισμός, το ελέγχετε από έξω:
# Αναμενόμενο: 403 ή 404, ποτέ 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
Οι δύο τελευταίες γραμμές δεν είναι τυχαίες: αντίγραφα όπως το .env.bak ή το .env.old δημιουργούνται σε εργασίες συντήρησης και ξεχνιούνται συχνά. Περισσότερα για τέτοια κατάλοιπα υπάρχουν στο Αρχεία αντιγράφων ασφαλείας στο webroot.
Δικαιώματα, Git και ο χειρισμός αντιγράφων
Και εκτός του webroot ισχύει η αρχή των ελάχιστων δικαιωμάτων. Μια δοκιμασμένη κατανομή:
- Κάτοχος είναι ο χρήστης deploy και όχι η διεργασία PHP.
- Ομάδα είναι η ομάδα του pool PHP-FPM, που επιτρέπεται μόνο να διαβάζει· δικαιώματα
640. - Καμία πρόσβαση εγγραφής για τη διεργασία PHP. Μια εφαρμογή δεν χρειάζεται να μπορεί να αλλάζει τα δικά της στοιχεία πρόσβασης.
- Καμία πραγματική τιμή στο αποθετήριο: Γίνεται check-in μόνο το
.env.exampleμε δείγματα, το πραγματικό αρχείο βρίσκεται στο.gitignore. - Χωριστές τιμές ανά περιβάλλον: Η ανάπτυξη, το staging και η παραγωγή χρησιμοποιούν διαφορετικές προσβάσεις, ώστε μια διαρροή σε περιβάλλον δοκιμών να μην ανοίγει την παραγωγή.
chown deploy:shop-php /srv/www/shop/.env
chmod 640 /srv/www/shop/.env
# Έλεγχος αν το αρχείο έχει ποτέ γίνει check-in
git log --all --oneline -- .env
Προσέξτε και τις σελίδες σφάλματος. Τα frameworks εμφανίζουν στη λειτουργία debug εν μέρει μεταβλητές περιβάλλοντος και τιμές διαμόρφωσης· σε παραγωγικό σύστημα αυτή η λειτουργία πρέπει να είναι απενεργοποιημένη. Ελέγξτε το μετά από κάθε deployment, γιατί μια λανθασμένη τιμή στο ίδιο το .env μπορεί να την ενεργοποιήσει ξανά.
Αν η τελευταία εντολή επιστρέψει αποτελέσματα, τα στοιχεία πρόσβασης βρίσκονται στο ιστορικό του Git και θεωρούνται εκτεθειμένα, ακόμη κι αν το αρχείο λείπει σήμερα. Γιατί αυτό είναι ιδιαίτερα λεπτό όταν ο φάκελος .git βρίσκεται στον διακομιστή, περιγράφει το Δημόσιος φάκελος .git: μια υποτιμημένη διαρροή δεδομένων. Τα βασικά για τα δικαιώματα εξηγεί ο οδηγός Δικαιώματα αρχείων στον διακομιστή ιστού.
Τα αρχεία δοκιμής με phpinfo() εμφανίζουν μεταβλητές περιβάλλοντος. Όποιος μεταβιβάζει μυστικά ως μεταβλητές περιβάλλοντος, τα αποκαλύπτει μέσω ενός ξεχασμένου αρχείου δοκιμής. Το υπόβαθρο υπάρχει στο Αρχεία phpinfo(): γιατί πρέπει να εξαφανιστούν.
Μετά από εισβολή: αντικατάσταση των στοιχείων πρόσβασης
Κανένας αποκλεισμός δεν προστατεύει από έναν επιτιθέμενο που εκτελεί ήδη κώδικα στον διακομιστή. Μια διεργασία PHP πρέπει να μπορεί να διαβάζει τη διαμόρφωσή της, άρα μπορεί και ο κώδικας που εισάγεται στην ίδια διεργασία. Μετά το PHP2Shell ισχύει γι' αυτό: αν δεν μπορεί να αποκλειστεί μια εισβολή, όλα τα στοιχεία πρόσβασης στον διακομιστή πρέπει να αντιμετωπίζονται ως γνωστά.
Μια οργανωμένη αντικατάσταση περιλαμβάνει κωδικούς βάσης δεδομένων, προσβάσεις email και SMTP, κλειδιά API εξωτερικών υπηρεσιών, κλειδιά υπογραφής της εφαρμογής και προσβάσεις σε υπηρεσίες αποθήκευσης. Η σειρά και ο χρόνος πρέπει να σχεδιάζονται: όποιος αντικαταστήσει πρώτα και καθαρίσει έπειτα τον διακομιστή, ενδέχεται να δώσει στον επιτιθέμενο αμέσως και τις νέες τιμές.
Τη ζημιά μιας διαρροής την περιορίζετε ήδη νωρίτερα, αν κάθε μυστικό επιτρέπεται να κάνει μόνο όσα χρειάζεται. Ο χρήστης βάσης δεδομένων του ιστοτόπου δεν χρειάζεται δικαιώματα σε άλλες βάσεις. Τα κλειδιά API εξωτερικών υπηρεσιών μπορούν σε πολλούς παρόχους να περιοριστούν σε μεμονωμένες λειτουργίες ή διευθύνσεις αποστολέα, για παράδειγμα δημιουργία αποστολών αλλά όχι εντολή πληρωμών. Και κάθε εφαρμογή παίρνει δικές της προσβάσεις, αντί να μοιράζονται πολλοί ιστότοποι τον ίδιο λογαριασμό email ή το ίδιο κλειδί. Τότε μια διαρροή αφορά μια σαφώς οριοθετημένη περιοχή και η αντικατάσταση παραμένει διαχειρίσιμη.
Σε περιβάλλοντα container το αρχείο .env δεν ανήκει ούτε στην εικόνα ούτε σε ένα δημόσια προσβάσιμο registry. Αποκλείστε το μέσω .dockerignore και μεταβιβάστε τα μυστικά μόνο κατά την εκτέλεση, μέσω των μηχανισμών της πλατφόρμας.
Μακροπρόθεσμα αξίζει μια ματιά στους κεντρικούς χώρους αποθήκευσης μυστικών, όπως τους συνιστά το OWASP: μυστικά σε ένα σημείο, με καταγραφή πρόσβασης, τακτική αντικατάσταση και όσο το δυνατόν πιο σύντομη διάρκεια ισχύος.
Πώς βοηθά συγκεκριμένα η PHP SOS;
- Ελέγχουμε από έξω αν αρχεία διαμόρφωσης, αντίγραφα και κρυφά αρχεία των ιστοτόπων σας είναι προσβάσιμα.
- Αλλάζουμε το webroot, τους αποκλεισμούς του διακομιστή ιστού και τα δικαιώματα αρχείων έτσι ώστε τα μυστικά να μην είναι πλέον προσβάσιμα μέσω HTTP.
- Ελέγχουμε αποθετήρια και deployments για στοιχεία πρόσβασης που έχουν γίνει check-in.
- Μετά από ένα περιστατικό σχεδιάζουμε και συνοδεύουμε την αντικατάσταση όλων των επηρεασμένων προσβάσεων με τη σωστή σειρά.
Αυτές οι εργασίες είναι μέρος της σκλήρυνσης διακομιστή για διακομιστές ιστού PHP.
Συχνές ερωτήσεις
Είναι ένα αρχείο .env στο webroot αυτόματα δημόσιο;
Όχι αυτόματα, αλλά συχνά. Το αν μπορεί να ανακτηθεί εξαρτάται από τη διαμόρφωση του διακομιστή ιστού. Πολλές προεπιλεγμένες διαμορφώσεις προστατεύουν μόνο τα αρχεία .htaccess και όχι άλλα αρχεία που αρχίζουν με τελεία. Μια δοκιμή με curl δίνει σαφή απάντηση.
Είναι οι μεταβλητές περιβάλλοντος ασφαλέστερες από ένα αρχείο .env;
Όχι κατ' ανάγκη. Το OWASP επισημαίνει ότι οι μεταβλητές περιβάλλοντος είναι αναγνώσιμες από όλες τις διεργασίες του χρήστη και μπορεί να εμφανιστούν σε αρχεία καταγραφής ή σε εικόνες μνήμης. Αποφεύγουν όμως ένα αρχείο στο webroot. Καλύτεροι είναι οι κεντρικοί χώροι αποθήκευσης μυστικών, όπου το περιβάλλον τους υποστηρίζει.
Τι κάνω αν το αρχείο .env ήταν προσβάσιμο;
Θεωρήστε όλα τα στοιχεία πρόσβασης που περιέχει ως γνωστά και αντικαταστήστε τα: βάση δεδομένων, email, API, υπηρεσίες πληρωμών, κλειδιά της εφαρμογής. Έπειτα ελέγξτε στα αρχεία καταγραφής πρόσβασης αν το αρχείο ανακτήθηκε και, αν υπάρχουν προσωπικά δεδομένα, συμπεριλάβετε τον υπεύθυνο προστασίας δεδομένων.
Ανήκει το αρχείο .env στο αποθετήριο Git;
Όχι. Στο αποθετήριο ανήκει το πολύ ένα πρότυπο χωρίς πραγματικές τιμές, για παράδειγμα το .env.example. Το πραγματικό αρχείο αποκλείεται μέσω του .gitignore και παρέχεται ξεχωριστά στον διακομιστή.
Μπορεί το phpinfo() να αποκαλύψει στοιχεία πρόσβασης;
Ναι. Το phpinfo() εμφανίζει, μεταξύ άλλων, μεταβλητές περιβάλλοντος και μεταβλητές διακομιστή. Αν υπάρχουν εκεί μυστικά, εμφανίζονται κι αυτά. Αρχεία δοκιμής με phpinfo() δεν ανήκουν ποτέ σε προσβάσιμο σύστημα.