Sunpak
MySQL/Sécurité
Sécurité.
Sur Internet, des pirates tentent de récupérer des données en violant leurs accès. Ils insèrent souvent du code dans une page HTML ou PHP, par injection de code, généralement par :
Les bases de données permettent d'assurer le stockage des informations en liaison par exemple avec des pages HTML couplées avec PHP. Donc tout le monde peut en avoir accès par l'intermédiaire d'un client relié au serveur. MySQL basé sur SQL est notamment très utilisé avec PHP. Il est donc pertinent d'examiner quelques notions de sécurité en matière de SQL.
En ce qui concerne SQL, il faut savoir premièrement qu'une astuce de programmation ou un détournement de requête possible à partir d'un serveur a de bonnes chances de réussir sur un autre et il en est de même avec les applications web mêmes, qui peuvent être utilisées afin d'atteindre le serveur et d'en saccager les données.
Paramètres de connexion.
Parfois, les paramètres de connexion (dont login et mot de passe) sont stockés dans un fichier texte non crypté, comme un .ini. Cela n'est donc pas recommandé : si un utilisateur devine son nom il peut le lire sans peine. S'il est situé en dehors du répertoire WWW c'est mieux, mais la meilleure façon est de les enregistrer dans un programme (ex : .php).
Il est toujours possible pour un utilisateur de trouver les accès FTP, donc il vaut mieux en utiliser d'autres pour MySQL.
Inutile de se souvenir des mots de passe MySQL car le programme est censé le retrouver automatiquement. Il convient donc d'en choisir un robuste : très long, avec au moins une majuscule, une minuscule, un symbole (ex : '_') et un chiffre. Le tout sans contenir de mots du dictionnaire car ils sont utilisés pour accélérer les crackages lors d'attaque par force brute.
Injections SQL.
Définition.
Normalement les valeurs stockées dans codice_1 peuvent être insérées directement dans des requêtes SQL. Toutefois les exploitent une faille de sécurité engendrée par le caractère d’échappement.
Exemple.
Numérique.
Soit le code PHP suivant qui récupère les données d'un formulaire :
 $sql = "DELETE FROM articles WHERE id = " . $_POST['article_id'];
Si on remplit le champ du formulaire avec le nombre "42", le code s'exécute normalement :
 DELETE FROM `articles` WHERE `id`= 42 -- supprime une ligne
Mais si on ajoute une expression booléenne toujours vraie ensuite, "42 OR 1=1", cela change complètement le résultat :
 DELETE FROM `articles` WHERE `id`= 42 OR 1=1 -- supprime toutes les lignes (car 1=1 toujours vrai)
L'utilisateur peut aussi insérer d'autres commandes à la suite, séparées par des points-virgules. Il s'agit du chainage ("chaining SQL queries"). Ex :
 DELETE FROM `articles` WHERE `id`= 42; DROP TABLE `users`;
Chaîne.
Soit le code PHP suivant :
 $sql = "SELECT * FROM `users` WHERE login = '" . $_POST['user_login'] . "'";
 SELECT * FROM `table1` WHERE title='bla bla' -- sélectionne
Dans le cas des chaînes de caractères, il faut exploiter les apostrophes autour :
 SELECT * FROM `table1` WHERE title='bla bla'; TRUNCATE TABLE `table1` -- supprime tout
Pour obtenir cette requête, il faut remplir le champ de formulaire pour fermer l'apostrophe ouvrant puis commenter le fermant :
 bla bla'; TRUNCATE TABLE `table1`--
Par ailleurs, si un utilisateur découvre comment manipuler une base de cette façon, il peut très bien se créer un compte administrateur ensuite, et effectuer des modifications discrètes dans le but de récupérer de l'argent (fausses factures, phishing...).
Blind SQL injection.
Si le code PHP empêche les injections SQL ci-dessus, il est potentiellement tout de même possible d'obtenir des informations en injectant des expressions booléennes vraies et fausses pour en comparer les retours de formulaire.
Par exemple, si les retours différent pour :
 x' and 1=1--
 x' and 1=0--
alors le champ rempli peut être exploité :
 x' and substring(password, 1, 1)='a
 x' and substring(password, 1, 1)='b
 x' and substring(password, 1, 1)='c
Solutions.
Il faut vérifier que la variable stocke bien le type de données prévu :
Par ailleurs, aucun commentaire SQL ne devrait pourvoir être inséré par l'utilisateur.
Mots de passe.
Généralement ils sont cryptés puis dans la base par les applications. Par contre si c'est fait en SQL, c'est qu'ils ont été écrits au moins une fois en clair et donc été visibles :
Il est donc fortement déconseillé d'envoyer ce genre de commandes :
SELECT 1 FROM `clients` WHERE `password`=MD5('abraxas')
Préférer depuis un .php par exemple :
 $sql = "SELECT 1 FROM `clients` WHERE `password`='".md5('abraxas')."'";
Il est également déconseillé de ne rechercher que le mot de passe, il faut que le nom corresponde aussi, et utiliser une fonction de hachage cryptographique plus récente comme SHA256 :
 $sql = "SELECT 1 FROM `clients` WHERE `name`='".username."' AND `password`='".hash('sha256','abraxas')."'";
SSL.
Si le contenu de la base est publique, il n'y a pas de raison de crypter les communications. 
Toutefois il peut y avoir un accès restreint pour les droits d'écriture, ce qui nécessite des mots de passe.
Le cryptage s'avère une bonne solution pour cela. En effet, en plus de crypter les messages, il certifie que l'utilisateur est bien celui qui était prévu (même si ce dernier a donné son mot de passe par phishing).
Risques dans les manipulations de données.
On en retrouve plusieurs types :
Chiffrement d'un mot de passe.
Le chiffrement d'un mot de passe ou d'une donnée consiste en sa transformation en une autre donnée par le biais d'une méthode extrêmement difficile à inverser voire impossible avec les fonctions de hachage.
MySQL offre des méthodes de chiffrement des données et par la même du mot de passe. Nous avons par exemple : 
INSERT INTO utilisateurs(identifiant, motdepasse) VALUES ('$id', MD5('$mdp'));
-- Vérification :
SELECT id FROM utilisateurs WHERE identifiant = '$idTest' AND motdepasse = MD5('$mdpTest');
-- Pour du contenu sécurisé à afficher : 
-- - Stockage :
INSERT INTO dossiersSecrets(titre, contenu) VALUES ('$titre', AES_ENCRYPT('$contenu','motdepasse'));
-- - Récupération :
SELECT titre, AES_DECRYPT(contenu,'motdepasse') AS contenu FROM dossiersSecrets; 
Sécurité PHP.
Voici quelques types d'attaques que l'on retrouve fréquemment :
Par exemple, c'est introduire une instruction PHP dans une page, qui ira chercher du code PHP sur un site distant pour le ramener sur le serveur local du pirate et l'exécuter comme code local, afin de prendre contrôle du serveur et des données du serveur distant piraté.
Cela ce fait par exemple à l'aide de : eval(), fonction qui prend en argument une chaîne de caractère pour l'exécuter comme du code PHP ; et par là exécuter des opérations destructrices de données par cette voie. 
Il suffit en effet que ce site ait des autorisations de lecture et qu'il soit accessible depuis le Web, sans besoin de droit d'exécution ou d'écriture pour exécuter tous les codes PHP que veut le pirate. En stockant le fichier, par la fonction "upload" (ex. image), le code est exécuté sur le serveur pirater et vient en saboter ou déranger le fonctionnement et même la lecture des autres documents.
Si elle est activée permet d'injecter dans les scripts toutes sortes de variables ; ce qui rend la programmation de script peu sûr. Heureusement que dans les versions supérieures à PHP 4.2 l'option register_globals est désactivée par défaut. 
C'est-à-dire la gestion des erreurs, ou les mécanismes par lesquels l'application web déterminera la validité des données qui entrent et sortent de l'application. Il s'agit donc de s'assurer que : premièrement on ne puisse pas contourné le filtrage des données, que deuxièmement les données invalides ne puissent pas être confondues avec des données valides et enfin identifier l'origine des données.
Vous trouverez les solutions possibles à ces problèmes dans ce guide de sécurité PHP en ligne : http://phpsec.org/.
La solution des systèmes de gestion de contenu ou de création de site web.
Une autre solution est d'utiliser des systèmes de création et de gestion de contenu Web, pour créer un site web personnel et l'agrémenter d'une petite bases de données. L'avantage ici est que si vous utilisez par exemple une application comme http://sites.google.com/.
L'avantage est que la sécurité est ici gérée par de grandes sociétés comme ici 'Google' qui engage des experts en la matière. Il devient dès lors très difficile pour des pirates de saccager les données de l'application web que vous créez, ainsi que la base de données.
Sites.google, par exemple, est une application en ligne qui permet le plus simplement possible de créer un petit site Internet perso agrémenter d'une base données. Pas besoin ici de sécuriser les données c'est la société Google, qui s'en charge ! Par exemple, Google.site permet de rassembler rapidement en un seul endroit une série d'informations, tout en sécurité : 
Elle permet également en matière de sécurité d'autoriser leur accès ou leur modification à un groupe restreint, ou carrément au monde entier. Encore une fois, il y a ici la garantie de Google en matière de sécurité des informations. 
Voici cependant quelques mesures de sécurité qui sont offertes à l'utilisateur : 
En matière de mot de passe il est à noter qu'il s'agit d'avoir sous la main trois types de mot de passe selon leur utilité : un pour des applications banales sans importance que vous utilisez, l'autre pour des applications personnelles (ex. e-mail), et l'autre enfin si possible plus complexes pour des informations hautement importantes et confidentielles que vous désirez gérer depuis Internet (ex. accès pour un site bancaire).
Ouverture à un PC distant.
Par défaut le serveur MySQL n'écoute pas sur le réseau. Pour changer cela, il faut préciser son IP publique dans la configuration :
 vim /etc/mysql/mysql.conf.d/mysqld.cnf
ajouter ou modifier la ligne :
 bind-address = MonIPPublique
Si le problème persiste, vérifier que le port 3306 est bien ouvert sur le pare-feu.
SQL SECURITY.
Les droits d'une vue peuvent dépendre se son créateur ou de ses utilisateurs. Pour les définir, utiliser codice_7 et codice_8.
Pour localiser les vues qui n'ont pas ces droits (et peuvent donc renvoyer des erreurs de permissions) :
select table_schema, table_name, SECURITY_TYPE
from information_schema.views
where SECURITY_TYPE <> 'INVOKER';