Improper signature validation
XMLSecLibs is a library written that implements the xml-enc and xml-dsig W3C recommendations. It allows its users to handle encrypted and digitally signed XML documents. SimpleSAMLphp delegates encryption and signature handling to this library.
SimpleSAMLphp delegates creating and handling all SAML objects (messages, specific elements, etc) to a separate library called the SAML2 library (simplesamlphp/saml2). This library performs all kinds of validations, including the verification of XML signatures. Signature validation is in turn delegated to XMLSecLibs.
When verifying a signature, the API in XMLSecLibs mandates the creation of an
XMLSecurityKey object, which is built
depending on the algorithm the key is going to be used for. The key material is later loaded into the object, and it is
then ready to use to verify a given signature against that key.
XMLSecurityKey objects are always used regardless of
the algorithm associated with the key, and the library does not perform any checks on the type of key being loaded into
the object. This leads to a key confusion issue, where an
XMLSecurityKey object can be instantiated with a specific
algorithm, and key material that doesn’t correspond that particular algorithm. Additionally, since the API provides
common methods regardless of the algorithm, those methods may return different values depending on the underlying
backend used, which in turns depends on the algorithm.
The combination of these two factors came into play in the SAML2 library, effectively allowing a SAML message to be signed using the HMAC_SHA1 algorithm and the public key of a SAML2 entity as the secret material used for that algorithm. Obviously, a public key is intended to be public, and as such must always be considered in possession of an attacker.
In order to use the HTTP-Redirect SAML2 binding, the SAML2 library provides the
SAML2\HTTPRedirect class, which
is used by SimpleSAMLphp when a message is received using this binding in the Assertion Consumer Service endpoint
(note that this endpoint is always available, and if a binding is supported, then it can always be used: it is not
possible to switch off the use of a particular binding on an endpoint). The
SAML2\HTTPRedirect class provides a static
validateSignature() that extracts the relevant information from the query, and performs the verification
of the signature by calling the
verifySignature() method provided by
One of the arguments used to validate the signature is the algorithm, which is of course provided by the user. Since
multiple algorithms are supported for digital signatures in SAML2, the SAML2 library allows creating a key with the
right algorithm associated by means of the
SAML2\Utils\castKey() method. This method simply checks the algorithm used
in a given key (which defaults to RSA_SHA1), and if they don’t match, it instantiates a new
with the algorithm provided. We should stress again that the algorithm is provided by the user. Once a new key is
castKey() method loads the key material present in the given key into this new instance, assuming
the material is a public key.
XMLSecLibs version 1.3.3 added support for the HMAC_SHA1 algorithm in 2015. Therefore, since that version it was
possible then to call
castKey() with that algorithm, and get a
XMLSecurityKey object for that algorithm in return,
loaded with the public key of the SAML2 entity whose signature we want to verify. Of course, the HMAC_SHA1 algorithm
is a symmetric algorithm, meaning in order to verify the signature, the key material used must be secret. That given, it
is possible for an attacker to use the HMAC_SHA1 algorithm with that public key to generate a signature for a manually
crafted SAML assertion, and a SimpleSAMLphp instance receiving the message with the HTTP-Redirect binding will
consider it as a legitimate signature.
This issue was possible, to summarise, due to several facts concurring at the same time:
- The API provided by XMLSecLibs does not differentiate between keys for symmetric or asymmetric algorithms, or keys used for encryption or digital signatures.
- The assumption that all algorithms supported for digital signatures were asymmetric algorithms (HMAC_SHA1 is not).
- The lack of proper check of the value returned by
Had any of these requisites not been met, the issue would have been averted. A fix for the latter is in fact what
avoided this issue from being present in other bindings like HTTP-POST, as
verifySignature() returns the integer
when a public key algorithm is used and the signature is validated, as opposed to the boolean
true when the signature
is deemed valid by using the HMAC_SHA1 algorithm. This particular issue opens up for other kinds of side attacks
previously fixed in other places, like 201612-01, 201612-02 or 201612-03.
It has also been fixed in versions 3.1.4, 2.3.8 and 1.10.6 of the SAML2 library and in version 1.15.4 of SimpleSAMLphp.
A security advisory has been published for it with the identifier
Regarding the other two requisites, the first one implies a complete rewrite of the XMLSecLibs library, in order to offer separate programming interfaces depending on the use that can be made of a key and the type of key itself. We have been in contact with the author and maintainer of the library, but unfortunately the fix for this problem was deemed too complex to have in a reasonable time span, and it would also entail major changes for all code making use of this library.
The second requisite was fixed by introducing a whitelisting mechanism in the
effectively ensuring that only the supported RSA_SHA* algorithms can be used. This fix was introduced in versions
3.1.3, 2.3.7 and 1.10.5 of the SAML2 library, and in version 1.15.3 of SimpleSAMLphp, and it effectively tackles the
security issue regardless of the API provided by XMLSecLibs and the value returned by
All simplesamlphp/saml2 versions 0.x, 1.x, 2.x and 3.x are affected, up to (including) 1.10.4, 2.3.6 and 3.1.2.
All SimpleSAMLphp 1.14.x and 1.15.x versions are affected, up to (including) 1.15.2.
Other software using the
XMLSecLibs library might be affected by the same issue. Several vendors have been contacted,
and so far the following implementations have been verified to not be affected:
For a SimpleSAMLphp installed as an Identity Provider, an attacker may impersonate a Service Provider asking for authentication or to log a user out. Neither of both cases have important consequences.
When SimpleSAMLphp is installed as a Service Provider, attackers may manually craft a SAML2 assertion to their complete will, including altering, adding or removing attributes, changing the subject of the assertion, specifying higher levels of assurance in the authentication context, etc. The only requirement for that is the public key of the Identity Provider being impersonated. The Service Provider will validate the signature as legitimate, and assume the assertion comes from the Identity Provider and corresponds to a legitimate user that has been properly authenticated.
Upgrade to the latest versions of the SAML2 library.
For SimpleSAMLphp users, run
composer update or upgrade to SimpleSAMLphp 1.15.3.Refer to the documentation for
instructions on how to run composer.
This security issue was discovered during a security audit performed by Cure53 and reported on December 18, 2017.