Εν συντομία: Η PHP διαθέτει για τις συχνότερες εργασίες ασφαλείας έτοιμες, δοκιμασμένες συναρτήσεις: password_hash() για κωδικούς πρόσβασης, random_bytes() και random_int() για tokens, htmlspecialchars() κατά του cross-site scripting, προετοιμασμένα ερωτήματα με PDO κατά του SQL injection, hash_equals() για ασφαλείς συγκρίσεις και την επέκταση Sodium για κρυπτογραφία. Όποιος χρησιμοποιεί αυτά τα δομικά στοιχεία με συνέπεια αποφεύγει τα περισσότερα κενά των εφαρμογών. Απέναντι σε σφάλματα στον ίδιο τον διερμηνέα της PHP, όπως στο PHP2Shell, δεν βοηθούν· εκεί βοηθά μόνο η ενημέρωση.
Γιατί ενσωματωμένες λειτουργίες ασφαλείας της PHP;
Το να γράφετε μόνοι σας κώδικα ασφαλείας είναι επιρρεπές σε σφάλματα. Ένα δικό σας hash κωδικού, μια γεννήτρια tokens φτιαγμένη μόνοι σας ή ένα φίλτρο για εξόδους HTML που φτιάξατε μόνοι σας φαίνονται συχνά σωστά και παρ' όλα αυτά δεν είναι. Οι ενσωματωμένες συναρτήσεις είναι τεκμηριωμένες, δοκιμασμένες και συντηρούνται με τις ενημερώσεις της PHP.
Για όσους αποφασίζουν αυτό σημαίνει: μην ρωτάτε το πρακτορείο ή την ομάδα ανάπτυξης αν οι λειτουργίες ασφαλείας φτιάχτηκαν μόνες τους, αλλά αν χρησιμοποιούνται οι τυπικές συναρτήσεις της γλώσσας. Ο πίνακας δίνει μια επισκόπηση.
| Εργασία | Συνάρτηση | Διαθέσιμη από | Σημαντική υπόδειξη |
|---|---|---|---|
| Αποθήκευση κωδικών πρόσβασης | password_hash(), password_verify() |
PHP 5.5 | Στήλη έως 255 χαρακτήρες· το bcrypt περικόπτει στα 72 byte |
| Τυχαία tokens | random_bytes(), random_int() |
PHP 7.0 | ποτέ rand() ή mt_rand() για μυστικά |
| Τυχαιότητα αντικειμενοστρεφώς | Random\Randomizer |
PHP 8.2 | ίδια ασφάλεια, πιο ευέλικτη διεπαφή |
| Μασκάρισμα εξόδου HTML | htmlspecialchars() |
από πάντα | Οι προεπιλεγμένες σημαίες από την 8.1 μασκάρουν και τα απλά εισαγωγικά |
| Σύγκριση σταθερού χρόνου | hash_equals() |
PHP 5.6 | είσοδος χρήστη ως δεύτερο όρισμα |
| Σύγχρονη κρυπτογραφία | Sodium (sodium_*) |
PHP 7.2 | αντί για δική σας κρυπτογράφηση |
| Μυστικά σε stack traces | #[\SensitiveParameter] |
PHP 8.2 | η τιμή δεν εμφανίζεται στο trace |
| Έλεγχος εισόδων | filter_var() |
PHP 5.2 | ελέγχει τη μορφή, δεν αντικαθιστά το μασκάρισμα |
Κωδικοί πρόσβασης και tokens
Η password_hash() δημιουργεί ένα hash με salt, η password_verify() το ελέγχει. Με το PASSWORD_DEFAULT η PHP χρησιμοποιεί προς το παρόν bcrypt· από την PHP 8.4 ο προεπιλεγμένος συντελεστής κόστους είναι σύμφωνα με το εγχειρίδιο 12 αντί για 10. Επειδή ο προεπιλεγμένος αλγόριθμος μπορεί να αλλάξει, το εγχειρίδιο συνιστά μια στήλη βάσης δεδομένων με 255 χαρακτήρες. Στο bcrypt οι κωδικοί περικόπτονται μετά από 72 byte, κάτι που πρέπει να λαμβάνεται υπόψη σε πολύ μακριές φράσεις πρόσβασης.
<?php
// Εγγραφή
$hash = password_hash($passwort, PASSWORD_DEFAULT);
// Σύνδεση, συμπεριλαμβανομένης της αυτόματης αναβάθμισης παλιών hashes
if (password_verify($eingabe, $hash)) {
if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
$hash = password_hash($eingabe, PASSWORD_DEFAULT); // νέα αποθήκευση
}
}
// Token για σύνδεσμο επαναφοράς κωδικού
$token = bin2hex(random_bytes(32));
Για συγκρίσεις μυστικών, για παράδειγμα μιας υπογραφής, πρέπει να χρησιμοποιείται η hash_equals(). Μια κανονική σύγκριση με === μπορεί σύμφωνα με το εγχειρίδιο να αποκαλύψει μέσω του χρόνου εκτέλεσης από ποιο σημείο διαφέρουν δύο τιμές. Αναλυτικότερα: Ασφαλής αποθήκευση κωδικών πρόσβασης στην PHP και ασφαλείς τυχαίοι αριθμοί και tokens.
Μασκάρισμα εξόδων και ασφαλή ερωτήματα στη βάση δεδομένων
Το cross-site scripting προκύπτει όταν εισόδοι χρηστών καταλήγουν αφιλτράριστες σε HTML. Η htmlspecialchars() μετατρέπει ειδικούς χαρακτήρες σε οντότητες HTML. Από την PHP 8.1 οι προεπιλεγμένες σημαίες είναι ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401· προηγουμένως τα απλά εισαγωγικά δεν μετατρέπονταν. Όποιος πρέπει να υποστηρίζει παλαιότερες εκδόσεις, δηλώνει τις σημαίες ρητά.
Το SQL injection αποτρέπεται από προετοιμασμένα ερωτήματα. Οι τιμές μεταβιβάζονται χωριστά από το κείμενο SQL και δεν μπορούν να αλλάξουν το ερώτημα:
<?php
$stmt = $pdo->prepare('SELECT id, name FROM kunden WHERE email = :email');
$stmt->execute(['email' => $email]);
$kunde = $stmt->fetch();
echo htmlspecialchars($kunde['name'] ?? '', ENT_QUOTES, 'UTF-8');
Οι λεπτομέρειες υπάρχουν στη σελίδα Αποτροπή του cross-site scripting στην PHP και στη σελίδα για το SQL injection.
Ο έλεγχος των εισόδων είναι ένα δεύτερο, ξεχωριστό βήμα. Η filter_var() διαπιστώνει αν μια τιμή έχει έγκυρη μορφή, για παράδειγμα μια διεύθυνση email ή έναν ακέραιο σε επιτρεπτό εύρος. Αυτό δεν αντικαθιστά όμως το μασκάρισμα στην έξοδο ούτε ένα προετοιμασμένο ερώτημα, επειδή και τυπικά έγκυρες τιμές μπορεί να περιέχουν ειδικούς χαρακτήρες.
Κρατώντας τα μυστικά μακριά από τα μηνύματα σφάλματος
Μια υποτιμημένη διαρροή δεδομένων είναι τα stack traces. Όταν προκύψει σφάλμα σε μια συνάρτηση, η PHP καταγράφει την αλυσίδα κλήσεων μαζί με τα ορίσματα. Αν εκεί υπάρχει κωδικός ή κλειδί API, καταλήγει στο log. Από την PHP 8.2 το χαρακτηριστικό #[\SensitiveParameter] σημαίνει τέτοιες παραμέτρους· η τιμή τους εμφανίζεται τότε στο trace μόνο ως αντικείμενο SensitiveParameterValue.
<?php
function anmelden(string $benutzer, #[\SensitiveParameter] string $passwort): bool
{
// ... έλεγχος ...
throw new RuntimeException('Datenbank nicht erreichbar');
}
Σύμφωνα με υπόδειξη του εγχειριδίου, το χαρακτηριστικό ισχύει μόνο στη συγκεκριμένη υλοποίηση, όχι στη μέθοδο μιας διεπαφής. Ορίστε το γι' αυτό εκεί όπου ο κώδικας πράγματι εκτελείται.
Sessions: ασφαλείς ρυθμίσεις και νέες προεπιλογές
Οι συνεδρίες είναι συχνός στόχος επιθέσεων. Τρεις ρυθμίσεις είναι κεντρικές: το session.use_strict_mode=1 απορρίπτει αναγνωριστικά session που δεν δημιούργησε ο ίδιος ο διακομιστής· το session.cookie_httponly=1 εμποδίζει την πρόσβαση στο cookie του session μέσω JavaScript· το session.cookie_samesite=Lax δυσχεραίνει την αποστολή του από ξένες σελίδες. Σύμφωνα με το εγκεκριμένο RFC, ακριβώς αυτές οι τρεις τιμές γίνονται με την PHP 8.6 προεπιλογή. Ορίστε τις μέχρι τότε μόνοι σας, και ρητά και μετά, ώστε η διαμόρφωση να μην εξαρτάται από την προεπιλογή.
session.use_strict_mode = 1
session.cookie_httponly = 1
session.cookie_samesite = Lax
session.cookie_secure = 1
Περισσότερα στη σελίδα Ασφάλεια των sessions στην PHP.
Τι δεν προσφέρουν οι ενσωματωμένες λειτουργίες
Το έργο PHP είναι σαφές στην πολιτική ασφαλείας του: η PHP δεν είναι sandbox. Παρακάμψεις των open_basedir ή disable_functions, κακόβουλες είσοδοι στην unserialize() και ανέλεγκτα ορίσματα σε συναρτήσεις όπως η mysqli_query() δεν θεωρούνται ευπάθειες ασφαλείας της PHP. Αυτό σημαίνει για τους διαχειριστές: αυτές οι ρυθμίσεις είναι χρήσιμη θωράκιση, αλλά όχι όριο ασφαλείας, και η unserialize() δεν έχει καμία σχέση με ξένα δεδομένα.
Το δεύτερο σημείο αφορά το PHP2Shell. Οι CVE-2026-109618 και CVE-2026-109619 επιτρέπουν σύμφωνα με το php.net εκτέλεση κώδικα πριν ή ενώ εκτελείται η εφαρμογή σας· στο mod_php έχει επιδειχθεί exploit πριν καν εκτελεστεί κώδικας εφαρμογής. Καμία συνάρτηση στον κώδικά σας δεν μπορεί να το αναχαιτίσει. Ο ασφαλής προγραμματισμός και η τρέχουσα έκδοση PHP είναι δύο ξεχωριστές υποχρεώσεις και πρέπει να εκπληρώνονται και οι δύο.
Πώς βοηθά συγκεκριμένα η PHP SOS;
Στον έλεγχο ασφαλείας για εφαρμογές PHP ελέγχουμε στοχευμένα:
- Χειρισμός κωδικών και tokens: Χρησιμοποιούνται οι
password_hash()καιrandom_bytes()ή υπάρχουν δικές σας κατασκευές; - Έξοδοι και ερωτήματα: Πού καταλήγουν αφιλτράριστες είσοδοι σε HTML, SQL ή εντολές shell;
- Διαμόρφωση sessions: Είναι ορισμένα τα Strict Mode, HttpOnly, SameSite και Secure και δεν παρακάμπτονται;
- Χρόνος εκτέλεσης: Εκτελείται υποστηριζόμενη έκδοση PHP με τις διορθώσεις της 21.10.2026;
Συχνές ερωτήσεις
Πώς αποθηκεύονται σωστά οι κωδικοί πρόσβασης στην PHP;
Με την password_hash() και το PASSWORD_DEFAULT, ο έλεγχος γίνεται με την password_verify(). Η στήλη της βάσης δεδομένων πρέπει σύμφωνα με το εγχειρίδιο να χωρά έως 255 χαρακτήρες, επειδή ο προεπιλεγμένος αλγόριθμος μπορεί να αλλάξει στο μέλλον.
Είναι η rand() κατάλληλη για tokens;
Όχι. Για tokens, κλειδιά και συνδέσμους κωδικών πρέπει να χρησιμοποιούνται οι random_bytes() ή random_int(). Παρέχουν σύμφωνα με το εγχειρίδιο κρυπτογραφικά ασφαλείς τυχαίες τιμές.
Από πότε περιλαμβάνεται το Sodium στην PHP;
Η επέκταση Sodium για σύγχρονη κρυπτογραφία αποτελεί μέρος της PHP από την PHP 7.2.0. Οι παλαιότερες εκδόσεις μπορούσαν να την προσθέσουν μόνο μέσω PECL.
Προστατεύουν αυτές οι λειτουργίες από το PHP2Shell;
Όχι. Προστατεύουν από σφάλματα στην εφαρμογή σας. Το PHP2Shell βρίσκεται στον ίδιο τον διερμηνέα και κλείνει μόνο με ενημέρωση της PHP, ακολουθούμενη από επανεκκίνηση όλων των διεργασιών PHP.
Αλλάζουν οι προεπιλογές των sessions στην PHP 8.6;
Ναι, σύμφωνα με το εγκεκριμένο RFC τα session.use_strict_mode και session.cookie_httponly ενεργοποιούνται από προεπιλογή και το session.cookie_samesite ορίζεται σε Lax. Τις υπάρχουσες διαμορφώσεις πρέπει παρ' όλα αυτά να τις ορίζετε εσείς ρητά.