Programmation PHP/Sécurité
Sécuriser les en-têtes HTTP
modifierPour commencer, il est préférable d'utiliser HTTPS à HTTP pour complexifier l'attaque de l'homme du milieu, en garantissant l'intégrité et la confidentialité du flux réseau.
Ceci peut être forcé par le mécanisme HSTS, qui utilise l'en-tête HTTP Strict-Transport-Security.
Masquer les versions
modifierPour se prémunir des exploitations des failles de sécurité liées à sa version de PHP ou de serveur Web, on peut chercher régulièrement si certaines ont été détectées et ont une mise à jour sur https://www.exploit-db.com/.
Mais pour éviter d'être la cible de celles qui fonctionneraient, il est préférable de masquer ces versions dans les en-têtes HTTP.
Ceci se fait généralement au niveau des fichiers de configuration du serveur, mais peut aussi être réalisé en PHP ainsi :
ini_set('expose_php', 'Off');
header('X-Powered-By: UnknownWebServer');
Restreindre les connexions
modifierDe plus, il existe d'autres sécurisations des en-têtes HTTP pour se prémunir des attaques de type Cross-site request forgery (CSRF).
Exemple de couche de protection utilisant le Content Security Policy (CSP) :
ini_set('register_globals', 'Off');
header('Content-Security-Policy "default-src \'self\'; style-src \'self\' \'unsafe-inline\'; script-src \'self\' \'unsafe-inline\'; img-src \'self\' data:"');
header('X-Frame-Options "SAMEORIGIN" always');
header('X-Content-Type-Options nosniff');
header('Referrer-Policy: origin');
header('Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()"');
Voir aussi Cross Origin Ressource Sharing (CORS) avec Access-Control-Allow-Origin.
Protéger l'accès à l'application
modifierPour éviter que des robots spammeurs polluent l'application via ses formulaires et ses API, ou la saturent par une attaque par déni de service (DoS attack), il y a plusieurs solutions complémentaires :
- Filtrer l'accès par un whitelistage d'IP (ex : via iptables).
- Configurer un throttle dans le serveur Web, qui va empêcher un trop grand nombre de connexions de la même provenance (via iptables aussi).
- Chiffrer la connexion par un VPN (impossible les utilisateurs prévus sont inconnus et proviennent des moteurs de recherche).
- Échapper les caractères interprétés lors des attaques de type injection SQL (généralement les apostrophes), et cross-site scripting (alias XSS, qui injecte du JavaScript entre balises HTML "script"), ou clickjacking (balises "iframe"). En échappant les chevrons cela suffit)[1].
- Imposer aux utilisateurs des mots de passe complexes (c'est-à-dire impossible à deviner par robots avant plusieurs années de tentatives infructueuses).
- Installer un captcha sur les formulaires accessibles aux utilisateurs non connectés. Par exemple reCAPTCHA, ou sur MediaWiki ConfirmEdit.
- Filtrer les messages postés sur l'application en les comparant aux listes partagées de spams connus, comme l'API Akismet[2], ou sur MediaWiki TitleBlacklist.
- Utiliser PHP >= 8 qui protège par défaut contre les attaques XML external entity attack (XXE)[3].
Chiffrer les données sensibles
modifierLe fait de stocker les mots de passe en clair (non chiffrés), dans un fichier ou une base de connées constitue une faille de sécurité.
Il est donc obligatoire de les chiffrer. Pour réaliser cela, il existe plusieurs fonctions PHP.
Chiffrement symétrique
modifierDans le cadre d'échange de données censées être déchiffrées par tout le monde, on peut utiliser base64, ce qui prend 33 % de place en plus que les données encodées[4] :
base64_encode()
base64_decode()
Mais si on souhaite restreindre le décodage à certains, une cryptographie symétrique peut être assurée avec OpenSSL[5] :
openssl_encrypt()
openssl_decrypt()
Chiffrement asymétrique
modifierLe cryptographie asymétrique est plutôt utilisé pour garantir une identité, via une clé privée et une publique. En PHP, selon se traduit par :
openssl_public_encrypt()
[6]openssl_private_decrypt()
Hachage
modifier- hash($algo, $data)[7] : avec un algorithme de la liste
hash_algos()
[8]. Ex :hash('sha256', $maChaine)
. - crypt()[9] est une fonction de hachage à sens unique d'une chaine, qui accepte en deuxième paramètre optionnel un salage.
- sha1() : déconseillé car facile à cracker[10].
- md5() : déconseillé car facile à cracker[11].
Scanners
modifierCertaines sociétés proposent des pentests payant (en boite noire ou blanche).
Mais un bon outil gratuit permet déjà de se faire une idée : https://observatory.mozilla.org.
Références
modifier- ↑ https://github.com/WebGoat/WebGoat
- ↑ https://symfony.com/doc/current/the-fast-track/fr/16-spam.html
- ↑ https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#php
- ↑ https://www.php.net/manual/fr/function.base64-encode.php
- ↑ http://php.net/manual/fr/function.openssl-encrypt.php
- ↑ https://www.php.net/manual/fr/function.openssl-public-encrypt.php
- ↑ https://www.php.net/manual/fr/function.hash.php
- ↑ https://www.php.net/manual/fr/function.hash-algos.php
- ↑ http://php.net/manual/fr/function.crypt.php
- ↑ https://www.php.net/manual/fr/function.sha1.php
- ↑ https://www.php.net/manual/fr/function.md5.php