Monday, October 22, 2012

Apache XML Security for Java 1.5.3 released

Apache XML Security for Java 1.5.3 has been released. This release features support for new XML Signature 1.1 KeyInfo extensions. It also fixes a number of bugs including a problem when message sizes are greater than 512 MB. The list of issues fixed is available at the Apache JIRA.

Wednesday, October 3, 2012

XML Signature Wrapping attacks on Web Services

The previous blog post looked at SOAP Action spoofing attacks on Web Services and discussed a recent security advisory in this area in Apache CXF. This vulnerability was uncovered with the help of the WS-Attacker tool referenced here. This paper also covers a different type of attack on WS-Security enabled Web Services, namely XML Signature Wrapping attacks. The WS-Attacker tool also offers some functionality to test Web Service endpoints for vulnerability against these types of attacks. In this post we will look at how to protect against XML Signature Wrapping attacks in Apache CXF.

1) XML Signature wrapping attacks

It is possible to sign a portion of a SOAP Web Service request or response at the message level using XML Signature. The message contains a security header with a Signature Element, that references one or more message parts that have been signed. Typically, the message parts are referenced by an Id, and so to validate the signature the recipient must find the Element in the request that has the corresponding Id. An XML Signature wrapping attack essentially exploits the fact that the Signature Element does not convey any information as to where the referenced Element(s) is(are) in the Document tree.

Consider a scenario where the SOAP Body of a request is signed by a signature placed in the security header of the request. The message recipient checks that the signature is correct and validates trust in the signing credential. Finally, the recipient checks to see that the required Element (in this case the SOAP Body) was actually signed, by comparing the wsu:Id of the SOAP Body to the Reference URI in the Signature.

An XML Signature wrapping attack against this scenario could work as follows. A malicious (man-in-the-middle) user could take a valid request and copy the SOAP body and insert it as part of a header in the request. The malicious user then freely alters the SOAP Body, but preserves the same wsu:Id. The message recipient must search for the Reference URI as part of the signature validation process, and hits the copied SOAP Body Element first. This verifies correctly as it has not been changed. Finally, the recipient checks to see if the Id of the SOAP Body was actually referenced in the signature (which it was, even though the SOAP Body itself was not signed).

Apache WSS4J has a built-in guard against this kind of attack, whereby an ID referenced in an XML Signature cannot appear more than once in a SOAP Envelope. However, there are more sophisticated types of wrapping attacks which can defeat this defence. The crucial thing to realise is that for XML Signature you must check to see that what you are expecting to be signed was actually signed. Apache WSS4J does not perform this kind of check, instead it is left up to the third party application (Apache CXF for the purposes of this article). 

2) Protecting against XML Signature wrapping attacks in Apache CXF

There are two ways to configure WS-Security in Apache CXF, the recommended approach based on WS-SecurityPolicy, and the older and less sophisticated approach of specifying individual security actions to perform.

2.1) WS-SecurityPolicy

The WS-SecurityPolicy approach offers easy protection against signature wrapping attacks via the WS-SecurityPolicy SignedParts and SignedElements policies. The SignedElements policy takes a number of XPath expressions corresponding to the Elements that must be signed, should they be included in the request. The XPath expression must not be a relative expression for the purposes of protection against this attack.

A more common approach is to use the WS-SecurityPolicy "SignedParts" policy. This policy allows the user to specify that the SOAP Body and any number of SOAP Headers must be signed. For example:

<sp:SignedParts>
<sp:Body />
<sp:Header Name="..." Namespace="..."
</sp:SignedParts>

Apache CXF makes sure that the SOAP Body and any specified SOAP header is actually signed, rather that just comparing Id's as outlined in the attack scenario above, this circumventing any XML Signature wrapping attack.

2.2) Older WS-Security approach

The older non-policy based approach to configuring WS-Security does not perform any checking by default of what Elements were signed, and so is vulnerable to XML Signature wrapping attacks out of the box. One way to remedy this since CXF 2.2.8 is to install the CryptoCoverageChecker interceptor. This allows you to define an XPath Expression corresponding to an Element that must be signed (or encrypted). Installing this interceptor defeats an XML Signature Wrapping attack (see the wiki for more details).

However, the CryptoCoverageChecker is somewhat complex to set up for the most common use-cases for signature verification and decryption, as it involves adding XPath expressions and the corresponding prefix/namespace pairs. In Apache CXF 2.4.9, 2.5.5 and 2.6.2, a new subclass of CryptoCoverageChecker has been introduced. The DefaultCryptoCoverageChecker provides an easy way to ensure that the SOAP Body is signed or encrypted, that the Timestamp is signed, and that the WS-Addressing ReplyTo and FaultTo headers are signed (if they are present in the message payload).

The default configuation is that the SOAP Body, (WSU) Timestamp and WS-Addressing ReplyTo and FaultTo headers must be signed (if they exist in the message payload). This provides an out-of-the-box way of preventing XML Signature wrapping attacks. All that is required is that the DefaultCryptoCoverageChecker be added to the in-interceptor chain. I strongly recommend that you consider doing this if you are still using the older configuration for a WS-Security enabled endpoint. For example:

<jaxws:inInterceptors>
    <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
        <constructor-arg>
            <map>
                <entry key="action" value="Signature Timestamp"/>
                <entry key="signaturePropFile" value="..."/>
                <entry key="passwordCallbackClass"value="..."/>
           </map>
        </constructor-arg>
    </bean>
    <bean class="org.apache.cxf.ws.security.wss4j.DefaultCryptoCoverageChecker"/>
</jaxws:inInterceptors>

Thursday, September 20, 2012

SOAP Action Spoofing Attacks on Web Services

A recent paper by Christian Mainka, Juraj Somorovsky and Jörg Schwenk at the Horst Görtz Institute for IT Security of the Ruhr University Bochum, describes an open-source tool that can be used to perform penetration testing attacks on Web Services. In particular, this tool has uncovered a vulnerability in Apache CXF to a type of SOAP Action spoofing attack, that is the content of a recently disclosed security vulnerability. This vulnerability has been fixed in versions 2.4.9, 2.5.5, and 2.6.2 of CXF.
Each operation in a SOAP web service can be associated with a SOAP Action String, for example in the WSDL binding or via an annotation. The web service client can send the SOAP Action String as a header with the request as a way of letting the web service know what operation is required.

In some cases, Apache CXF uses the received SOAP Action to select the correct operation to invoke, and does not check to see that the message body is correct. This can be exploitable to execute a SOAP Action spoofing attack, where an adversary can execute another operation in the web service by sending the corresponding SOAP Action. This attack only works if the different operation takes the same parameter types, and hence has somewhat limited applicability.

This attack also only applies for web services that use unique SOAP Actions per service operation which is not the default in CXF. Also note that WS-Policy validation is done against the operation being invoked and thus the incoming message must meet those policy requirements as well, also limiting applicability.

Friday, August 3, 2012

Apache WSS4J 1.6.7 released

Apache WSS4J 1.6.7 has been released. The release notes are available here. The main features of the release are:
  • A critical fix for a concurrency bug in the MemoryReplayCache
  • Subject DN Certificate Constraint support (as blogged previously).
  • A number of relatively minor fixes identified by interop testing with WCF.
  • A fix that prevented the 1.6.6 release from being deployed in an OSGi container.

Thursday, August 2, 2012

Subject DN Certificate Constraint support in Apache WSS4J and CXF

Apache WSS4J 1.6.7 features support for specifying constraints on the subject DN of the certificate used for signature validation. This functionality will also be available in the forthcoming Apache CXF 2.6.2, 2.5.5 and 2.4.9 releases.

After a successful signature validation using a certificate referenced in the KeyInfo structure of an XML Signature, the next step is to establish trust in the certificate. The term "direct trust" applies to when the certificate is contained directly in the signature keystore. In this case, certificate constraints are not required as we "directly trust" the certificate. The term "chain trust" refers to when the issuing certificate of the certificate used for signature validation is contained in the signature truststore, and the certificate path of the received certificate is verified.

There is a potential security issue when "chain trust" is applicable. Although the certificate used for signature validation might be "trusted" in a general sense (via a trusted issuing certificate), you may not wish to accept every certificate issued by the trusted certificate. This is particularly relevant if any certificate in your signature truststore is (or can potentially be) used to issue a wide range of certificates.

This is where the concept of constraints on the subject DN of a trusted certificate comes in. The idea is that the user can specify a list of regular expressions, one of which (note not all) must be applicable to the subject DN of a (trusted) certificate used for signature verification. These constraints are not used when the certificate is contained in the keystore (direct trust). If no cert constraints are defined, and a successful trust validation is done using "chain trust", a warning message is logged indicating that a potential security risk exists in signature validaition.

Subject DN Cert Constraints can be configured in WSS4J by specifying a WSHandlerConstants tag, see the WSS4J configuration page for more information. To see this functionality in action take a look at the corresponding WSS4J Unit Test, which uses a cert constraint of ".*CN=Colm.*O=Apache.*". Certificate constraint support can also be enabled in CXF via the endpoint property tag "ws-security.subject.cert.constraints". See the CXF WS-SecurityPolicy for more information.

Tuesday, June 19, 2012

SAML Web SSO profile support in Apache CXF

Apache CXF has an impressive range of security features for JAX-RS endpoints. It also has excellent documentation in this space, see for example the JAX-RS documentation for OAuth, SAML Assertions and XML Encryption/Signature.  Apache CXF 2.6.1 enhances the JAX-RS security story further by featuring support for the SAML 2.0 Web SSO profile.

The basic standard scenario for Web SSO involves a client browser accessing a secured (JAX-RS) endpoint. The endpoint constructs a SAML AuthnRequest and includes it in redirecting the browser to a Identity Provider (IDP) for authentication (via a dialog). The IDP constructs a SAML Response, and redirects the browser to a Request Assertion Consumer Service (RACS) URI contained in the AuthnRequest.  The RACS validates the SAML Response and redirects the browser yet again to the original secured endpoint. The endpoint stores the session in a cookie (hence single sign-on) and access is granted to the resource. The following steps detail how to implement this scenario in Apache CXF using the new "cxf-rt-rs-security-sso-saml" module.

1) JAX-RS binding filters

The SAML 2.0 bindings specification defines HTTP redirect and HTTP POST bindings which can be used to "redirect" the client browser, e.g. from the secured endpoint to the IDP. Apache CXF 2.6.1 provides a separate JAX-RS filter to support these bindings. Therefore, the first step in securing a JAX-RS endpoint is to decide which of these two bindings to use. The SamlRedirectBindingFilter class providers support for the HTTP redirect binding, and the SamlPostBindingFilter provides support for the HTTP POST binding. Both of these filters share the following configuration properties.

1.1) Required Configuration Properties

Each filter implementation must be configured with the URL of the IDP, as well as the URL of the RACS. It must also be configured with a SPStateManager implementation to keep track of the Authenticated sessions. CXF ships with an EhCache based implementation:
  • SPStateManager stateProvider - An object which keeps track of authenticated sessions.
  • String idpServiceAddress - The URL of the IDP.
  • String assertionConsumerServiceAddress - The URL of the RACS. This can be a relative or absolute URL.
1.2) Signature Configuration Properties 

The following configuration properties are only required if you wish to sign the AuthnRequest:
  • boolean signRequest - Whether to sign the AuthnRequest or not. The default is false.
  • String signatureUsername - The keystore alias to use to sign the AuthnRequest.
  • Crypto signatureCrypto - A WSS4J Crypto object if the SAML AuthnRequest is to be signed.
  • String signaturePropertiesFile - This points to a properties file that can be used to load a Crypto instance if the SAML AuthnRequest is to be signed. 
  • CallbackHandler callbackHandler - A CallbackHandler object to retrieve the private key password used to sign the request.
  • String callbackHandlerClass - A class name that is loaded for use as the CallbackHandler object. 
Either the "signatureCrypto" or "signaturePropertiesFile" properties must be set if "signRequest" is set to true. Similarly, either "callbackHandler" or "callbackHandlerClass" must be configured.

1.3) Optional Configuration Properties

Here are some optional configuration properties that can be set:
  • long stateTimeToLive - The default value (in milliseconds) that a session is valid for. The default value is 2 minutes. 
  • String issuerId - The Issuer Id value to be included in the AuthnRequest. It defaults to the Base URI.
  • AuthnRequestBuilder authnRequestBuilder - An object that constructs the AuthnRequest. It defaults to DefaultAuthnRequestBuilder.
There are some additional optional configuration properties relating to domains and web application contexts that will be covered in more detail on the CXF wiki.

1.4) Sample Spring configuration

Here is a sample spring configuration extract to support the redirect binding filter which signs AuthnRequests:

<bean id="stateManager" class="org.apache.cxf.rs.security.saml.sso.state.EHCacheSPStateManager"/>

<bean id="ssoSignedRedirectURI"  class="org.apache.cxf.rs.security.saml.sso.SamlRedirectBindingFilter">
        <property name="idpServiceAddress" value="https://.../idp-sig/"/>
        <property name="assertionConsumerServiceAddress"
                  value="/racs/sso"/>
        <property name="stateProvider" ref="stateManager"/>
        <property name="addEndpointAddressToContext" value="true"/>
        <property name="callbackHandlerClass" value="....SSOCallbackHandler"/>
        <property name="signatureUsername" value="myservicekey"/>
        <property name="signaturePropertiesFile" value="serviceKeystore.properties"/>
        <property name="signRequest" value="true"/>
</bean>

<jaxrs:server address="/app1">
       <jaxrs:serviceBeans><ref bean="..."/></jaxrs:serviceBeans>
       <jaxrs:providers><ref bean="ssoRedirectURI"/></jaxrs:providers>
</jaxrs:server>

2) The Request Assertion Consumer Service

The JAX-RS filters described above take care of creating a SAML AuthnRequest, optionally signing it, and redirecting the client browser to the IDP. The next step is to define a RequestAssertionConsumerService (RACS) which will intercept the SAML Response from the IDP. The RACS processes the SAML Response, and validates it in a number of ways:
  • The SAMLProtocolResponseValidator validates the Response against the specifications and checks the signature of the Response (if it exists), as well as doing the same for any child Assertion of the Response. It validates the status code of the Response as well. 
  • The SAMLSSOResponseValidator validates the Response according to the Web SSO profile. 
If validation is successful the RACS redirects to the service provider endpoint.

2.1) Configuration properties shared with the filters

The RequestAssertionConsumerService that ships with CXF shares a number of configuration properties with the filters, mainly relating to state and signature configuration:
  • SPStateManager stateProvider - An object which keeps track of authenticated sessions. This is required.
  • long stateTimeToLive - The default value (in milliseconds) that a session is valid for. The default value is 2 minutes.
  • Crypto signatureCrypto - A WSS4J Crypto object to use to validate a signed Response.
  • String signaturePropertiesFile - This points to a properties file that can be used to load a Crypto instance for signature validation.
  • CallbackHandler callbackHandler - A CallbackHandler object to retrieve the private key password used to decrypt an encrypted request.
  • String callbackHandlerClass - A class name that is loaded for use as the CallbackHandler object.  
Only the "stateProvider" property is required. Either the "signatureCrypto" or "signaturePropertiesFile" properties must be set if you wish to support verifying signed Responses, or signed Assertions contained in a Response. Similarly, either "callbackHandler" or "callbackHandlerClass" must be configured if you wish to support decrypting encrypted Assertions. 

2.2) Additional Optional Configuration properties

The RACS supports the following additional (optional) configuration properties:
  • boolean supportDeflateEncoding - Whether Deflate encoding is used to inflate a token received via the Redirect binding. The default is true.
  • boolean supportBase64Encoding - Whether the token is Base64 decoded or not. The default is true.
  • boolean enforceAssertionsSigned - Whether the Assertions contained in a Response must be signed or not. The default is true.
  • boolean enforceKnownIssuer - Whether the Issuer of the Response (and child Assertions) is "known" to the RACS. This value is compared against the IDP URL configured on the filter. The default value is true.
  • TokenReplayCache<String> replayCache - A TokenReplayCache implementation to store Assertion ID's for the POST binding to guard against replay attacks. The default uses an implementation based on EhCache.
2.4) Sample Spring Configuration

Here is a sample spring configuration extract to set up a RACS, that could be used with the filter configuration in section 1.4:

 <bean id="consumerService" class="org.apache.cxf.rs.security.saml.sso.RequestAssertionConsumerService">
        <property name="stateProvider" ref="stateManager"/>
        <property name="signaturePropertiesFile" value="serviceKeystore.properties"/>
        <property name="enforceKnownIssuer" value="false"/>
        <property name="callbackHandlerClass" value="...SSOCallbackHandler"/>
</bean>

3) The Identity Provider (IDP)

The remaining piece of the puzzle is the Identity Provider (IDP) which receives the SAML AuthnRequest from the service provider, processes it accordingly, and then interacts with the client browser to authenticate the client. It then creates a SAML Response and redirects the client browser to the RACS defined in the AuthnRequest. Apache CXF does not (yet) ship with an IDP, although this may change in the near future. However, there are a number of open-source IDPs that can be used with a CXF JAX-RS endpoint that supports SAML Web SSO. These include Shibboleth, PicketLink, OpenAM, JOSSO, etc. I have tested against all of these products. Report any interop issues to the CXF JIRA.

4) Ongoing Development

SAML Web SSO profile support is still being actively developed. A number of bugs have been fixed that do not yet appear in a released version of CXF. For example, support for decrypting encrypted Assertions in a SAML Response, and some bugs relating to signed Assertions (CXF-4352 and CXF-4365).

Thursday, June 14, 2012

Simplified Apache CXF STS configuration

The Apache CXF STS configuration options have been covered in detail in previous posts on this blog. Following some suggestions by Glen Mazza, a new simplified way of configuring the STS will be available in Apache CXF 2.6.2. This new configuration is essentially a simpler and more intuitive way of catering for the most common STS scenarios. The older configuration style is still fully supported.

An example of how to configure the CXF STS using the old configuration is available here. It involves a mixture of the STS Provider API that lives in the WS-Security module in CXF, and the concrete STS functionality that is available in the STS services module in CXF. The SecurityTokenServiceProvider in the CXF API is instantiated with implementations of the various Operations (Issue/Validate/etc.) that are available in the CXF STS. However, the flexibility of this approach leads to a slightly verbose configuration style, which is perhaps overly complicated for the most common use-cases.

An example of the simpler configuration approach is available here. Rather than use the SecurityTokenServiceProvider in the CXF API, it uses a sub-class in the CXF STS (DefaultSecurityTokenServiceProvider). This implementation supports the issue and validate bindings by default. It also supports the ability to issue and validate SAML Tokens, and to validate UsernameTokens and X.509 Tokens. Therefore, for any of these use-cases there is no need to use the old-style configuration, which involves explicitly instantiating each TokenProvider or TokenValidator instance and setting them on an IssueOperation/ValidateOperation instance.  However, if you want to use the renew or cancel bindings, or do anything with SecurityContextTokens, it's necessary to use the old configuration.

The DefaultSecurityTokenServiceProvider can be configured with the following (optional) properties:
  • boolean encryptIssuedToken - Whether to encrypt the issued token or not. The default is false.
  • List<ServiceMBean> services - A list of service endpoints to support. See here for more information.
  • boolean returnReferences - Whether to return references to an issued token or not. The default is true.
  • TokenStore tokenStore - The TokenStore caching implementation to use. See here for more information.
  • ClaimsManager claimsManager - The ClaimsManager to use if you want to be able to handle claims. See here for more information.