tag:blogger.com,1999:blog-7391783704166348052.post7158432912562490517..comments2024-03-15T22:26:58.542-07:00Comments on Open Source Security: Support for SAML2 assertions in WSS4J 1.6Colm O hEigeartaighhttp://www.blogger.com/profile/10711987281965801793noreply@blogger.comBlogger20125tag:blogger.com,1999:blog-7391783704166348052.post-87692590641238943472014-09-11T14:11:16.523-07:002014-09-11T14:11:16.523-07:00Thanks Colm. Your help with these issues is very m...Thanks Colm. Your help with these issues is very much appreciated.Anonymoushttps://www.blogger.com/profile/00589551294538912964noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-54950181665511481612014-09-11T09:18:32.341-07:002014-09-11T09:18:32.341-07:00For the record, I've fixed the first issue &qu...For the record, I've fixed the first issue "SignedElements" in WSS4J and tested that it's working with the latest CXF/WSS4J SNAPSHOTS: https://git-wip-us.apache.org/repos/asf?p=cxf.git;a=commit;h=b7a7916a3095578b70a6b9d9e8d0bd7a94e4d051<br /><br />I'll respond to your second point via a different channel...<br /><br />Colm.Colm O hEigeartaighhttps://www.blogger.com/profile/10711987281965801793noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-22686703690513960312014-09-09T17:34:44.424-07:002014-09-09T17:34:44.424-07:00In conclusion.
1. The issue I was having with the ...In conclusion.<br />1. The issue I was having with the inclusion of "SignedElements" was that I was not propery specifying the namespace. In order to specify this you need:<br /> <sp:SignedElements<br /> xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"><br /> <sp:XPath>//*[name()='saml2:Assertion']</sp:XPath><br /> </sp:SignedElements><br /><br />HOWEVER, that didn't work anyway because the WSS4J SamlAssertionValidator marks the SAML assertion as a unsigned supporting token (WSConstants.ST_UNSIGNED) and the CXF PolicyBasedWSS4JInInterceptor does not take these into account when verifying "SignedElements"<br /><br />2. I did figure out one way to make CXF check the SAML signature by including a "SignedSupportingTokens" policy in the "TransportBinding" policy:<br /><br /> <sp:TransportBinding<br /> xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"><br /> <wsp:Policy><br /> <sp:TransportToken><br /> <wsp:Policy><br /> <sp:SamlToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"><br /> <wsp:Policy><br /> <sp:WssSamlV20Token11 /><br /> </wsp:Policy><br /> </sp:SamlToken><br /> </wsp:Policy><br /> </sp:TransportToken><br /> … stuff here omitted for brevity …<br /> <sp:SignedSupportingTokens<br /> xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"><br /> <wsp:Policy><br /> <sp:SamlToken<br /> sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"><br /> <wsp:Policy><br /> <sp:WssSamlV20Token11 /><br /> </wsp:Policy><br /> </sp:SamlToken><br /> </wsp:Policy><br /> </sp:SignedSupportingTokens><br /> </wsp:Policy><br /> </sp:TransportBinding><br /><br />HOWEVER, while that forces CXF to check that the SAML assertion is signed, CXF ignores this verification because I am using TLS. Futhermore, CXF doesn't even care if I use a client certificate or not!<br /><br />Here's the offending code from org.apache.cxf.ws.security.wss4j.policyvalidators.AbstractSupportingTokenPolicyValidator:<br /><br /> private boolean isTLSInUse() {<br /> // See whether TLS is in use or not<br /> TLSSessionInfo tlsInfo = message.get(TLSSessionInfo.class);<br /> if (tlsInfo != null) {<br /> return true;<br /> }<br /> return false;<br /> }<br /><br />I would recommend, at the very least, that the code be modified to:<br /><br /> private boolean isTLSInUse() {<br /> // See whether TLS is in use or not<br /> TLSSessionInfo tlsInfo = message.get(TLSSessionInfo.class);<br /> if ( (tlsInfo != null) && (tlsInfo.getPeerCertificates() != null) ) {<br /> return true;<br /> }<br /> return false;<br /> }<br /><br />However, that still allows anyone with a valid certificate to essentially impersonate any user.Anonymoushttps://www.blogger.com/profile/00589551294538912964noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-52643150559309942532014-09-09T13:40:32.988-07:002014-09-09T13:40:32.988-07:00Sorry, my brain is fried from staring at code. The...Sorry, my brain is fried from staring at code. There are two things I wanted to mention:<br /><br />1. The STS does not properly create its WSDL when I include the "SignedElements" policy. Thus the STSClient is not able to properly create the BindingOperationInfo and therefore the request fails with "No binding operation info..."<br /><br />2. In regard to your previous comment. Even with proper TLS client authentication, this means that any client that authenticates with a certificate trusted by the server can impersonate any user. Because it does not seem to me that the code is comparing the subject of the client certificate to the issuer or subject of the SAML token.<br /><br />Thus, this is still a security hole as far as I can tell because it means that with successful TLS client authentication I can submit an unsigned SAML token with any subject and issuer information.Anonymoushttps://www.blogger.com/profile/00589551294538912964noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-65531631311486985732014-09-09T13:36:55.559-07:002014-09-09T13:36:55.559-07:00This comment has been removed by the author.Anonymoushttps://www.blogger.com/profile/00589551294538912964noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-21290576274293955962014-09-09T13:34:43.118-07:002014-09-09T13:34:43.118-07:00This comment has been removed by the author.Anonymoushttps://www.blogger.com/profile/00589551294538912964noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-89733472114927987942014-09-09T11:21:43.852-07:002014-09-09T11:21:43.852-07:00Well, anyway I spoke to soon. I thought the additi...Well, anyway I spoke to soon. I thought the addition of the "SignedElements" in the policy would work. Instead, it turns out that the RST was failing for a different reason. It seems that if I add the "SignedElements" part in the policy, the SOAP body sent to the server is completely empty and as a result I get:<br /><br />"No binding operation info while invoking unknown method with params unknown."<br /><br />Any thoughts?Anonymoushttps://www.blogger.com/profile/00589551294538912964noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-76272374672391649862014-09-09T10:16:54.084-07:002014-09-09T10:16:54.084-07:00Hi Thomas,
CXF accepts security tokens as "s...Hi Thomas,<br /><br />CXF accepts security tokens as "signed" in the context of SignedSupportingTokens if they are received over TLS OR if they are signed via XML Signature. It is somewhat of a grey area whether this is correct or not as the tokens are not directly signed. However it is up to the deployer to make sure that TLS is set up correctly with client authentication etc.<br /><br />Colm.Colm O hEigeartaighhttps://www.blogger.com/profile/10711987281965801793noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-34790981478946645102014-09-09T10:07:23.745-07:002014-09-09T10:07:23.745-07:00Hi Colm,
I think I solved my own problem. I perus...Hi Colm,<br /><br />I think I solved my own problem. I perused the WS-SecurityPolicy specification and eventually tried adding this to my policy:<br /><br /> <sp:SignedElements><br /> <sp:XPath>//saml2:Assertion</sp:XPath><br /> </sp:SignedElements><br /><br />And it worked like a charm. So it looks like the issue here was really my incomplete understanding of WS-Policy.<br /><br />Still, I wonder if this is an example of INsecurity through obfuscation. This seems like a rather basic requirement to which the "correct" solution requires the understanding of a number of rather dense standards and frameworks. Wouldn't it be more secure to enforce signature of all elements by default and use the policy only to disable signing requirements?Anonymoushttps://www.blogger.com/profile/00589551294538912964noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-50939462854377161832014-09-09T09:16:38.986-07:002014-09-09T09:16:38.986-07:00BTW, I've also tried with the policy included ...BTW, I've also tried with the policy included below. The problem for me is that it seems like the WS-SecurityPolicy allows you to specify that you require a SAML token and what version it must be. However, I can't see anything in the specification that describes how to require that the token is signed. Of course, this could be a failure on my part to grasp the finer details of the specification.<br /><br /> <wsp:Policy wsu:Id="Transport_policy_saml"><br /> <wsp:ExactlyOne><br /> <wsp:All><br /> <wsap10:UsingAddressing /><br /> <sp:TransportBinding<br /> xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"><br /> <wsp:Policy><br /> <sp:TransportToken><br /> <wsp:Policy><br /> <sp:SamlToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"><br /> <wsp:Policy><br /> <sp:WssSamlV20Token11 /><br /> </wsp:Policy><br /> </sp:SamlToken><br /> </wsp:Policy><br /> </sp:TransportToken>Anonymoushttps://www.blogger.com/profile/00589551294538912964noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-65582013060825193492014-09-09T08:32:29.540-07:002014-09-09T08:32:29.540-07:00First off all, thank you very much for helping out...First off all, thank you very much for helping out.<br /><br />a) There is no ActAs or OnBehalfOf Element, so this does not apply.<br /><br />b) I was initially suspicious that the problem might be a WS-Policy issue but everything I tried seem not to have an effect. Please see the WSDL snippet below.<br /><br /> <wsp:Policy wsu:Id="Transport_policy_saml"><br /> <wsp:ExactlyOne><br /> <wsp:All><br /> <wsap10:UsingAddressing /><br /> <sp:TransportBinding<br /> xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"><br /> <wsp:Policy><br /> <sp:TransportToken><br /> <wsp:Policy><br /> <sp:HttpsToken><br /> <wsp:Policy /><br /> </sp:HttpsToken><br /> </wsp:Policy><br /> </sp:TransportToken><br /> <sp:AlgorithmSuite><br /> <wsp:Policy><br /> <sp:Basic128 /><br /> </wsp:Policy><br /> </sp:AlgorithmSuite><br /> <sp:Layout><br /> <wsp:Policy><br /> <sp:Lax /><br /> </wsp:Policy><br /> </sp:Layout><br /> <sp:IncludeTimestamp /><br /> </wsp:Policy><br /> </sp:TransportBinding><br /> <sp:SignedSupportingTokens<br /> xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"><br /> <wsp:Policy><br /> <sp:SamlToken<br /> sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"><br /> <wsp:Policy><br /> <sp:WssSamlV20Token11 /><br /> </wsp:Policy><br /> </sp:SamlToken><br /> </wsp:Policy><br /> </sp:SignedSupportingTokens><br /> <sp:Wss11<br /> xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"><br /> <wsp:Policy><br /> <sp:MustSupportRefKeyIdentifier /><br /> <sp:MustSupportRefIssuerSerial /><br /> <sp:MustSupportRefThumbprint /><br /> <sp:MustSupportRefEncryptedKey /><br /> <sp:RequireSignatureConfirmation/><br /> </wsp:Policy><br /> </sp:Wss11><br /> <sp:Trust13<br /> xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"><br /> <wsp:Policy><br /> <sp:MustSupportIssuedTokens /><br /> <sp:RequireClientEntropy /><br /> <sp:RequireServerEntropy /><br /> </wsp:Policy><br /> </sp:Trust13><br /> </wsp:All><br /> </wsp:ExactlyOne><br /> </wsp:Policy>Anonymoushttps://www.blogger.com/profile/00589551294538912964noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-20079926434928346232014-09-09T08:22:27.200-07:002014-09-09T08:22:27.200-07:00This comment has been removed by the author.Anonymoushttps://www.blogger.com/profile/00589551294538912964noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-26905788808811041742014-09-09T05:38:28.292-07:002014-09-09T05:38:28.292-07:00Which of the following cases applies?
a) The WS-T...Which of the following cases applies?<br /><br />a) The WS-Trust request has an "ActAs" or "OnBehalfOf" Element which includes (or references the SAML Assertion in the security header)?<br /><br />b) There is no reference to a SAML Assertion in the WS-Trust request. Instead you are including a SAML Assertion in the security header of the request? In this case, what does the security policy of the STS endpoint require?<br /><br />Colm.Colm O hEigeartaighhttps://www.blogger.com/profile/10711987281965801793noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-53868775652853366042014-09-08T11:34:04.586-07:002014-09-08T11:34:04.586-07:001. Yes I am calling the issue binding.
2. I am us...1. Yes I am calling the issue binding.<br /><br />2. I am using the CXF STSClient.<br /><br />3. I am setting the SecurityConstants.SAML_CALLBACK_HANDLER property to a CallbackHandler implementation that supplies the SAML token used to authenticate with the STS.Anonymoushttps://www.blogger.com/profile/00589551294538912964noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-85503659954888333822014-09-08T08:34:12.626-07:002014-09-08T08:34:12.626-07:00What is your use-case exactly? Are you calling the...What is your use-case exactly? Are you calling the issue binding of the STS and passing the other SAML Token as OnBehalfOf/ActAs? Or are you calling the validate binding + including the SAML Token in the security header as per a security policy requirement?<br /><br />Colm.Colm O hEigeartaighhttps://www.blogger.com/profile/10711987281965801793noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-26009574664783291802014-09-08T08:22:50.749-07:002014-09-08T08:22:50.749-07:001. Trying this with an up to date version f CXF wo...1. Trying this with an up to date version f CXF would require a monumental amount of effort to change software that is only partially in my control. Imagine a scenario where you have to update a critical component for an existing product with an incredibly dense dependency tree. Upgrading a library like CXF might take a day but it could also take a week or more.<br /><br />2. I gave you the two classes where the problem exits. SamlAssertionValidator.java in WSS4J and SecurityTokenServiceProvider in CXF. It only takes few minutes to look up more recent versions of code in WSS4J (2.1.0) and CXF (2.7.12) and determine that they have not changed in ways that would mitigate this issue.<br /><br />3. This issue is easy enough to mitigate by writing a few lines of custom code. However, there are two reasons why I am bringing this to your attention:<br /><br />A. There may be an easier way to mitigate this that I do not know of. The inner security mechanisms of CXF and WSS4J are not exactly thoroughly documented. Your blogs certainly help, but in my experience, significant time spent looking at code is required to delve into things and the code is so dense it could take weeks to fully understand.<br /><br />B. This is potentially a pretty serious security issue. If you could please spend some time investigating this I think it would benefit the whole community. I also think it would be more productive than the typical process for dealing with potential vulnerabilities.Anonymoushttps://www.blogger.com/profile/00589551294538912964noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-59187005065616788452014-09-08T01:38:59.936-07:002014-09-08T01:38:59.936-07:00Could you please try with a more up to date versio...Could you please try with a more up to date version of CXF + let me know what happens? CXF 2.7.3 is quite old now + contains known security issues...<br /><br />Colm.Colm O hEigeartaighhttps://www.blogger.com/profile/10711987281965801793noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-77695913112984529072014-09-05T15:50:02.100-07:002014-09-05T15:50:02.100-07:00We're using CXF 2.7.3.
Based on what I know f...We're using CXF 2.7.3.<br /><br />Based on what I know from stepping through the code in the debugger, when the RST arrives at org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider, only the Issue operation is called not the Validate operation. Therefore, there is no way that SAMLTokenValidator gets called on the RST issue operation.<br /><br />In fact, the only code executed is the WSS4J SamlAssertionValidator and the CXF SAMLTokenProvider. Neither of which complains if the token is not signed.<br /><br />I think this is a serious problem.Anonymoushttps://www.blogger.com/profile/00589551294538912964noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-30322805663343764132014-09-05T08:28:41.735-07:002014-09-05T08:28:41.735-07:00What version of CXF are you using? The latest vers...What version of CXF are you using? The latest versions of CXF have (in the SAMLTokenValidator in the STS):<br /><br />if (!assertion.isSigned()) {<br /> LOG.log(Level.WARNING, "The received assertion is not signed, and therefore not trusted");<br /> return response;<br />}<br /><br />Colm.Colm O hEigeartaighhttps://www.blogger.com/profile/10711987281965801793noreply@blogger.comtag:blogger.com,1999:blog-7391783704166348052.post-45478758887971558582014-09-04T16:14:13.945-07:002014-09-04T16:14:13.945-07:00Hi Colm,
I created an STS using the CXF framework...Hi Colm,<br /><br />I created an STS using the CXF framework that accepts a SAML token from a trusted third party and returns a signed SAML bearer token. The STS will reject a tampered SAML tokens or a SAML tokens signed by an untrusted party. Unfortunately, and quite surprisingly, the STS will ALSO happily accept an UNSIGNED SAML token.<br /><br />Can this be right? Here is the code in WSS4J SamlAssertionValidator class where the validation occurs:<br /><br /> // Verify trust on the signature<br /> if (assertion.isSigned()) {<br /> verifySignedAssertion(assertion, data);<br /> }<br /> return credential;<br /><br />How do I change this behavior so that only signed SAML tokens are accepted? Do I have to create my own SamlAssertionValidator?<br />Anonymoushttps://www.blogger.com/profile/00589551294538912964noreply@blogger.com