CVE 2022-39299

A new vulnerability appeared last week, affecting a well-deployed npm package - Passport SAML. This package handles SAML-based authentication assertions generated by a SAML Identity Provider. SAML is itself very widely deployed, and identity providers offering SAML assertion-based authentication, for single signon within a domain of services, are everywhere (Microsoft ACtive Directory, Ping Federate, OKTA and others). Because of the model that SAML provides, however, SAML service providers (sometimes called relying parties) who rely on SAML assertions are even more widely deployed. For every identity provider, there are typically tens, hundreds or even thousands of service providers relying on these SAML assertions.

This bug involves the parsing and validation of the cryptographic signatures over XML documents, a very painful subject (for me personally, and a few others, so I understand), and what is implied by the presence or absence of a SAML assertion in a SAML response.

When an identity provider sends back a failed authentication message (with an error status code), it must (according to the SAML specification itself) NOT include a SAML assertion in the response. Additionally, the identity provider will typically sign the SAML response itself. So there is a usually-valid signature by a party that the SAML service provider trusts (has exchanged metadata with including X509 certificates and associated public keys), saying that an authentication failed, and there is no SAML assertion for the service provider to accept.

The semantics of this from a SAML perspective are clear - my trusted identity provider (trusted because they signed the message in a way I can verify) says authentication of the party currently trying to authenticate with me, failed, so I’m not giving you a SAML assertion about their authentication status.

The essence of this bug is that if a MITM between the identity provider and the service provider is able to obtain a signed SAML response containing an failed authentication response, they can add a SAML assertion into an XML document outside of the signed SAML response itself, which says that authentication succeeded.

There should be some problems with doing this:

  • The XML specification itself says that an XML document must contain only one “root” element. But an MITM can’t inject content inside the signed SAML response, so it must be added as an additional root element. Multiple root elements are illegal, so the document should fail basic validation/parsing, right? Wrong. But the reason why is complicated.

  • The injected SAML assertion comes along with an error status code, and is not signed by the identity provider. Shouldn’t the service provider code stop processing when it encounters the error status, and deny authentication? Shouldn’t the service provider validate that the assertion is covered by the signature of its trusted identity provider?