Bones pràctiques
En la següent secció fem un recull d'algunes mesures que cal tenir en compte a l'hora de posar una aplicació web en producció.
Usa sempre HTTPS
Usa sempre HTTPS si no s'enviarà tota la informació en text pla. Contrasenyes incloses.
Usa sessions
A diferència de les galetes les dades emmagatzemades en les sessions no s'envien mitjançant els encapçalats HTTP, romanen al servidor.
El que sí s'envia és l'identificador de sessió. Caldrà prendre mesures perquè l'identificador no puga ser accessible per tercers i així poder accedir a les dades emmagatzemades.
Segons l'OWASP:
Session settings are some of the MOST important values to concentrate on in configuring. It is a good practice to change session.name to something new.
I proposen la següent configuració bàsica:
session.save_path = /path/PHP-session/
session.name = myPHPSESSID
session.auto_start = Off
session.use_trans_sid = 0
session.cookie_domain = full.qualified.domain.name
#session.cookie_path = /application/path/
session.use_strict_mode = 1
session.use_cookies = 1
session.use_only_cookies = 1
session.cookie_lifetime = 14400 # 4 hours
session.cookie_secure = 1
session.cookie_httponly = 1
session.cookie_samesite = Strict
session.cache_expire = 30
session.sid_length = 256
session.sid_bits_per_character = 6 # PHP 7.2+
session.hash_function = 1 # PHP 7.0-7.1
session.hash_bits_per_character = 6 # PHP 7.0-7.1
Les recomanacions en major detall:
Control de la vida de sessió
-
Fes que expire la sessió després d’un curt període d’inactivitat: ajusteu el temps d’inactivitat a 5 minuts per a aplicacions altament protegides fins a no més de 30 minuts per a aplicacions de baix risc.
-
Habilita l’opció de tancament de sessió: caduca i destrueix explícitament la sessió en tancar la sessió.
-
Eviteu els inicis de sessió persistents (opció "recordeu-me"): opcionalment podeu restringir la informació conservada i revelada per l'aplicació, és a dir, obligar a l'usuari a tornar a iniciar sessió abans de realitzar cap operació crítica.
-
Fes que expire la sessió quan hi haja error de seguretat: qualsevol error de seguretat de l'aplicació hauria de donar lloc a la finalització de la sessió.
-
Fes caducar la sessió quan siga de llarga durada: obligació a reautentificar la sessió, que tot i estar actiu ha arribat al temps màxim permès, p.e. unes poques hores.
-
Elimineu la galleta de sessió en destruir una sessió.
Identificador de sessió
-
Utilitzeu només galetes per propagar l’ID de sessió, ja que quan es transmeten mitjançant un paràmetre URL, les sol·licituds GET poden ser emmagatzemades a l’historial del navegador, a la memòria cau i als marcadors. Aleshores també es pot visualitzar fàcilment.
-
Regenereu l'identificador de sessió: regenereu (substituïu-ne per un de nou) l'identificador de sessió, almenys cada cop que canvie el nivell de privilegi de l'usuari. Generalment es pot regenerar abans de qualsevol transacció important, després d’un determinat nombre de sol·licituds o després d’un període de temps.
-
Comproveu si l'identificador de sessió és vàlid (de mida i tipus previst) i que ha estat generat per l'aplicació i no proporcionat per l'usuari.
-
L'identificador de sessió hauria de ser adequadament llarg, imprevisible, difícil de reproduir i creat a partir de fonts aleatòries d'alta qualitat.
Cookie de sessió
-
Definiu el domini de la galleta a quelcom més específic que el domini de primer nivell.
-
No emmagatzeneu res a la galleta (almenys qualsevol informació sensible com el nom d’usuari o la contrasenya) sols’ID de sessió.
-
Definiu el senyalador només http per desactivar la captura de l'identificador de sessió mitjançant XSS.
-
Quan siga possible, utilitzeu un xifrat fort (SSL) i l'atribut
cookie_secure
per permetre la transmissió de cookies només a través de https.
Emmagatzematge de dades de sessió
-
Determineu on s'emmagatzemen les dades de sessió i si es tracta d’un sistema de fitxers o d’una base de dades, determineu qui més podria tenir accés a aquestes dades.
-
Quan s'emmagatzemen les dades de sessió en fitxers, assegureu-vos que l'aplicació està configurada per utilitzar un directori privat independent (per exemple, la directiva
session.save_path
). Utilitzeu els permisos del sistema de fitxers per protegir aquests fitxers d’observació o modificació d’usuaris diferents dels comptes necessaris per operar el servidor web i les aplicacions. Si això no és possible, cal xifrar les dades de la sessió o contenir només dades no sensibles. Tingueu en compte que PHP utilitza de manera predeterminada el directori temporal del sistema públic. -
Totes les variables de sessió s’han de validar i sanejar per assegurar-se que siguem correctes i que no conté caràcters inesperats.
No conèixer les contrasenyes
Al final, tothom crea una aplicació PHP que es basa en la sessió d’usuari. Els noms d’usuari i les contrasenyes s’emmagatzemen en una base de dades i s’utilitzen posteriorment per autentificar els usuaris després de l’inici de sessió.
És important que fer hash de les contrasenyes correctament abans d’emmagatzemar-les. El hashing i el xifrat són dues coses molt diferents que sovint es confonen.
El hashing és una funció irreversible i unidireccional. És produeix una cadena de longitud fixa que no es pot invertir. Això vol dir que podeu comparar un hash amb un altre per determinar si tots dos provenien de la mateixa cadena font, però no podeu determinar la cadena original. Si les contrasenyes no s'emmagatzemen amb hashing i un tercer no autoritzat accedeix a la vostra base de dades, tots els comptes d'usuari estaran compromesos.
A diferència del hashing, el xifrat és reversible (sempre que tingueu la clau). El xifratge és útil en altres àrees, però és una estratègia deficient per emmagatzemar contrasenyes de forma segura.
Les contrasenyes també han de salar-se individualment afegint una cadena aleatòria a cada contrasenya abans d'aplicar hashing. Això evita els atacs de diccionari i l'ús de "taules de l'arc de Sant Martí" (una llista inversa de hash criptogràfics per a contrasenyes comunes.)
El hashing i el salat són vitals, ja que sovint els usuaris utilitzen la mateixa contrasenya per a diversos serveis i la qualitat de la contrasenya és deficient.
Addicionalment, haureu d'utilitzar un algorisme especialitzat en hashing en lloc d'una funció de hash criptogràfic de propòsit general i ràpid (per exemple, SHA256). La llista breu d'algorismes de hashing de contrasenya acceptables (a juny de 2018) a utilitzar són:
- Argon2 (disponible a PHP 7.2 i versions posteriors)
- Scrypt
- Bcrypt (PHP us proporciona aquesta; vegeu més avall)
- PBKDF2 amb HMAC-SHA256 o HMAC-SHA512
Afortunadament, avui en dia PHP ens ho facilita.
Hashing de contrasenyes amb password_hash
A PHP 5.5 s'ha introduït password_hash()
. En aquest moment està utilitzant BCrypt, l'algorisme més fort actualment suportat per PHP. Tot i això, s'actualitzarà en el futur per donar suport a més algoritmes. La biblioteca de password_compat
es va crear per proporcionar una compatibilitat de PHP> = 5.3.7.
A continuació hem aplicat hashing a una cadena i, a continuació, apliquem el hashing contra una nova cadena. Com que les dues cadenes d'origen són diferents ("contrasenya-secreta" i "contrasenya-errònia"), aquesta sessió fallarà.
$passwordHash = password_hash("contrasenya-secreta", PASSWORD_DEFAULT);
if (password_verify("contrasenya-errònia", $passwordHash)) {
// Contrasenya correcta
} else {
// Contrasenya incorrecta
}
password_hash()
s'ocupa de la salificació de contrasenyes. La sal s'emmagatzema, juntament amb l'algorisme i el "cost", com a part del hash. password_verify()
extreu això per determinar com comprovar la contrasenya, de manera que no necessiteu un camp de base de dades independent per emmagatzemar les vostres sals.
PASSWORD_DEFAULT
Actualment utilitza l’algoritme bcrypt (predeterminat a partir de PHP 5.5.0). Observeu que aquesta constant està pensada per a adaptar-se sempre que hi haja un algoritme nou i més fort a PHP. Per aquesta raó, la longitud del resultat d’utilitzar aquest identificador pot canviar amb el temps. Per tant, es recomana emmagatzemar el resultat en una columna d’una base de dades de més de 60 caracters (255 caracters seria una bona elecció).