En esta serie de entradas, repasaremos algunas técnicas para realizar pentesting sobre entornos en Azure. En esta tercera entrada, vamos a ver vectores de ataque enfocados a obtener credenciales de usuarios registrados en Azure AD.
Antes de comenzar, si estás viendo este contenido por primera vez, te recomendamos ir a las partes anteriores para entender los fundamentos:
- https://labitacoradelhacker.com/atacar-a-la-nube-pentesting-en-azure-parte-1-fundamentos/
- https://labitacoradelhacker.com/atacar-a-la-nube-pentesting-en-azure-parte-2-iaas-y-paas
Ahora sí, comencemos:
Importante: Este escenario es demostrativo y con la base de realizar pruebas de hacking ético. Comprometer cuentas sin consentimiento, puede ser considerado ilegal. Utilice este conocimiento bajo su propio riesgo.
¿Por donde empiezo?
Como hemos explicado en los artículos anteriores, Azure tiene una estructura jerarquizada para la creación de los recursos, y para conceder accesos a dichos recursos se utilizan roles, que son asignados a security principals.
Los roles tienen diferentes niveles de privilegios, tanto sobre los recursos como el propio AD, por lo que es importante comprender que no todas las cuentas nos serán igual de útiles en nuestro proceso de pentest. En un entorno real, pueden existir cuentas que solo tengan acceso de lectura a un determinado recurso o servicio, y no nos permita conseguir nada crítico, o incluso podrían existir cuentas de usuario final que solo tienen acceso a Office 365, y no tenga permisos a ningún recurso de Azure.
En la siguiente imagen se muestra una estructura de cómo funcionan los roles dentro de Azure:

Un objetivo ideal es comprometer la cuenta de un Global Admin, sin embargo, esto podría ser muy complicado en un entorno correctamente configurado. Por ahora nos concentraremos en obtener un acceso inicial, y dejaremos el escalamiento de privilegios para después.
Con esto en mente, debemos tener en cuenta que muchas organizaciones utilizan patrones para la creación de sus usuarios, por ejemplo
- nombre.apellido@compañia.com
- nombre.apellido.primera_letra_de_segundo_apellido@compañia.com
Si ya hemos recopilado información de fuentes públicas sobre la organización, podría servirnos probar combinaciones de nombres y apellidos, y validar que existan en Azure AD. Pero, ¿cómo hacemos esto?
Consulta a las URLs públicas de Microsoft
Microsoft cuenta con endpoints que pueden ser consultados de manera pública, que nos ayudarán a validar si un usuario existe y está activo en un directorio de Azure.
Lo primero es validar si el dominio es válido y existe un tenant en Azure configurado, para ello, haremos una petición GET a la siguiente URL:
https://login.microsoftonline.com/GetUserRealm.srf?login=[cuenta a validar]

El cuerpo de la respuesta nos ayudará a determinar si vamos por buen camino:
- Si el resultado indica que el NameSpaceType es «Managed», el tenant existe y probablemente la cuenta también
- Si el resultado indica que el NameSpaceType es «Unknown», el tenant no existe, por tanto, nuestra cuenta no existe.

Entonces, ¿porqué solo decimos que la cuenta «probablemente» exista en el primer escenario?. Porque este endpoint no comprueba la existencia de la cuenta como tal, veamos que sucede si ponemos una cuenta inexistente en el AD:

El resultado es igual al primer caso.
Para poder determinar si la cuenta existe, apuntemos a este recurso:
https://login.microsoftonline.com/common/GetCredentialType
Esta vez, haremos una petición de tipo POST, agregando en el body la estructura de consulta: {«username»:»[Cuenta a validar]»}. Para nuestro caso ejemplo, será: {«username»:»[email protected]»}

La respuesta es un poco más larga, pero ahora nos concentraremos en el parámetro IfExistsResult, si este valor está en 0, podemos asumir que la cuenta existe. Veamos que sucede cuando le pasamos una cuenta inexistente:

El parámetro cambia a «1», por lo que podemos asumir que esta cuenta no existe.
Hay algunos casos excepcionales en donde la respuesta podría causar confusión, como cuando la cuenta tiene SSO habilitado, pero esto lo dejaremos de lado. El objetivo es tener el mayor grado de certeza de que la cuenta es válida, para poder construir nuestra lista de cuentas.
Un aspecto a tener en cuenta, es que estos endpoints también nos sirven para validar si un usuario externo existe. En algunos entornos, suelen existir usuarios externos al dominio, cuyo formato es el siguiente:
nombredeusuario_correopublico_com#EXT#@midominio.com
Comprometiendo credenciales
Ahora que tengo una lista de cuentas válidas, el siguiente paso es tratar de obtener las contraseñas. Para ello podemos usar técnicas de OSINT (por ejemplo, en repositorios de Github públicos o en DataLeaks públicos) o escaneando cuentas de almacenamiento que tengan contenido expuesto.
Sin embargo, si nada de esto funciona, podemos realizar algunas de las siguientes técnicas:
1) Fuerza bruta: Esta técnica es la menos recomendada. Consiste en utilizar una herramienta que nos permita automatizar la petición de inicio de sesión, haciendo uso de una lista de muchas contraseñas. ¿Por qué no la recomiendo?: Porque en un entorno real, existen políticas de bloqueo ante intentos fallidos para cuentas de Azure AD, por lo que nuestra herramienta fallará al tercer, quinto, o décimo intento (dependiendo de la configuración de la política), y nuestro usuario objetivo se bloqueará. Esto solo levantará la alerta de un ataque y nuestro proceso no podrá continuar.
2) Password Spraying: Esta técnica es útil. A diferencia de la fuerza bruta, en este escenario, solo tomamos una contraseña, y lo que iteramos son las cuentas obtenidas, de tal manera que cada cuenta solo tenga un solo intento fallido, o dos como máximo, así no causamos el bloqueo de las cuentas. La parte complicada está en predecir una contraseña válida.
Si existe una cultura robusta de ciberseguridad en la organización en la que estamos haciendo las pruebas, nos costará dar con una contraseña útil, sin embargo, en el caso contrario, podemos inferir que habrá usuarios que utilizarán contraseñas sencillas de recordar como:
- Miempresa2022$ [y lo que cambia es el año]
- Miempresa.2022.5 [año y mes]
En ambos casos, la contraseña está cumpliendo con las políticas de seguridad más usuales: 1 mayúscula, 1 número, 1 caracter especial y una longitud mayor a 8 caracteres.
Entonces, ¿Cómo puedo automatizar las pruebas de Password Spraying?
Para eso utilizaremos la herrramienta MSOLSpray, la cual podemos descargar desde aquí: https://github.com/dafthack/MSOLSpray.
Una vez instalado, la ejecutamos en Powershell:
Import-Module .\MSOLSpray.ps1
Invoke-MSOLSpray -UserList .\userlist.txt -Password Mi3mpresa2022$$
Solo debes reemplazar el archivo userlist.txt por tu propia lista con usuarios válidos y el password por un valor que hayas inferido como válido.

La imagen nos muestra como de una lista de 4 usuarios válidos, hemos encontrado una cuya contraseña es Mi3mpresa2022$$
Voilà! tenemos una credencial válida.
3) Ingeniería social: Este tipo de escenario, aunque es más complejo ya que depende en parte del desconocimiento o confusión del usuario, también es útil, ya que nos permitirá obtener una credencial que probablemente no responda a ningún patrón predecible.
Una herramienta muy útil para realizar ataques de ingeniería social, es Evilginx2, la cual pueden encontrar aquí: https://github.com/kgretzky/evilginx2. Aunque configurarla puede ser un poco engorroso, una vez que tengamos preparado el entorno, lo demás ya solo depende de la forma de engaño al usuario víctima.
Si ya tenemos nuestro entorno preparado, lo siguiente es activar el phislet de o365, y luego nuestro lure que utilizaremos para enviárselo a nuestro usuario:


Una vez hecho esto, compartiremos el enlace con la victima. Este enlace, que en nuestro caso ejemplo es https://login.demo.labitacoradelhacker.com/wenezeck, mostrará automáticamente la pantalla de login de Microsoft:

Veremos que el sitio dispone de un certificado SSL, lo que evitará que el usuario tenga mensajes de alerta por certificados no confiables en su navegador.

Una vez que el usuario coloque su contraseña, podremos capturarla en nuestro entorno de Evilginx2

Voilà! tenemos credenciales de un usuario válido.
Estas tres técnicas nos pueden servir para conseguir credenciales válidas, sin embargo, como dijimos antes, utilizar fuerza bruta no es recomendable.
Cuentas con MFA habilitado
Una pregunta que podría surgir es: ¿Qué sucede si la cuenta que he obtenido tiene el MFA habilitado?
En este caso, la sugerencia es validar antes si existe algún servicio configurado que no necesite el MFA para nuestra cuenta. Esta validación la podemos hacer usando MFASweep, una herramienta que podrás encontrar aquí: https://github.com/dafthack/MFASweep. Para usarla solo debes ejecutar el siguiente comando:
PS C:\> Import-Module .\MFASweep.ps1
PS C:\> Invoke-MFASweep -Username [cuenta válida] -Password [Password encontrado]
La herramienta validará varios servicios de Microsoft, y te indicará si alguno de ellos permite el acceso sin MFA.

Otra opción, es utilizar Evilginx2, capturando la cookie de sesión. En este caso, cuando el usuario ingrese el OTP, la herramienta nos capturará el token que reemplazaremos en nuestro navegador, consiguiendo un acceso temporal (recordemos que este token tendrá un tiempo de vida).





Así, aunque el usuario tenga activo el MFA, podemos conseguir acceso.
Y esto ha sido todo en este post. Por ahora dejaremos el tema aquí, y en la siguiente entrada veremos algunas técnicas para obtener información de la cuenta, ya que hemos conseguido acceso.