Skip to content

v2.15.0

Choose a tag to compare

@tngan tngan released this 20 Oct 09:29
· 10 commits to master since this release

Security release

2.15.0 fixes a batch of security issues in signature verification, response validation and message construction. All users should upgrade. Several checks are now on by default, so read the behaviour changes below before you deploy.

Fixed vulnerabilities

Advisory Severity Summary
GHSA-w8r9-gp23-wcxp Critical XML signatures were verified with a certificate from the message when the IdP metadata had no X.509 signing certificate (for example RSAKeyValue only). Only metadata-declared certificates are trusted now, and KeyDescriptor use is honoured.
GHSA-wxh7-j2vx-w63f High Login responses issued for another service provider were accepted. Audience, Destination and Recipient are now checked.
GHSA-wr2x-fh6q-q243 High On the Redirect and SimpleSign bindings, the detached signature was not bound to the message being parsed. The signed octet string must now carry the parsed message, SigAlg and RelayState.
GHSA-wj54-2vfp-35f2 High Missing InResponseTo and replay checks; an invalid message signature was ignored when the assertion signature verified; wantMessageSigned was not enforced. The bearer SubjectConfirmationData validity window was not enforced either.
GHSA-3427-gh8x-vv2c High Unbounded DEFLATE inflation on the Redirect binding (denial of service). Inflated messages are capped at 1 MB.
GHSA-963m-r92r-qm7c High XML comments could split extracted values, so samlify read a different value than the one signed. Element text is now read whole.
GHSA-fq9x-v53h-7w5p Medium XML injection through attribute metadata (name, nameFormat, valueXsiType, valueXmlnsXs, valueXmlnsXsi) in generated assertions. Template rendering is hardened, and a strict renderer is added. An encryption certificate from SP metadata is now validated before it is copied into the response.
GHSA-63ch-w8pw-4mf2 Medium Signature wrapping on signed LogoutRequest / AuthnRequest: the signature of an embedded assertion could authenticate the message, and a genuine signed message hidden in <Extensions> of a forged root was accepted. Requests and logout messages now need their own root signature, and every signature must cover the element that contains it (saml-core §5.4.2), with or without schema validation.
GHSA-3gg4-m4mq-vcxc Medium Assertions encrypted with RSA-1.5 key transport or TripleDES were decrypted. They are now refused before the private key is used.

Duplicate reports: GHSA-4g4q-xgjf-jcx5, GHSA-6gg9-3vvg-c3p4 and GHSA-p9hp-pg94-7847 (fixed with GHSA-wxh7-j2vx-w63f); GHSA-qwg3-7m52-ghg5 (fixed with GHSA-fq9x-v53h-7w5p).

Hardening

  • allowedSignatureAlgorithms (GHSA-59q7-p59f-fx9m): requestSignatureAlgorithm only selects the algorithm an entity signs with; it never restricted what it accepts. The new SP / IdP setting restricts accepted signature and digest algorithms on every binding, for example to refuse SHA-1. This was not exploitable: the sender chooses the algorithm, and changing it does not allow a forgery. Unset keeps today's behaviour.
  • Signature wrapping for encrypted assertions (GHSA-rq37-f3qr-mr59): we found no bypass on either decryption path. The new signature-placement and fail-on-invalid-signature checks harden both paths further.

Also update the schema validator. @authenio/xsd-schema-validator 0.7.4 (used by @authenio/samlify-xsd-schema-validator) fixes a crash: input the JVM rejected early could terminate the Node process with an unhandled EPIPE. Reinstall or update so that 0.7.4 or later is resolved (npm ls @authenio/xsd-schema-validator).

⚠️ Behaviour changes

Change Error Opt-out
Audience, Destination and Recipient are checked against the SP ERR_AUDIENCE_MISMATCH, ERR_RECIPIENT_MISMATCH wantAudienceCheck: false
Peer metadata must declare an X.509 signing certificate; a certificate in the message must match it NO_SELECTED_CERTIFICATE, ERROR_UNMATCH_CERTIFICATE_DECLARATION_IN_METADATA —
KeyDescriptor use is honoured; a descriptor without use serves both and logs a warning — —
Response@InResponseTo must agree with the signed SubjectConfirmationData@InResponseTo ERR_INRESPONSETO_MISMATCH —
A signature must be enveloped in the element it signs; signatures beside the element or covering only a child (such as <Issuer>) are rejected. Signatures made by samlify since 2.5.0 are not affected. ERR_POTENTIAL_WRAPPING_ATTACK —
Any invalid signature fails the message; wantMessageSigned: true requires a signed <Response> FAILED_TO_VERIFY_SIGNATURE, ERR_MISSING_MESSAGE_SIGNATURE —
Requests and logout messages must carry a signature on their root element FAILED_TO_VERIFY_SIGNATURE —
Element text that contains comments or CDATA is read whole — —
RSA-1.5 and TripleDES are refused on decryption ERR_INSECURE_ENCRYPTION_ALGORITHM allowInsecureDecryptionAlgorithms: true
Redirect / SimpleSign: octetString is required when the signature is checked, and must match the parsed message ERR_MISSING_OCTET_STRING, ERR_OCTET_STRING_MISMATCH —
Bearer SubjectConfirmation required; every bearer SubjectConfirmationData must be within its NotBefore / NotOnOrAfter window; an assertion with no NotOnOrAfter at all is rejected; every SessionNotOnOrAfter is checked ERR_SUBJECT_UNCONFIRMED, ERR_EXPIRED_SESSION —
inResponseTo passed as undefined / null (no pending request) rejects a response that answers a request; on POST an unsigned outer InResponseTo without a signed counterpart is rejected ERR_INRESPONSETO_MISMATCH omit the option
Metadata certificates must be base64; tagPrefix values must be XML names ERR_INVALID_CERTIFICATE, ERR_INVALID_TAG_PREFIX —
A message whose root element does not match the parser is rejected ERR_UNEXPECTED_MESSAGE_TYPE —
A LogoutRequest must come from the expected issuer; LogoutRequest / LogoutResponse Destination must be one of the receiver's SingleLogoutService locations; an expired LogoutRequest is rejected; with replayCache, a LogoutRequest is accepted once ERR_UNMATCH_ISSUER, ERR_RECIPIENT_MISMATCH, ERR_EXPIRED_REQUEST, ERR_REPLAYED_REQUEST wantAudienceCheck: false (Destination)
Input that is not well-formed XML, contains a DTD, or characters outside the XML range is rejected before schema validation ERR_INVALID_XML —
Redirect-binding messages are limited to 1 MB after inflation ERR_INFLATED_MESSAGE_TOO_LARGE —
{ and } in template values are written as &#123; / &#125; (the same text once parsed) — —

New features

  • sp.parseLoginResponse(idp, binding, request, { inResponseTo }) checks that the response answers a request you issued (one ID or an array).
  • allowUnsolicitedResponse: false on the SP rejects IdP-initiated responses (ERR_UNSOLICITED_RESPONSE).
  • replayCache: { saveIfAbsent(key, expiresAt) } on the SP rejects an assertion that was already accepted (ERR_REPLAYED_ASSERTION). samlify ships no store; plug in Redis, a database, or similar. (#639)
  • templateRenderer: 'strict' on the SP / IdP, and SamlLib.renderTemplate for customTagReplacement callbacks: a context-aware renderer that rejects placeholders in names, comments and other unsafe positions. See Migrating to the strict template renderer.
  • allowedSignatureAlgorithms on the SP / IdP.
  • Redirect / SimpleSign parse results include relayState, the RelayState covered by the signature. Detached signatures verify against every signing certificate in the peer's metadata (key rollover).
  • The extract now exposes assertionID, plus the signed SubjectConfirmationData and AudienceRestriction.

Deprecations

  • wantLogoutRequestSigned and wantLogoutResponseSigned default to false. Accepting an unsigned logout message now logs a warning. Both become true by default in v3; set them now if your peer signs logout messages.

  • SamlLib.replaceTagsByValue is hardened but deprecated, and will be removed in v3. Use SamlLib.renderTemplate. The strict renderer becomes the default in v3.

  • SignatureVerifierOptions.signatureAlgorithm is ignored. Use allowedSignatureAlgorithms.

Acknowledgements

Thank you to the security researchers who reported these issues and worked with us through coordinated disclosure:

GHSA-wr2x-fh6q-q243, the <Extensions> variant of GHSA-63ch-w8pw-4mf2, and the issues listed under behaviour changes that are not tied to an advisory were found while we validated these reports.

Fixes, tests and documentation by @tngan.

Full Changelog: v2.14.0...v2.15.0