SAML 101
by Devang-Solanki
Before diving deep into SAML we must understand Single Sign-On is.
What Is Single Sign-On
Single sign-on is a method of logging in that lets a user enter in their login credentials (usually a username and password) just once and automatically be logged into multiple websites or applications.
What is SAML
SAML stands for Security Assertion Markup Language. It is a standard commonly used Single Sign-On (SSO). It is an XML-based open-standard for transferring identity data or authorization credentials between two parties: an identity provider (IdP) and a service provider (SP).
Identity Provider (IDP) — Performs authentication and passes the user’s identity and authorization level to the service provider.
Service Provider (SP) — Trusts the identity provider and authorizes the given user to access the requested resource.
Example :- Suppose you want to use Gmail, Hangouts and Google Docs we can call them service provider. Sigining into all of them separately and remmebering passwords for all of them seems very annoying. So, to solve this problem we will use SAML. Where we will only provide credentials to one Identity Provider in this case it would be Google and that IDP will allow us to login into Gmail, Hangouts and Google Docs without providing any credentials to them.
SAML implements a secure method of passing user authentications and authorizations between the identity provider and service providers. When a user logs into a SAML enabled application, the service provider requests authorization from the appropriate identity provider. The identity provider authenticates the user’s credentials and then returns the authorization for the user to the service provider, and the user is now able to use the application.
SAML messages are base64 encoded but that is easily decoded to view the message contents. The two most common areas in SAML messages that are prone to tampering are signatures and assertions. The signature enforces the trust relationship between the IP and SP. The assertion instructs the SP on what trusted operations to perform, usually to allow you to access the application as a certain user.
Basic SAML Terminology
- SAML Request - Also known as an authentication request, is generated by the Service Provider to “request” an authentication.
- SAML Response - It is generated by the Identity Provider. It contains the actual assertion of the authenticated user. In addition, a SAML Response may contain additional information, such as user profile information and group/role information, depending on what the Service Provider can support.
- Assertion - It is an XML document that has the details of the user which we’ve been discussing is transmitted from IDP to SP. This contains the timestamp of the user login event and the method of authentication used (eg. 2 Factor Authentication, Kerberos, etc.). Once an identity provider has determined that you are who you say you are and have the right to access the content or services you’re interested in, it sends a SAML assertion to the server that actually can actually provide those services to you.
- XML Signature (DSig) – It is a Base64 encoded string which protects the integrity of the assertion. (If an attacker tries to change the username in the assertion to the victim’s username, the signature will prevent the hacker from logging in as the user).
- Assertion Consumer Service (ACS) - The URL location where the SAML assertion is sent. Basically ACS is the location at a ServiceProvider that accepts SAML response message. This endpoint responsible for receiving SMAL response from the IDP and checking the assertions signatures and vaildating the entire document.
- Attributes - This contains the information about the user such as their first name, last name or any other information might required for identifying the user. The number of and format of attributes can vary greatly. There’s usually at least one attribute, the nameID, which is typically the username of the user trying to log in.
- RelayState - This tells the SP where to take the user once they’ve successfully logged in. It is also used to remmeber where the user was before he/she started authentication process.
- A Service Provider Initiated (SP-initiated) sign-in describes the SAML sign-in flow when initiated by the Service Provider as shown in the diagram. This is typically triggered when the end user tries to access a resource or sign in directly on the Service Provider side, such as when the browser tries to access a protected resource on the Service Provider side.
- An Identity Provider Initiated (IdP-initiated) sign-in describes the SAML sign-in flow initiated by the Identity Provider. Instead of the SAML flow being triggered by a redirection from the Service Provider, in this flow the Identity Provider initiates a SAML Response that is redirected to the Service Provider to assert the user’s identity.
SAML Authentication Workflow
At a basic level, a successful Service Provider Initiated SAML flow occurs as follows:
- The user (e.g. devang@example.com) navigates to the SP’s login page and begins to log in. Some SPs offer a link to “sign in using SSO” on the login page (e.g. hackerone). The service provider checks to see if you’re already authenticated within the system. If you are, you skip to step 7; if you’re not, the service provider starts the authentication process.
- The SP then generates a SAML request and redirects the user to the appropriate IDP.
- Once the user is redirected to IDP they’ll need to enter their credentials, unless they had already authenticated into IDP in a previous session within the same browser.
- On successful authentication request IDP will redirect the user back to the SP’s Assertion Consumer Service (ACS) with an SAML response from IDP containing the authentication information needed by the service provider.
- After the response is successfully processed by the SP, the user will logs you in. After this user will be redirected to SP’s default relay state.
SAML Request
An AuthnRequest is sent by the Service Provider to the Identity Provider in the SP-initiated flow.
SAML REQUEST EXAMPLE
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="ONELOGIN_809707f0030a5d00620c9d9df97f627afe9dcc24" Version="2.0" ProviderName="SP test" IssueInstant="2014-07-16T23:52:45Z" Destination="http://idp.example.com/SSOService.php" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="http://sp.example.com/demo1/index.php?acs">
<saml:Issuer>http://sp.example.com/demo1/metadata.php</saml:Issuer>
<samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="true"/>
<samlp:RequestedAuthnContext Comparison="exact">
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
</samlp:RequestedAuthnContext>
</samlp:AuthnRequest>
In SAML request the ID ID="ONELOGIN_809707f0030a5d00620c9d9df97f627afe9dcc24"
is generated by SP and the IDP will respond to this ID within it’s SAML response. SAML request contains Destination value Destination="http://idp.example.com/SSOService.php"
that points to IDP and also helps ensure IDP that its the intended recipient of SAML request. The ACS AssertionConsumerServiceURL="http://sp.example.com/demo1/index.php?acs"
tells the IDP that where the SP accept the SAML response.
SAML Response
A SAML Response is generated by the Identity Provider. It contains the actual assertion of the authenticated user.
SAML RESPONSE EXAMPLE
<?xml version="1.0"?>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="pfx3572f7e6-48ee-b750-7939-5475435beb62" Version="2.0" IssueInstant="2014-07-17T01:01:48Z" Destination="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_809707f0030a5d00620c9d9df97f627afe9dcc24">
<saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#pfx3572f7e6-48ee-b750-7939-5475435beb62"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>F0yFi+7QJVS4HaAFEk5WSOxnyUQ=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>OrwZ2o/uROEvTujoyRnV58Q6Q4NtUoYOsB0zPh09QrJkMGcXREQG+1GvT+YDDCdgyq6Z895QyVm9fS0rKv19eUd8Uh+Nbsx3VirsSAvVR77vyOmCZrpdNFE4A2xRG7jcIl/2JDeN9dFNuh1nNdyX1e7qJIaWutL3o/LJIx8SR2o=</ds:SignatureValue>
<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICajCCAdOgAwIBAgIBADANBgkqhkiG9w0BAQ0FADBSMQswCQYDVQQGEwJ1czETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMT25lbG9naW4gSW5jMRcwFQYDVQQDDA5zcC5leGFtcGxlLmNvbTAeFw0xNDA3MTcxNDEyNTZaFw0xNTA3MTcxNDEyNTZaMFIxCzAJBgNVBAYTAnVzMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQKDAxPbmVsb2dpbiBJbmMxFzAVBgNVBAMMDnNwLmV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZx+ON4IUoIWxgukTb1tOiX3bMYzYQiwWPUNMp+Fq82xoNogso2bykZG0yiJm5o8zv/sd6pGouayMgkx/2FSOdc36T0jGbCHuRSbtia0PEzNIRtmViMrt3AeoWBidRXmZsxCNLwgIV6dn2WpuE5Az0bHgpZnQxTKFek0BMKU/d8wIDAQABo1AwTjAdBgNVHQ4EFgQUGHxYqZYyX7cTxKVODVgZwSTdCnwwHwYDVR0jBBgwFoAUGHxYqZYyX7cTxKVODVgZwSTdCnwwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQ0FAAOBgQByFOl+hMFICbd3DJfnp2Rgd/dqttsZG/tyhILWvErbio/DEe98mXpowhTkC04ENprOyXi7ZbUqiicF89uAGyt1oqgTUCD1VsLahqIcmrzgumNyTwLGWo17WDAa1/usDhetWAMhgzF/Cnf5ek0nK00m0YZGyc4LzgD0CROMASTWNg==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="pfx19d38796-12f1-c9b0-edd4-73c3f560f99a" Version="2.0" IssueInstant="2014-07-17T01:01:48Z">
<saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#pfx19d38796-12f1-c9b0-edd4-73c3f560f99a"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>W6keCv1rK7ZsH68VuoSrfF1Abvo=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>pmf6u8mZyxKlDOe1Idf8MGF/w4Ky2NC1Q16fISLjvb+t1+lnX7g4L9B/v0xnJ2Mskyuyr2yWCf6MBzYGgeu0fS4iRtX7LjOTgYVOjUdEbHWZrYt69c/Kyl/RM/B4/Po5bi6HmXM4pbTWCxwZYhhO/Szhsa1N7zIlqp0eG3fuucw=</ds:SignatureValue>
<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICajCCAdOgAwIBAgIBADANBgkqhkiG9w0BAQ0FADBSMQswCQYDVQQGEwJ1czETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMT25lbG9naW4gSW5jMRcwFQYDVQQDDA5zcC5leGFtcGxlLmNvbTAeFw0xNDA3MTcxNDEyNTZaFw0xNTA3MTcxNDEyNTZaMFIxCzAJBgNVBAYTAnVzMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQKDAxPbmVsb2dpbiBJbmMxFzAVBgNVBAMMDnNwLmV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZx+ON4IUoIWxgukTb1tOiX3bMYzYQiwWPUNMp+Fq82xoNogso2bykZG0yiJm5o8zv/sd6pGouayMgkx/2FSOdc36T0jGbCHuRSbtia0PEzNIRtmViMrt3AeoWBidRXmZsxCNLwgIV6dn2WpuE5Az0bHgpZnQxTKFek0BMKU/d8wIDAQABo1AwTjAdBgNVHQ4EFgQUGHxYqZYyX7cTxKVODVgZwSTdCnwwHwYDVR0jBBgwFoAUGHxYqZYyX7cTxKVODVgZwSTdCnwwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQ0FAAOBgQByFOl+hMFICbd3DJfnp2Rgd/dqttsZG/tyhILWvErbio/DEe98mXpowhTkC04ENprOyXi7ZbUqiicF89uAGyt1oqgTUCD1VsLahqIcmrzgumNyTwLGWo17WDAa1/usDhetWAMhgzF/Cnf5ek0nK00m0YZGyc4LzgD0CROMASTWNg==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature>
<saml:Subject>
<saml:NameID SPNameQualifier="http://sp.example.com/demo1/metadata.php" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">devang@user.com</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2024-01-18T06:21:48Z" Recipient="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_809707f0030a5d00620c9d9df97f627afe9dcc24"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2014-07-17T01:01:18Z" NotOnOrAfter="2024-01-18T06:21:48Z">
<saml:AudienceRestriction>
<saml:Audience>http://sp.example.com/demo1/metadata.php</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2014-07-17T01:01:48Z" SessionNotOnOrAfter="2024-07-17T09:01:48Z" SessionIndex="_be9967abd904ddcae3c0eb4189adbe3f71e327cf93">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">test</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">test@example.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">users</saml:AttributeValue>
<saml:AttributeValue xsi:type="xs:string">examplerole1</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>
Notice in SAML response we have Destination="http://sp.example.com/demo1/index.php?acs
and InResponseTo="ONELOGIN_809707f0030a5d00620c9d9df97f627afe9dcc24"
which matches to ID="ONELOGIN_809707f0030a5d00620c9d9df97f627afe9dcc24"
and AssertionConsumerServiceURL="http://sp.example.com/demo1/index.php?acs"
this helps us verify that this SAML response is generated in response to the SAML request we made. We have multiple assertion within the SAML respone which are all signed using some alogrithim which we can identify using <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
this tag. The <ds:KeyInfo>
tag has public key which the IDP used to sign asserstion to protect its integrity. The signed asserstion is then Base64 encoded and stored into the <ds:DigestValue>
tag.
In this SAML response we have a subject <saml:Subject>
this is in refernece to user sigining in to SP. The subject contains a nameID <saml:NameID SPNameQualifier="http://sp.example.com/demo1/metadata.php" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">devang@user.com</saml:NameID>
which helps to uniquely indentify the user.
At last we have the conditions <saml:Conditions NotBefore="2014-07-17T01:01:18Z" NotOnOrAfter="2024-01-18T06:21:48Z">
which give us timestamps that this response is valid in the time frame window from NotBefore="2014-07-17T01:01:18Z"
to NotOnOrAfter="2024-01-18T06:21:48Z
Weak Points
SAML might be complex, but it can be secure if properly impelmented. Lets look at some mistake that could lead to disaster.
Flawed Validation
Message Expiration
SAML messages should contain a timestamp of when the request was issued, when it expires or both. If the SAML message never expires a malicious user could capture the SAML response and reuse it. Check the message for timestamps, such as an IssueInstant or NotOnOrAfter assertion.
SAML Response Forwarding
An application should only accept a SAML response intended for the SP application. If the application does not perform this check, malicous user could pass a valid SAML response genrated for an application to another application and allow it to login. The malicous user can get a valid login for application and record it then the user can replay the same message to another application which uses the same IP and login to the that SP application.
Flawed Signature Validation Mechanisim
The SAML authentication mechanism relies on signature for maintaing its intergrity and if they are not properly implemented this can leads to authentication bypass or account takeover.
Signature is not verified
If the ACS is not verifying the signature or not checking if its exist in SAML response a malicous user could try removing the signature value from the SAML response. By simply emptying the signature field or removing the field entirely malicious user can bypass security checks.
Signature is only verified if it exist
Sometimes service provider only verify the signature if it is present in the SAML response. If it’s not being provided, in that case ACS simply skips the validation.
Flawed XML Parsers
The service provider processes the SAML response which is basicaly a XML document hence vulnerbilty exist in XML also exist in SAML such as XXE.
XML Comment Injection
XML can be quite complicated. Diffrent XML parsers parses XML diffrently. For example take this two xml tag mentioned below
<email>devangsolanki@gamil.com</email>
<email>devangsolanki@gamil.com<!-- Here lies the problem --></email>
Seems diffrent right?
Let’s see what we get when we parsed both the xml and gets it element tree
First Case:
element: email
|_ text: devangsolanki@gamil.com
Second Case:
NameID
|_ Text: devangsolanki@gamil.com
|_ Comment: Here lies the problem
|_ Text: .evil.com
In second case the comment tricked the XML parser into stoping at that comment and the service provider would thought the user was just devangsolanki@gamil.com beacuse it failed to notice .evil.com.
A malicious user could leverage this problem and can create a account very similar to a admin account like admin@business.com.evil.co and can modify SAML assertions to change the NameID to admin@business.com when processed by the SP. By adding simple comment into the SAML response malicous user can now access admin account with this simple payload
<SAMLResponse>
<Issuer>https://idp.com/</Issuer>
<Assertion ID="_id1234">
<Subject>
<NameID>admin@business.com<!---->.evil.co/NameID>
</Subject>
</Assertion>
<Signature>
<SignedInfo>
<CanonicalizationMethod Algorithm="xml-c14n11"/>
<Reference URI="#_id1234"/>
</SignedInfo>
<SignatureValue>
some base64 data that represents the signature of the assertion
</SignatureValue>
</Signature>
</SAMLResponse>
XML Signature Wrapping Attack
Some implementations check for a valid signature and match it to a valid assertion, but do not check for multiple assertions, multiple signatures, or behave differently depending on the order of assertions. A malicous user can malformed a SAML message which contains one signed asseertion and a second unsigned assertion formed by user. When this SAML message is forwarded to Assertion Consumer Service depending on XML Parser it will validate the signed assertion but will process the unsigned malicious assertion. This could also allow a malicous user to bloat a XML document and ddos Assertion Consumer Service.
Best Practices
- Limit the XML parser as much as possible when implementing Assertion Consumer Service. Disabling Document Type Defination Fetching (DTD) which will protect againts XEE (XML External Entities Attacks).
- Use Canonicalized XML to normalize XML via specified algorithims.
- Validate the schema of the XML within the SAML response which will prevent from adding arbitary data outside the signature which eventually prevent Signature Wrapping Attacks.
- Validate every signature and every assertion should be signed.
- Reject partially signed responses.
- Limit accepted encryption algorithms.
- Use only strong encryption al.gorithms.
- Validate Destination and AssertionConsumerServiceURL so that when the IDP sends the response it only get accepted to the intended service provider.
- Enforce Validation window so that no no saml reponse get accpted outside the mentioned time window.