Mardi le 27 octobre 2009 à 01:36

[Tutoriel] SQL Injection – Les classiques (partie1)

Par Mohammed CHERIFI

sql_imgHello,
Aujourd’hui je vous parlerai d’un vecteur d’attaque très répondu sur internet, c’est SQL Injection, le sujet est très riche, j’ai donc décidé de le répartir en trois parties:

  • Les injections SQL basiques
  • SQL Injection avancée
  • Blind SQL Injection

Dans ce billet, j’expliquerai le concept d’une Injection SQL basique, les différentes formes sous lesquelles elle peut se présenter dans une application WEB, illustrées par des exemples concrets, ainsi que des solutions pour sécuriser son code et prévoir ce genre d’attaques!

Comme vous le savez tous, SQL (Structured Query language), est un langage de bases de données qui constitue le cœur des applications WEB qui interagissent avec un SGBD, sachant que le concept d’une Injection SQL est commun pour tous les types de SGBD (avec quelques petites variations), dans toute la série de ces tutoriaux, je vais considérer qu’on travaille sur une base de données MySQL qui tourne sur un serveur LAMP!

Alors c’est parti =)

SQL Injection, c’est quoi ?

SQL Injection est parmi les vecteurs d’attaques les plus connus sur la toile!, son principe est de modifier une requête SQL grâce à un champ mal filtré dans le but d’exécuter une requête non prévue par l’application, l’exploitation d’une injection SQL peut avoir des conséquences désastreuses sur un site, elle peut permettre à un attaquant de :

  • Bypasser une authentification
  • Lire des données sensibles depuis les tables mySQL
  • Injecter le nom et le schéma de la base de données
  • Lire et écrire dans le système de fichier et potentiellement exécuter du code PHP

Comment repérer une injection SQL?

Une Injection SQL est souvent repérée par un attaquant grâce aux messages d’erreurs, le test est assez facile à faire, il suffit d’insérer un caractère spéciale (un signle quote « ‘ » le plus souvent), ou modifier le type d’une variable utilisée dans une requête SQL, si la variable est mal filtrée l’exécution de la requête est interrompue et il y a de fortes chances que cette dernière est faillible à une Injection

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near

Et oui! c’est ça, merci mysql_error =)

Et si on passe aux exemples?

Assez de blabla, là on passe aux exemples, et on commence par l’un des plus classiques :

Bypasser une identification:

Stanislas: un développeur en herbe a conçu un formulaire d’identification, qui permet de poster le nom d’utilisateur et le mot de passe dans une page PHP, cette dernière vérifie si c’est les bons et affiche un message selon le résultat:

Code :

// page processlogin.php
$username = $_POST['username'];
$password = $_POST['password'];
$sql = mysql_query("SELECT * FROM users WHERE username = '$username' AND password = '$password'") or die(mysql_error());
if(mysql_num_rows($sql) == 1)
{
echo "Bienvenue $username dans votre espace membre!";
}
else
{
echo "Nom d'utilisateur et/ou mot de passe incorrecte";
}

Maintenant imaginons qu’un attaquant se connecte avec comme login : admin’–, la requête devient :

SELECT * FROM users WHERE username = ‘admin’–‘ AND password = ‘$password’

La requête SQL va aboutir, le single quote permettra de fermer le délimiteur de la chaine admin et les deux tirées servent à mettre le reste de la requête en commentaire, du coup la vérification du mot de passe sera ignorée ;) , Bienvenue admin dans votre espace membre!

C’est juste un exemple! l’attaque peut se présenter différemment selon la requête SQL :

Exemple 2:

//...
$sql = mysql_query("SELECT * FROM users WHERE ( username='$username' AND password = '$password' )");

Dans ce cas, pour bypasser l’identification il y a plusieurs possibilités, l’une est d’utiliser comme login: admin’)–
ou encore, comme login : admin’) or (‘a’='a, le principe est de toujours forcer la requête à retourner true :)

Injecter des données depuis une table

On dit souvent que l’union fait la force! c’est le cas pour les injections SQL car là on arrive aux choses sérieuses!

la commande UNION, elle existe depuis MySQL 4.0 et permet de combiner le résultat de plusieurs requêtes SELECT en une seule. Pour l’UNION, les champs des différents SELECT doivent avoir le même nombre et le même type!

Prenant l’exemple d’un petit forum, on considère une page profile.php qui affiche le profil d’un utilisateur donné à partir de son ID récupéré par $_GET

Code :

mysql_connect("localhost","root","");
mysql_select_db("test");
$user_id = $_GET['id'];
$sql = mysql_query("SELECT usernamen, nom, prenom, email FROM users WHERE user_id = $user_id") or die(mysql_error());
if(mysql_num_rows($sql) > 0)
{
$data = mysql_fetch_object($sql);
echo "
<fieldset>
<legend>Profile de ".$data->username."</legend>
<p>Nom d'utilisateur : ".$data->username."</p>
<p>Nom et prénom : ".$data->nom." " .$data->prenom ."</p>
<p>Adresse email : ".$data->email."</p>
</fieldset>";
}

Sans connaitre le code qui s’exécute derrière un attaquant peut détecter la présence d’une injection sql en essayant d’interrompre la requête en accèdent à la page : profile.php?id=1′, le fameux message d’erreur s’affiche, l’attaquant passe à l’étape suivante, qui est l’identification de nombre des champs utilisés dans le SELECT

La technique la plus courante est l’utilisation de la clause « ORDER BY », en incrémentant l’indice petit à petit jusqu’à ce que la page affiche une erreur

  • profile.php?id=1 order by 1 [OK]
  • profile.php?id=2 order by 2 [OK]
  • profile.php?id=3 order by 3 [OK]
  • profile.php?id=4 order by 4 [OK]
  • proile.php?id=5 order by 5 [ERREUR]

A ce stade là, l’attaquant peut savoir que la requête contient 4 champs dans le SELECT, et peut donc utiliser la clause UNION pour injecter des données!

profile.php?id=-1 UNION SELECT 1,2,3,4–

là on peut bien voir les chiffres s’afficher au lieu des données vu que l’id -1 n’existe pas dans la base, du coup les champs sélectionné dans l’UNOIN seront retourné (1,2,3,4), à la place de ces derniers l’attaquant peut sélectionner des données de n’importe quelle table sur laquelle l’utilisateur sql courant a les droits

Exemple :

profile.php?id=-2 UNION SELECT version(), user(), password, null FROM users
profile.php?id=-2 UNION SELECT host, user, password, database() FROM mysql.user

Il est facile pour un attaquant de deviner le nom des tables, d’ailleurs il existe des listes de tables sensibles susceptibles d’exister sur une base de données genre (login, users, auth, membres..), et depuis mysql 5 il est possible d’injecter les noms des tables à partir de la base information_schema! je reviendrai dans le billet de cette série (SQL Injection avancée) avec plus de détails sur cette partie là!

Il est également possible d’injecter des données depuis les autres bases sur-lesquelles l’utilisateur mysql courant a des droits!

Comment se protéger?

Maintenant que vous avez conscience du danger qu’une injection SQL classique pourrait engendrer lorsqu’elle est exploitée voici les bonnes pratiques pour sécuriser son application :

Pour notre cas par exemple : la solution est de filtrer l’input $_GET['id'] on conservant que la partie entière de sa valeur, pour ce faire :

$user_id = intval($_GET['id']);

et voilà le tour est joué :) , s’il s’agissait d’un nombre à virgule flottante on utilisera floatval() et ainsi de suite..

Pour les chaines de caractères, pensez toujours à utiliser mysql_real_escape_string, cette fonction permet de filtrer tous les caractères spéciaux et vous facilitera la vie! Et si vous avez le malheur de ne pas les utiliser dans vos requêtes, alors c’est bien le moment ;)

Donc voilà les classiques pour les injections SQL! Dans le prochain billet, on passera à la vitesse supérieur! J’exposerai des méthodes d’exploitation plus avancées, des erreurs à ne pas commettre ainsi que des solutions pour prévenir à ce genre d’attaques!

Partager cet article:
  • Twitter
  • Facebook
  • Google Bookmarks
  • del.icio.us
  • Netvibes
  • viadeo FR
  • Digg
  • LinkedIn
  • Slashdot
  • Sphinn
  • Mixx
  • Blogplay
  • Identi.ca
  • Print
  • Ping.fm
  • email
  • Posterous
  • Reddit
  • Yahoo! Buzz
  • PDF
  • RSS
  • Diigo
  • Fark
  • Blogosphere News
  • blogtercimlap
Tags :, , , ,

Articles similaires

7 Commentaires to [Tutoriel] SQL Injection – Les classiques (partie1)

Avatar

Stack

octobre 27th, 2009 at 1 h 51 min

top fort dude

Avatar

Zouhir Bahij

octobre 27th, 2009 at 2 h 38 min

You are the best :P

Avatar

vladimire

octobre 27th, 2009 at 10 h 03 min

J’ai suivis l’article avec tout l’interet du monde.. et je n’étais pas deçu, vivement la suite.

Avatar

boh

novembre 27th, 2009 at 15 h 22 min

bien joue moha
c’est bien explique
bon corage

Avatar

fenoril

février 15th, 2010 at 20 h 30 min

Clair, concis, génial !

Et tant pis pour mes heures de sommeil, il y a de quoi devenir parano…

Merci Mohammed

Avatar

Wail

mai 23rd, 2010 at 0 h 32 min

très bien expliqué mon khoya, génial

Avatar

Sécurité : Injection SQL (liste d’outils) « GNU-It

juin 12th, 2010 at 10 h 04 min

[...] aller plus loin, un tutoriel en trois parties destiner à mieux comprendre l’injection SQL (partie 1, partie 2, partie [...]

Réagissez à ce billet

Categories

Derniers commentaires

  • Victor: Roseny : Pour avoir les mois en Français voici mon code : $dateWidget = new sfWidgetFormI18nDate(array(...
  • abdessamad: Salam, Salutation pour cet article, N.B :  » Un md5 est une chaine de caractère en hexadécimal...
  • 0x1337: Nice tuto bien structuré et synthétisé ! La question qui se pose est ce un attaquant peut faire un Privilege...
  • Roseny: Bonjour, comment fais-t’on pour mettre les mois en français?
  • Laurent: Bonjour Mohammed et merci pour ce tuto. Que faut-il modifier pour que le champ date soit en un seul bloc au...
  • Stack: dommage que le co.ma était hacké aussi
  • Technologix: Très bon article, gg ;)
  • Wail: très bien expliqué mon khoya, génial
  • UpDeL: Respect !
  • El King Zizou: trés bonne explication j’aimerai bien voir des autres articles des attaques sur le web :)...

Flickr PhotoStream

  • Au dessus des montagnes
  • Nuages
  • Insolite hopital marocain
  • Plage bouznika
  • Maroc Blog awars with vladimire
  • Linux Party 2010 - EMI (Maroc)
  • Mawazine 2008
  • Essaouira
  • Rabat Ville with baba mimoun
  • Fucking CowBoyz
  • Essaouira 2009 - En attente de l'arrivé du cheb khaled!
  • Linux Install party Mohammadia

Twitter Feed


Warning: fread() [function.fread]: Length parameter must be greater than 0 in /homepages/44/d193174039/htdocs/mcherifi/wp-content/plugins/wordpress-twitter/BiBTweets.php on line 199
  • mcherifi: Underground Parking System http://bit.ly/aI440T original! le 27 Jul 2010 10:58
  • mcherifi: @halflings un moment j'ai pensé qu'il s'agit d'une erreur, c'est en lisant bien que j'ai compris que ya aussi #freelansing lol le 27 Jul 2010 10:38 en réponse à halflings
  • mcherifi: Comment réaliser sa première photographie en freelensing? http://bit.ly/daZewv le 27 Jul 2010 09:45
  • mcherifi: Une nouvelle loi vient d’être adoptée en #Tunisie , elle intérdit les fessées données aux enfants! Qu'allez vous faire si c'était au #Maroc ? le 26 Jul 2010 16:57
  • mcherifi: Faut-il suivre ses passions ou s’orienter vers du lucratif ? http://bit.ly/99Nsiu le 26 Jul 2010 16:30
  • mcherifi: Safari v4 & v5 critical vulnerability in the AutoFill feature http://bit.ly/9yVKco #safari #security #autofill le 26 Jul 2010 14:41
  • mcherifi: RT: @agharass : Est ce que vous avez un compte http://meme.yahoo.com ? Plz RT le 24 Jul 2010 21:20
  • mcherifi: @A_T_J pas encore mon ami, la soirée vient à peine de commencer ;) ce n'est pas qu'on tweetant pas qu'on dors :P le 24 Jul 2010 03:06 en réponse à A_T_J
  • mcherifi: Trop drôle! Insultes de développeurs http://ping.fm/SKdvT #fordeveloppersonly le 20 Jul 2010 09:02
  • mcherifi: Si vous aimez les pentests voici un ISO pour s'entrainer avec l'OS le plus vulnérable au monde http://ping.fm/a5rKi #damnvulnerablelinux le 20 Jul 2010 08:58
  • mcherifi: Oulah! c'est mon 1000 tweet, Happy day à tous! le 20 Jul 2010 08:56
  • mcherifi: Frameworks PHP: Symfony vs CodeIgniter http://ping.fm/MnLvy le 14 Jul 2010 15:42
  • mcherifi: D'ici fin juillet, l'enveloppe annuelle de la compensation sera déjà épuisée ! Que va faire l'Etat ? http://ping.fm/t2ym2 le 14 Jul 2010 14:00
  • mcherifi: Real Social Dynamics Nation : Smart people http://ping.fm/g2zfw le 14 Jul 2010 11:26
  • mcherifi: just achieved all WabLab HackMe challenges http://bit.ly/dClKUj Actual Rank: Morocco 1, World 10, waiting for the next contests.. le 11 Jul 2010 16:52
  • mcherifi: le monde est fondé sur des conventions, ce que accepte la majorité est souvent ce qui est adopté même si il est faux! le 11 Jul 2010 10:49
  • mcherifi: Youpii, ma carte son Creative Sound Blaster Live marche à merveille sous Ubuntu Lucid lynx, VIVA LINUX <3 ! le 10 Jul 2010 22:20
  • mcherifi: si vous avez du mal avec les dns google voici une version standalone du chat audio/video dans gmail 3http://ping.fm/S76qv le 06 Jul 2010 15:32