---
# System prepended metadata

title: SAML

---

# SAML

# Introducción
Esta aplicación permite comprender mejor SAML y aprender cómo descubrir, explotar y remediar las vulnerabilidades asociadas con las implementaciones.

# Trasfondo
Para este escenario somos Yogi Bear. El personal del parque JellyStone ya está harto de nuestro robo de cestas de picnic. En un esfuerzo por rastrear este comportamiento, han configurado la "Aplicación Saml de Yogi". Esta aplicación permite a los visitantes del parque presentar quejas sobre nuestro comportamiento.

Nuestro objetivo como Yogi es obtener acceso administrativo a la aplicación a través de errores de implementación de SAML y eliminar las quejas. Si fallamos, existe la posibilidad de que nos reubiquen en otro parque sin canastas de picnic.

# SAML: Qué es
Según RFC7522, "el Security Assertion Markup Language (SAML) 2.0 es un marco basado en XML que permite que la información de identidad y seguridad se comparta entre dominios de seguridad". En pocas palabras, SAML proporciona una manera de decirle a una aplicación web que eres quien dices ser sin tener que mantener una base de datos de usuario / contraseña dentro de cada aplicación web a la que acceden los usuarios. En cambio, la autenticación se realiza en un proveedor de identidad de confianza (IDP) y la autorización se deja a la aplicación web a la que las personas intentan acceder una vez que se autentican con el IDP.

Términos:
* **Proveedor de identidad (IDP)**: este es el servidor que maneja la autenticación. En el entorno de prueba a continuación, el IDP es el "IDP de Jellystone". Esta es la plataforma en la que demuestra que es quien dice ser. Un IDP puede tener conexiones de back-end a AD, o podría cotejar con otra base de datos de usuarios. Los desplazados internos también pueden ayudar a implementar fácilmente la autenticación multifactor. Eliminando la carga del desarrollador de la aplicación.
* **Proveedor de servicios (SP)**: esta es la aplicación a la que un usuario intenta acceder. En el caso del ejemplo siguiente, el SP es 'Aplicación SAML de Yogi'.
* **Cliente**: Este es usted. Un cliente es cualquier persona o cualquier cosa que esté enviando una solicitud al SP.

# SAML: Cómo funciona
SAML tiene un par de flujos de autenticación diferentes, el flujo iniciado por IDP y el flujo iniciado por el proveedor de servicios. Una vez que el usuario llega al IDP, los flujos son básicamente los mismos. Para este artículo, nos centraremos en el flujo iniciado por el proveedor de servicios. Al mirar la imagen de abajo, podemos ver tres pasos de alto nivel para este flujo.
![](https://i.imgur.com/ZsdYQ1M.png)
Analicemos estos:
1. En este paso, el usuario navega hasta la aplicación web (proveedor de servicios) y selecciona el botón de inicio de sesión.
2. La aplicación web envía la solicitud SAML al navegador y la redirige al IDP. El navegador transmite la solicitud al IDP. El IDP solicita al usuario que se autentique. Con los requisitos definidos. Esto podría ser un nombre de usuario / contraseña, MFA, ambos, etc.
3. Una vez que el usuario demuestra que es quien dice ser, el IDP genera una afirmación SAML, la envía de vuelta al navegador y lo redirige al proveedor de servicios. El proveedor de servicios confirma que el usuario debe tener acceso a la aplicación y le otorga acceso a los recursos a los que puede acceder.

Los mensajes de afirmación que se proporcionan al proveedor de servicios son lo más importante para proteger. Esto se puede hacer configurando el proveedor de servicios para confirmar que los mensajes del IDP que se transmiten a través del usuario están firmados y son válidos. La mayoría de las veces, aquí es donde surgen los problemas de seguridad.

Si los mensajes no están firmados, o están firmados pero no son válidos, la aplicación debe rechazarlos. Por ejemplo, los tres ataques siguientes deberían resultar en el rechazo de un mensaje de aserción:

* El atacante elimina la firma y edita el mensaje - Mensaje sin firmar
* El atacante deja la firma y edita el mensaje - Mensaje firmado pero no válido
* El atacante edita el mensaje y lo renuncia: mensaje / firma firmado pero no válido

# Despliegue
```
git clone https://github.com/yogisec/VulnerableSAMLApp.git
cd VulnerableSAMLApp
sudo docker-compose up
```
![](https://i.imgur.com/WAjjBL9.png)

# URLs de acceso
* Proveedor de servicios / Service Provider (SP): http://127.0.0.1:8000
* Proveedor de identidad / Identity Provider (IDP): http://127.0.0.1

# Credenciales de acceso
| Nombre de usuario | Contraseña | Descripción |
| -------- | -------- | -------- |
| yogi     | bear     | Cuenta de usuario básica, miembro del grupo 'usuarios'. Sin permisos especiales     |
| admin     | this-is-the-administrator-pasword-oh-no-is-that-a-typo-in-password     | Cuenta de administrador regular, miembro del grupo de administración. Esta cuenta tiene la capacidad de eliminar las quejas.     |
| brubble     | password     | Esta cuenta se registró específicamente para CVE-2017-11427     |
| instructor     | G0od-LuckGu3ssingThisButHeyItCouldHappenRight?     | Esta cuenta puede restablecer el tablero de quejas a su estado original. Además, esta cuenta tenía la capacidad de aumentar o disminuir la postura de seguridad de la aplicación.     |

# Vistazo general
1. Presionar "Login".
![](https://i.imgur.com/doDtlMS.png)

2. Iniciar sesión con las credenciales yogi:bear.
![](https://i.imgur.com/Yi1RIvH.png)

3. Comprobar el usuario y grupo actual.
![](https://i.imgur.com/4JbkQwz.png)

4. Ir a "Complaints".
![](https://i.imgur.com/fqBwNoy.png)
![](https://i.imgur.com/1qhHZ3f.png)

5. Cerrar sesión, iniciar sesión con las credenciales admin:this-is-the-administrator-pasword-oh-no-is-that-a-typo-in-password y comprobar que en "Complaints" se añade la funcionalidad "Delete".
![](https://i.imgur.com/HKfjuLV.png)

6. Cerrar sesión, iniciar sesión con las credenciales instructor:G0od-LuckGu3ssingThisButHeyItCouldHappenRight? y comprobar que en "Complaints" se añade la funcionalidad "Restore Complaints".
![](https://i.imgur.com/PU1GIeA.png)

7. Comprobar que la cuenta de instructor también tiene una nueva pestaña llamada "Saml Settings".
Dentro de esta pestaña podemos hacer que la aplicación sea más o menos segura marcando las funciones que queremos tener activadas o desactivadas.
![](https://i.imgur.com/PcWF8R0.png)

# Escenarios

| Configuración | Descripción |
| ------------- | ----------- |
| Nothing Configured | La aplicación acepta cualquier mensaje SAML, edítelo, la aplicación confía en todo. |
| Valid Assertion / Valid Messages | El proveedor de servicios está verificando afirmaciones válidas, cualquier manipulación da como resultado el rechazo del mensaje. A menos que eliminemos el bloque de firmas. |
| Want Assertions / Messages Signed | El proveedor de servicios requiere que los mensajes estén firmados, pero no comprueba si son firmas válidas. |
| Everything Signed, Everything Valid | Esta es la implementación ideal, los mensajes deben estar firmados y deben ser válidos, no se permite alteración. |
| CVE-2017-11427 | Esta es una implementación de CVE-2017-11427 que aprovecha los comentarios dentro del XML de respuesta SAML para evitar los controles de seguridad. |

Nota: Para toda la manipulación de mensajes SAML a continuación, estoy aprovechando el complemento SAML Raider para Burp. Maneja la decodificación de los mensajes sobre la marcha y permite editarlos. También admite ataques XSW que actualmente están fuera del alcance de esta aplicación.

Nota adicional: al cambiar de un escenario a otro, es mejor asegurarse de cerrar sesión antes de ajustar los niveles de seguridad del proveedor de servicios (SP). Esto ayuda a garantizar que no haya resultados imprevistos.

# Escenario 1: Nothing Configured (Nada configurado)
Este fallo de seguridad es uno de los más frecuentes de encontrar en SAML.

1. Establecer la Configuración de seguridad como muestra la siguiente imagen desde el usuario instructor.
![](https://i.imgur.com/BINAk2p.png)

2. Cerrar sesión, iniciar sesión con las credenciales yogi:bear e interceptar la respuesta SAML con Burp.
![](https://i.imgur.com/yme71rT.png)

3. Cambiar el grupo "users" por "administrators" y enviar la petición.
![](https://i.imgur.com/rvzYhGu.png)

4. Comprobar que el grupo actual es administrators.
![](https://i.imgur.com/pHHjYxK.png)

5. Comprobar que en la sección "Complaints" aparece la opción "Delete".
![](https://i.imgur.com/URxHhao.png)

Incluso podemos dar un paso más si queremos y reemplazar todos los campos dentro de la respuesta con información falsa similar a la imagen de abajo.
![](https://i.imgur.com/UHj8Ojn.png)

Los mensajes quedan totalmente vulnerables a cualquier persona que pueda autenticarse ante el IDP.


# Escenario 2: Valid Assertion / Valid Messages (Aserción válida / Mensaje válido)
1. Establecer la Configuración de seguridad como muestra la siguiente imagen desde el usuario instructor.
![](https://i.imgur.com/XcZxe1d.png)

2. Cerrar sesión, iniciar sesión con las credenciales yogi:bear e interceptar la respuesta SAML con Burp.
![](https://i.imgur.com/qFJOdO8.png)

3. Cambiar el grupo "users" por "administrators" y enviar la petición.
![](https://i.imgur.com/53rnXeA.png)

4. Comprobar que aparece un mensaje de error.
![](https://i.imgur.com/jWvBLqh.png)
El mensaje se rechaza porque no es válido en comparación con la firma del mensaje.

Hay una gran fallo de seguridad con esta configuración. El SP solo verifica que la aserción sea válida SI está firmada. La aplicación no tiene mensajes firmados como requisito. Si eliminamos todo el bloque signature de nuestro payload SAML, el mensaje se puede cambiar.

5. Interceptar la respuesta SAML. Presionar "Remove Signatures".
![](https://i.imgur.com/QFmzxWv.png)

6. Cambiar el grupo "users" por "administrators".
![](https://i.imgur.com/0nNF84a.png)

7. Comprobar que el grupo actual es "administrators".
![](https://i.imgur.com/IEgFHiD.png)


# Escenario 3: Valid Assertion / Valid Messages (Firmado y Válido)
1. Establecer la Configuración de seguridad como muestra la siguiente imagen desde el usuario instructor.
![](https://i.imgur.com/xOY8nIw.png)

2. Cerrar sesión, iniciar sesión con las credenciales yogi:bear e interceptar la respuesta SAML con Burp. Presionar "Remove Signatures".
![](https://i.imgur.com/jkRW056.png)

3. Cambiar el grupo "users" por "administrators" y enviar la petición.
![](https://i.imgur.com/ifC12qY.png)

4. Comprobar que aparece un mensaje de error.
![](https://i.imgur.com/l8jpTlt.png)

5. Ahora la firma no se borrará y solo se cambiarán los atributos de la aserción ("users" por "administrators").
![](https://i.imgur.com/zUIYyci.png)

6. Comprobar que el grupo actual es “administrators”.
![](https://i.imgur.com/nH7YA7L.png)

La aplicación en su configuración actual está verificando que haya atributos de firma dentro de la respuesta SAML y que esté firmada con el certificado de confianza. En realidad, no se trata de comprobar si son válidos o no. Si los elementos de la firma están en el mensaje, la aplicación asume que es legítimo y digno de confianza.

# Escenario 4: Everything Signed, Everything Valid (Todo firmado, Todo válido)
En esta configuración, el SP requiere que los mensajes estén firmados y que las firmas coincidan con los datos del mensaje general y la aserción. Esto significa que, como atacante, no podemos alterar las áreas del mensaje que se utilizan para calcular las firmas. Esto incluye los valores de los atributos dentro de la aserción. 

1. Establecer la Configuración de seguridad como muestra la siguiente imagen desde el usuario instructor.
![](https://i.imgur.com/aj4Roil.png)

2. Cerrar sesión. 
![](https://i.imgur.com/61huHlW.png)
Se producirá un error al intentar cerrar sesión después de un inicio de sesión válido. La solución actual es eliminar las cookies de sesión o reducir la configuración de seguridad de la aplicación eliminando el requisito de que los mensajes firmados completen el cierre de sesión.

3. Borrar todas las cookies actuales.
![](https://i.imgur.com/H6IEJ51.png)

4. Iniciar sesión con yogi:bear, eliminar la firma de la respuesta SAML y enviar la petición.
![](https://i.imgur.com/5VUTwwG.png)

5. Comprobar que aparece un mensaje de error. 
![](https://i.imgur.com/91PdQSB.png)
La aplicación está verificando si el mensaje está firmado.

6. Borrar todas las cookies.
![](https://i.imgur.com/2hh1Lw0.png)

7. Iniciar sesión con yogi:bear, dejar la firma pero cambiar los valores de los atributos ("users" por "administrators") y enviar la petición.
![](https://i.imgur.com/VfA2iNG.png)

8. Comprobar que aparece un mensaje de error.
![](https://i.imgur.com/QgPKcj9.png)
Esto se debe a que la aplicación está configurada para asegurarse de que los mensajes sean válidos si están firmados.

# Escenario 5: CVE-2017-11427
En un nivel alto, puede agregar un comentario en medio de la aserción XML para cambiar los atributos / valores de la respuesta SAML. La parte realmente perjudicial de esto es que, dependiendo de la biblioteca que se utilice, el comentario puede ignorarse durante el cálculo de la firma del mensaje. Entonces, para el SP, el mensaje sigue siendo válido.

1. Establecer la Configuración de seguridad como muestra la siguiente imagen desde el usuario instructor.
![](https://i.imgur.com/RGCtxdZ.png)

2. Cerrar sesión, iniciar sesión con las credenciales brubble:password.
![](https://i.imgur.com/VEOBrvb.png)
brubble tiene permisos de "usuario avanzado" dentro del Proveedor de servicios. No tiene derechos de administrador completos, por lo que no puede eliminar comentarios.
También, pertenece al grupo administratorsbutnot, este grupo cobrará importancia en los siguientes pasos.

3. Comprobar que brubble no puede eliminar quejas.
![](https://i.imgur.com/mbsmqWd.png)

4. Cerrar sesión, iniciar sesión con las credenciales brubble:password e interceptar la respuesta SAML con Burp. 
![](https://i.imgur.com/59TegjJ.png)

5. Modificar el grupo `administrators` por `administrators<!--butnot-->` y enviar la petición.
![](https://i.imgur.com/hZErhsr.png)

6. Ahora el grupo es administrators.
![](https://i.imgur.com/Fd3SS5n.png)

7. Comprobar que la funcionalidad de borrar quejas ya está disponible.
![](https://i.imgur.com/LqmQesQ.png)

# Otros ataques
* Message replays: donde un atacante envía un mensaje después de que su TTL ha expirado.

# Referencias
* https://github.com/yogisec/VulnerableSAMLApp
* https://jellyparks.com/web-things/vulnerable-saml-app.html
* https://jellyparks.com/web-things/saml-overview.html

# Ataques XSW
Toman fragmentos de la respuesta SAML, los duplican y los colocan en varios lugares dentro de la respuesta.

Van desde XSW1 a XSW8.

![](https://i.imgur.com/4ggtyHy.png)
Documento técnico bien explicado, el plugin SAML Raider se creó basándose en esta referencia: https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf

# Inyección de Comentarios I
`admin<!--test-->@ejemplo.es` se convierte en admin@ejemplo.es.

# Inyección de Comentarios II
`admin@ejemplo.es<!--test-->.sufijo` se convierte en admin@ejemplo.es. El comentario y lo que está a su derecha se ignora.

# Certificado falso
Cuando el proveedor de servicios (SP) no verifica la huella digital del certificado proporcionado en SAMLResponse para asegurarse de que el certificado sea de confianza.

1. Si hay una Firma incluida en la Respuesta, usar el botón "Send Certificate to SAML Raider Certificates".
![](https://i.imgur.com/E8eAGcJ.png)
2. Después de enviar el certificado, deberíamos ver un certificado importado en la pestaña Certificates de SAML Raider. Una vez allí, resaltamos el certificado importado y presionamos el botón "Save and Self-Sign".
![](https://i.imgur.com/TNz3BPR.png)
3. Al hacerlo, se genera un clon autofirmado del certificado original.
![](https://i.imgur.com/tdibQdo.png)
4. Ahora es el momento de volver a la solicitud interceptada que aún se mantiene en el Proxy de Burp. Luego usamos el botón "Remove Signatures" para eliminar las firmas existentes. 
![](https://i.imgur.com/bodi9HT.png)
5. Cambiamos el usuario por uno administrador.
![](https://i.imgur.com/DTF1PQm.png)
6. Seleccionamos el nuevo certificado autofirmado del menú desplegable de XML Signature Attacks. Finalmente, usamos el botón ""(Re-)Sign Message" o "(Re-)Sign Assertion" (el que sea más apropiado en cada situación).
![](https://i.imgur.com/VY37V2r.png)

# Reenvío de SAMLResponse
Consiste en pasar la SAMLResponse de un proveedor de servicios a otro proveedor de servicios.

Dado que el proveedor de servicios n.°2 no verifica el reclamo, tendremos que emitir un reclamo para el proveedor de servicios n.°1 y pasarlo al proveedor de servicios n.°2.

Para obtener un reclamo válido, necesitaremos alterar el SAMLRequest del Proveedor de servicios #1 y cambiar el valor de ServiceURL.

# Códigos Python
**saml1.py**
```python=
from urllib.parse import quote, unquote
from sys import argv
import base64

str = unquote(argv[1])
response = base64.b64decode(str.encode('ascii')).decode('ascii')

malicious_response = response.replace("prueba@prueba.es", "admin@libcurl.so")

print(quote(base64.b64encode(malicious_response.encode('ascii')).decode('ascii')))
```

**saml2.py**
```python
from urllib.parse import quote, unquote
from sys import argv
import base64
from re import sub

str = unquote(argv[1])
response = base64.b64decode(str.encode('ascii')).decode('ascii')

malicious_response = response.replace("prueba@prueba.es", "admin@libcurl.so")
without_signature = sub("<ds:SignatureValue>.*</ds:SignatureValue>", "<ds:SignatureValue></ds:SignatureValue>", malicious_response)
print(quote(base64.b64encode(without_signature.encode('ascii')).decode('ascii')))
```