BrowserWar-Dev

La guerre des navigateurs

Injections SQL


<< Inclusions arbitraires XSS >>


   Quand je me servais dans mes requêtes SQL d'une variable obtenue par interaction avec l'utilisateur ou son navigateur (notamment POST, GET) et comme je n'y faisais pas vraiment attention, il était possible à d'éventuels attaquants d'utiliser ce qu'on appelle une injection SQL afin de modifier le sens de mes requêtes. Le langage SQL est très puissant : il permet, outre la consultation et parfois la modification de la base de données, par exemple de créer des fichiers avec un contenu arbitraire. Ainsi, ce type de faille est critique et très dangeureuse.

Injections sur chaînes de caractères
   Sur mon serveur, il est vrai que la variable PHP magic_quotes_gpc était mise à true. Ainsi, toutes les données transmises par POST, GET ou cookies étaient systématiquement assainies (les null bytes étaient remplacés par "\0" et les ' ou " étaient aussi échappés, à savoir, précédés d'un antislash qui annule leur effet).
Donc, il n'était pas possible de perpétrer une injection sur chaînes de caractères puisque une injection aurait été remplacée par exemple par SELECT * from table WHERE champ=' \' OR 1=1--'. Puisque aucun champ n'est varisemblablement égal à " \' OR 1=1--", la requête échouera comme prévu.
Tout ceci avait l'air très bien, sauf que je me reposais sur le serveur. Si quelqu'un avait copié mon code et placé sur un serveur qui n'effectuait pas l'assainissement des variables (les serveurs perso free par exemple), il aurait été vulnérable aux injections sur chaînes de caractères. Pareil si une mise à jour ou une modification intervenait sur mon propre serveur.
Dans la version 2, j'ai donc préféré regarder si cette option est activée et effectuer moi-même l'ajout de slashes dans le cas contraire (fonctions addslashes() ou mysql_real_escape_string() à laquelle je préfère cette dernière pour des raisons qui dépassent le cadre de cette petite note) :
    function happy_meal($meltingpot) {
      ...
      $meltingpot = get_magic_quotes_gpc() ? $meltingpot : mysql_real_escape_string($meltingpot);
      ...
      return $meltingpot;
    }
La pratique veut que la fonction addslashes() pose des problèmes de sécurité dans certains cas précis, il peut donc paraître préférable si ces cas ne sont pas maîtrisés d'utiliser systématiquement mysql_real_escape_string() de la façon suivante et voici donc la version 2 finale :
    function happy_meal($meltingpot) {
      ...
      $meltingpot = mysql_real_escape_string(get_magic_quotes_gpc() ? stripslashes($meltingpot) : $meltingpot);
      ...
      return $meltingpot;
    }


Injections sur champs numériques
   Un fait plus dangereux et qui m'était totalement inconnu : les injections SQL sur les champs numériques. En effet, le SELECT login FROM members WHERE id=$_GET['id'] paraît tout à fait inoffensif. Il n'y a sans doute pas plus dangereux. En effet, on s'en rend bien compte sur l'exemple ci-dessus : il n'y a même pas besoin de quotes pour effectuer une injection SQL !
Une telle faille permet beaucoup d'exploitations :
    - exécution de code arbitraire avec une requête du type SELECT b FROM a WHERE id=-1 UNION SELECT 'code' INFILE trojan.php
    - divulgation de la base de données avec SELECT b FROM a WHERE id=-1 UNION SELECT concat(login,char(32),passwd) FROM members
    - XSS avec SELECT b FROM a WHERE id=-1 UNION SELECT '<script>alert(document.cookie);</script>' si le résultat de la requête est amené à être affiché
    - etc...
On peut facilement repérer ce type de faille en observant les différences entre la requête 1+AND+1=1 et 1+AND+1=2 (si la page n'est pas modifiée dans le premier cas mais l'est dans le deuxième, il y a vulnérabilité).
Il y a plusieurs façons d'empêcher ce type d'injections :
    - entourer les paramètres numériques de quotes : SELECT login FROM members WHERE id='$id'. Il faut bien sûr s'assurer dans ce cas que les dispositions anti injections dans les chaînes de caractères existent.
    - vérifier que les paramètres passés sont bien numériques grâce à la fonction is_numeric(). De la même façon, quand cela est possible, on peut vérifier les formats de données, même pour les chaînes de caractères (dates, nombres de chiffres, de lettres, etc...). Dans ce cas, on produit une erreur quand les données ne sont pas correctes.
    - utiliser des fonctions qui rendent conforme les données, quelle que soit leur format (fonction intval() pour caster en entier par exemple, qui renvoie forcément un entier). Ainsi, on prévoit une forte tolérance aux erreurs de l'utilisateur.
Dans la version 2, nous avons utilisé au moins l'une de ces techniques dès lors qu'un paramètre numérique intervient dans une requête.


<< Inclusions arbitraires XSS >>


Hacking et sécurité informatique - BrowserWar - Releases