JeuWeb - Crée ton jeu par navigateur
La sécurité & les bonnes pratiques - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : La sécurité & les bonnes pratiques (/showthread.php?tid=7389)

Pages : 1 2 3


La sécurité & les bonnes pratiques - Jade H - 02-06-2015

Hiiii ! C'est encore moi, j'espère que vous allez bien. Et si ce n'est pas le cas il faut quand même le dire :O!
J'ouvre ce POST pour moi, mais aussi pour les personnes qui ne se sont jamais posées la question de la Sécurité et des Bonnes Pratiques. Sincèrement je suis la première à avoir négligé ce point lors de ma formation au développement c'est pour cela que j'ai décidé de rendre disponible cet aspect extrêmement important.

Alors, si vous avez des choses à dire  je serais ravis de le lire.
Biensure il serait vraiment intéressant de savoir le pourquoi du comment sans forcément rentrer dans du code (même si ce serait l'idéal).
Merci Beaucoup.


Jade ? J'adhère Smile


RE: La sécurité & les bonnes pratiques - Xenos - 02-06-2015

Le grand principe:
Tout ce qui est hors d'une entité (serveur, classe, méthode,...) est dangereux pour cette entité: tout ce qui entre dans le serveur est potentiellement dangereux, et tout ce qui sort du serveur n'est plus traçable


Les principes de bases:

Ne jamais accorder le moindre crédit aux données extérieurs: en conséquence, toujours les valider (via filter_input pour PHP)
• De même, éviter d'accorder du crédit aux entrées des fonctions/méthodes: si le paramètre n'est pas typé, Classe::methode($x) doit pouvoir accepter n'importe quoi pour $x (la méthode peur vérifier que le paramètre est du bon type); n'oubliez pas que les attributs publics $this->* et les variables globales ($_*) sont des entrées implicites
Toute commande sérialisée est dangereuse et doit être maniée avec précaution (dans SELECT * FROM users WHERE user_id=$id, la machine ne sait pas que $id est un 'paramètre')
Tout ce qui sort du serveur n'est plus fiable; ergo toute page peut être appelée avec n'importe quels paramètres, par n'importe qui, n'importe quand
Hasher et saler tout ce qui peut l'être, c'est à dire tout ce dont seule la signature compte (mot de passe principalement)



Ressource utile:
• L'OWASP et son Top 10 des failles de sécurité, à savoir:

Le TOP 10
→ L'injection = Accepter un paramètre qui sera ensuite interprété comme une commande
→ L'authentification = Une mauvaise façon d'identifier les utilisateurs
→ XSS = L'injection dans HTML (ou toute autre sortie du serveur)
→ Les fuites de références = Faire sortir du serveur une donnée qui lui est interne
→ La configuration = Mal configurer ses outils de sécurité
→ Les fuites d'informations = Donner plus d'informations à l'utilisateur que ce dont il a besoin
→ La vérification des droits = Ne pas oublier de vérifier les droits dans la page appelée par un formulaire/URL
→ CSRF = La requête reçue par le serveur n'a pas forcément été envoyée consciemment par l'utilisateur
→ Les versions obsolètes = Se reposer sur de vielles versions
→ Les redirections = Rediriger l'utilisateur vers une URL que l'on n'a pas vérifiée


RE: La sécurité & les bonnes pratiques - Jade H - 03-06-2015

Génial ! Merci so much


RE: La sécurité & les bonnes pratiques - Akira777 - 03-06-2015

Difficile de passer après Xenos, c'est exactement ça !

Pour apporter une petite touche vis à vis de PHP en particulier :

- Toujours protéger les liens effectuant des actions avec un jeton unique à chaque session utilisateur. Genre: index.php?page=equipement&action=supprimer&id=5 (ou via POST c'est pareil) peut-être utilisé de manière vilaine. C'est la base du CSRF.

- Quand on utilise un CMS (coucou WordPress), bien faire gaffe à le garder à jour et bien faire gaffe aux plugins / thème qu'on y installe.

- De préférence, toujours utiliser des requêtes préparées lors d'une interaction avec la SGBD.

- Sur les pages lourdes, genre génération d'un classement de joueur, bien veiller à ce qu'il ne soit pas généré à la demande, mais mis dans un système de cache (même à durée courte). Afin d'éviter les pinioufs qui vont l'ouvrir dans 150 onglets et saturer le serveur.

- Faire attention aux scripts qui redimensionnent les images à la volée via l'URL. Genre : index.php?image=avatar.jpg&width=150&height=150. Bien effectuer un max de contrôle dans ce genre de cas, ou bien définir des scénarios précis (Genre: index.php?image=avatar.jpg&size=thumb qui correspondrait à 150x150).
Ca évite encore une fois les péquenauds qui vont tenter de générer 13 millions d'images en testant 13 millions de combinaison de tailles différentes et ainsi saturer l'espace disque (en plus du CPU quand utilisation de GD par exemple).

- Surtout bien hasher les passwords. Xenos l'a dit mais je le répète parce que j'en ai marre de voir des pass en clair en BDD.

- Ne jamais laisser le listing des répertoires, on sait jamais... Genre l'accès direct à /includes/classes/ devrait afficher un forbidden et pas un listing de fichier.
Bon, de part leur organisations, peu de frameworks modernes rendent ça possible vu que le code est en dehors du root.

- En plus des requêtes, faire gaffe avec les en-têtes de la fonction mail(). Quand on laisse un message ou sujet libre dans un formulaire de contact, ça peut faire des dégâts si mal protégé.

- Garder ses plugins à jours, genre CKFinder, gestionnaire de fichiers en tout genre, scripts d'uploads, ... Et SURTOUT, ne jamais déployer ces scripts en laissant les fichiers d'examples de ces mêmes scripts. Ils sont souvent utilisés, une requête Google bien placé permet de savoir le numéro de version de l'outil et de trouver si ces fichiers d'exemple existent. Ca peut FAIRE DE GROS DEGATS.

Euh... Je crois que c'est tout pour le moment.


RE: La sécurité & les bonnes pratiques - Xenos - 04-06-2015

Perso, l'accès au listing d'un répertoire ne me semble pas trop problématique pour les ressources publiques. Voire même, cela permet de vite s'apercevoir qu'une ressource est considérée à tort comme publique. Dans Apache, si une ressource est dans le listing, c'est qu'elle est accessible, si elle ne l'est pas, c'est qu'elle est privée. C'est un bon moyen de vite vérifier la configuration des accès à certains fichiers ou répertoires.


RE: La sécurité & les bonnes pratiques - Akira777 - 05-06-2015

(04-06-2015, 10:22 PM)Xenos a écrit : Perso, l'accès au listing d'un répertoire ne me semble pas trop problématique pour les ressources publiques. Voire même, cela permet de vite s'apercevoir qu'une ressource est considérée à tort comme publique. Dans Apache, si une ressource est dans le listing, c'est qu'elle est accessible, si elle ne l'est pas, c'est qu'elle est privée. C'est un bon moyen de vite vérifier la configuration des accès à certains fichiers ou répertoires.

Oui justement, c'est que je disais (mais je l'ai peut-être mal expliqué...). Oui pour de la ressource publique ça pose pas de problème ! Justement en utilisant des frameworks PHP récents (j'entends par là Symfony, Laravel et consors), cette séparation est faite de part leur structure vu que le document root ne contient que des données "publiques".
Je faisais référence à du code maison, ou du vieux framework où tu fais un "include/" ou "lib/", et tu tombes sur tout un tas de script PHP et/ou des librairies utilisées qui pourraient laisser entrevoir un readme avec un numéro de version par exemple.


RE: La sécurité & les bonnes pratiques - Xenos - 05-06-2015

Dans ce cas, d'accord Smile

D'ailleurs, ça me permet d'ajouter que bien définir les droits des fichiers est essentiel: Apache gèrera alors tout seul cette histoire de listing (les fichiers privés n'apparaissent pas dans le listing, et le listing d'un dossier privé est interdit).

Je dirai, à titre d'exemple (me corriger si besoin):
• Fichiers publics, accessibles à tous: 444 (ou 644?)
• Fichiers privés (scripts PHP): 400 (ou 500?)
• Dossiers et fichiers de données écrits par le serveur: 600 (ou 644 s'ils doivent être directement lus par les visiteurs)


RE: La sécurité & les bonnes pratiques - L'Omniscient - 25-03-2016

Moi j'utilise strip_tags au lieu de filter_input, ça va aussi ?


RE: La sécurité & les bonnes pratiques - Xenos - 25-03-2016

strip_tag supprime uniquement les tags HTML, PHP et les null-bytes, donc tout dépend de ce que la donnée d'entrée est censée être.

Si ta donnée est censée être un texte (genre nom du joueur), et si ton stirp_tags est là pour éviter les injections dans la page HTML (genre echo "<strong>" . $user->name . "</strong>"), alors ce n'est pas la donnée d'entrée qu'il faut protéger, mais l'emplacement où elle est insérée: echo "<strong>" . htmlentities($user->name, 'utf-8') . "</strong>" (ou mieux: utiliser DOMDocument, générer un XML avec les données, et le passer dans une moulinette XSL, là, t'as rien à gérer niveau échappement/encodage).

D'ailleurs: tu gères comment, en strip_tag, le fait que $_GET['...'] n'existe peut-être tout simplement pas? via un array_key_exists() avant le strip_tags? filter_input le fait implicitement Wink

Note: à la relecture, je me dis que peut-être tu récupères ton $_GET['...'] sans filtre, et qu'à l'insertion dans la page HTML, tu strip_tags. Pourquoi pas, ce n'est pas un soucis, d'une part, il faut savoir ce qu'il se passe si le $_GET['...'] n'existe pas, et d'autre part, il faudra bien être conscient que la donnée peut alors contenir absolument n'importe quoi, de n'importe quelle longueur.


RE: La sécurité & les bonnes pratiques - Prélude - 25-03-2016

Attention, strip_tag n'empêchera pas de faire un truc du genre onmouseover="alert('et Boum');"
Ce n'est pas suffisant.