PROBLEM
By default, Spring Security SAML’s SAMLBootstrap uses SHA1withRSA for signature algorithm and SHA-1 for digest algorithm.
@Configuration
@EnableWebSecurity
public abstract class AppSAMLConfig extends WebSecurityConfigurerAdapter {
...
@Bean
public static SAMLBootstrap SAMLBootstrap() {
return new SAMLBootstrap();
}
...
}
For example, the above configuration will generate the following SAML request payload when using HTTP-POST binding:-
<!--?xml version="1.0" encoding="UTF-8"?-->
<saml2p:authnrequest assertionconsumerserviceurl="https://server/app/saml/SSO" destination="https://adfs-server/adfs/ls/" forceauthn="true" id="a3bj4e05i70f6946gi85299i51i02a" ispassive="false" issueinstant="2016-02-23T15:10:26.414Z" protocolbinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
<saml2:issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://server/app/saml/metadata</saml2:issuer>
<ds:signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:signedinfo>
<ds:canonicalizationmethod algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ds:signaturemethod algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1">
<ds:reference uri="#a3bj4e05i70f6946gi85299i51i02a">
<ds:transforms>
<ds:transform algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature">
<ds:transform algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
</ds:transform></ds:transform></ds:transforms>
<ds:digestmethod algorithm="http://www.w3.org/2000/09/xmldsig#sha1">
<ds:digestvalue>u25hV7rk8hIpXYLJQs0aZjkueP0=</ds:digestvalue>
</ds:digestmethod></ds:reference>
</ds:signaturemethod></ds:canonicalizationmethod></ds:signedinfo>
<ds:signaturevalue>YDR9ybi...</ds:signaturevalue>
<ds:keyinfo>
<ds:x509data>
<ds:x509certificate>MIICxz...</ds:x509certificate>
</ds:x509data>
</ds:keyinfo>
</ds:signature>
<saml2p:requestedauthncontext comparison="exact">
<saml2:authncontextclassref xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:authncontextclassref>
</saml2p:requestedauthncontext>
</saml2p:authnrequest>
Unfortunately, SHA-1 is now deemed insecure due to “Freestart Collision” attack.
Further, most modern browsers have ceased to trust SHA-1 code signing certificates starting January 2016 and will eventually stop accepting these certificates by January 2017.
SOLUTION
To fix this, we could replace SHA-1 with stronger secure hash algorithm, such as SHA-256.
To do so, create a class that extends SAMLBootstrap that uses SHA256withRSA for signature algorithm and SHA-256 for digest algorithm.
public final class CustomSAMLBootstrap extends SAMLBootstrap {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
super.postProcessBeanFactory(beanFactory);
BasicSecurityConfiguration config = (BasicSecurityConfiguration) Configuration.getGlobalSecurityConfiguration();
config.registerSignatureAlgorithmURI("RSA", SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256);
}
}
Then, return CustomSAMLBootstrap instead of SAMLBootstrap
@Configuration
@EnableWebSecurity
public abstract class AppSAMLConfig extends WebSecurityConfigurerAdapter {
...
@Bean
public static SAMLBootstrap SAMLBootstrap() {
return new CustomSAMLBootstrap();
}
...
}
Now, the generated SAML request payload using HTTP-POST binding looks like this:-
<!--?xml version="1.0" encoding="UTF-8"?-->
<saml2p:authnrequest assertionconsumerserviceurl="https://server/app/saml/SSO" destination="https://adfs-server/adfs/ls/" forceauthn="true" id="a2e7f98agfaec7d253714fjdbcf8a83" ispassive="false" issueinstant="2016-02-23T15:18:43.452Z" protocolbinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
<saml2:issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://server/app/saml/metadata</saml2:issuer>
<ds:signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:signedinfo>
<ds:canonicalizationmethod algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ds:signaturemethod algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256">
<ds:reference uri="#a2e7f98agfaec7d253714fjdbcf8a83">
<ds:transforms>
<ds:transform algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature">
<ds:transform algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
</ds:transform></ds:transform></ds:transforms>
<ds:digestmethod algorithm="http://www.w3.org/2001/04/xmlenc#sha256">
<ds:digestvalue>w4qHFsBxFGifzemEJCYcuGOt+oZJ9N2DQM+Q2aEqJFI=</ds:digestvalue>
</ds:digestmethod></ds:reference>
</ds:signaturemethod></ds:canonicalizationmethod></ds:signedinfo>
<ds:signaturevalue>YDR9ybi...</ds:signaturevalue>
<ds:keyinfo>
<ds:x509data>
<ds:x509certificate>MIICxz...</ds:x509certificate>
</ds:x509data>
</ds:keyinfo>
</ds:signature>
<saml2p:requestedauthncontext comparison="exact">
<saml2:authncontextclassref xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:authncontextclassref>
</saml2p:requestedauthncontext>
</saml2p:authnrequest>
Leave a Reply