In 2018, Duo Security found a new vulnerability class that affects SAML-based single sign-on (SSO) systems and this led to the following vulnerabilities being disclosed: CVE-2017-11427, CVE-2017-11428, CVE-2017-11429, CVE-2017-11430, CVE-2018-0489, CVE-2018-7340.

From a specially crafted <SAMLResponse> file, an attacker having already access to the SAML system with his own account can bypass the authentication mechanism and be authenticated as another user.

This is due to the fact that SAML protocol rely on XML format and how the underlying XML parser interprets XML comments.

If an attacker manage to change the <NameID> field identifying the authenticated user with XML comments, he can exploit the vulnerability.

Here is an example of a potential payload:

<SAMLResponse>
  [...]
  <Subject>
    <NameID>admin@domain.com<!---->.evil.com</NameID>
  </Subject>
  [...]
</SAMLResponse>

The attacker will manage to generate a valid <SAMLResponse> content with the account "admin@domain.com.evil.com". He will modify it with XML comments to finally be authenticated as "admin@domain.com". To prevent this vulnerability on application using Spring Security SAML relying on OpenSAML2, XML comments should be ignored thanks to the property ignoreComments set to true.

Noncompliant Code Example

import org.opensaml.xml.parse.BasicParserPool;
import org.opensaml.xml.parse.ParserPool;
import org.opensaml.xml.parse.StaticBasicParserPool;

public ParserPool parserPool() {
  StaticBasicParserPool staticBasicParserPool = new StaticBasicParserPool();
  staticBasicParserPool.setIgnoreComments(false); // Noncompliant: comments are not ignored during parsing opening the door to exploit the vulnerability
  return staticBasicParserPool;
}
public ParserPool parserPool() {
  BasicParserPool basicParserPool = new BasicParserPool();
  basicParserPool.setIgnoreComments(false); // Noncompliant
  return basicParserPool;
}

Compliant Solution

public ParserPool parserPool() {
  return new StaticBasicParserPool(); // Compliant: "ignoreComments" is set to "true" in StaticBasicParserPool constructor
}
public ParserPool parserPool() {
  return new BasicParserPool();  // Compliant: "ignoreComments" is set to "true" in BasicParserPool constructor
}

See