Wednesday, April 25, 2012

Security Token Caching in Apache CXF 2.6 - part II

This post is the second in a two-part series on how security tokens are cached in Apache CXF 2.6. Part I covered how UsernameToken nonces and Timestamps are cached to prevent replay attacks, using a default caching implementation based on EhCache. In this post I will cover how security tokens are cached in the CXF WS-Security runtime and also in the STS.

1) CXF WS-Security runtime token caching

CXF caches tokens in the security runtime in the following circumstances:
  • When the IssuedTokenInterceptorProvider is invoked to obtain an Issued token from an STS.
  • When the STSTokenValidator is used to validate a received UsernameToken, BinarySecurityToken or SAML Assertion to an STS.
  • When the SecureConversation protocol is used.
  • When the WS-Trust SPNEGO protocol is used.
  • When tokens are obtained from a Kerberos KDC.
In each of these use-cases, the retrieved token is cached to prevent repeated remote calls to obtain the desired security token. There is no built-in support as yet to cache tokens in the WS-Security layer to prevent repeat validation. Of course this could be easily done by wrapping the existing validators with a custom caching solution.

1.1) SecurityTokens

CXF defines a SecurityToken class which encapsulates all relevant information about a successful authentication event in the security runtime (as defined above). In particular, it contains the following items (amongst others):
  • A String identifier of the token. This could be a SAML Assertion Id, the Identifier element of a SecurityContextToken, or the wsu:Id of a UsernameToken, etc.
  • The DOM Element that represents that security token.
  • Attached and Unattached reference elements for that token that might have been retrieved from an STS.
  • A byte[] secret associated with the token.
  • An expiration date after which the token is not valid.
  • A String TokenType that categorizes the token.
  • An X.509 Certificate associated with the token.
  • The principal associated with the token.
  • A hashcode that represents the security token (normally the hashcode of the underlying WSS4J object).
  • An identifier of another SecurityToken that represents a transformed version of this token.
 1.2) TokenStores

CXF defines a TokenStore interface for caching SecurityTokens in the WS-Security runtime module. Prior to CXF 2.6, a simple default HashMap based approach was used to cache security tokens. In CXF 2.6, Ehcache is used to provide a suitable default TokenStore implementation to cache security tokens. Tokens are stored until the expiry date of the token if it exists, provided it does not exceed the maximum storage time of 12 hours. If it exceeds this, or if there is no expiry date provided in the security token, it is cached for the default storage time of 1 hour. If the token is expired then it is not cached. This default storage time is configurable. Note that while Ehcache is a compile time dependency of the WS-Security module in CXF, it can be safely excluded in which case CXF will fall back to use the simple HashMap based cache, unless the user specifically wants to implement an alternative TokenStore implementation and configure this instead.

Apache CXF 2.6 provides support for configuring caching via the following JAX-WS properties:
  • "org.apache.cxf.ws.security.tokenstore.TokenStore" - The TokenStore instance to use to cache security tokens. By default this uses the EHCacheTokenStore if Ehcache is available. Otherwise it uses the MemoryTokenStore.
  • "ws-security.cache.config.file" - Set this property to point to a configuration file for the underlying caching implementation. By default the cxf-ehcache.xml file in the CXF rt-ws-security module is used.
2) CXF STS token caching

Token caching in the CXF STS has been previously (briefly) covered in the STS documentation. Prior to CXF 2.6, the STS shipped an interface called "STSTokenStore" that contained some additional functionality related to storing SecurityTokens specific to the STS. In CXF 2.6, this interface has been removed, and instead the same TokenStore interface is used as in the security runtime. A TokenStore instance can be set on any of the STS operations (see AbstractOperation), and it will be used for caching in the token providers, validators, etc. The STS ships with two TokenStore implementations, a DefaultInMemoryTokenStore which just wraps the EHCacheTokenStore discussed above, and an implementation based on HazelCast.

Token caching works in different ways depending on where it is used. Both token providers (SAML and SecurityContextTokens) that ship with the STS cache a successfully generated token. When a SAML or SecurityContextToken (or UsernameToken) is received by the STS for validation, it will first check to see whether the token is stored in the cache. If it is then validation is skipped. If it is not, then the TokenValidator will re-validate the token, and store it in the cache if validation is successful. A slight caveat to this behaviour for SAML Tokens is that token validation is only skipped if the token that is stored in the cache originally was signed, as this signature value is used to check to see if the two SAML Tokens are equal. The TokenCanceller implementation for cancelling SecurityContextTokens in the STS removes the token from the cache, if the token is stored in the cache and proof-of-possession passes.

Finally, two significant changes in CXF 2.6.0 concerning caching in the STS relate to the length of time tokens are valid for. Prior to CXF 2.6.0, SecurityContextTokens and SAML Tokens issued by the STS were valid for a default (configurable) value of 5 minutes. In CXF 2.6.0, both tokens are now issued for a default value of 30 minutes, and are stored in the cache for this length of time as a result.

Monday, April 23, 2012

Note on CVE-2011-1096

A new attack on the XML Encryption standard has recently emerged and is described by the security advisory CVE-2011-1096:
Tibor Jager, Juraj Somorovsky, Meiko Jensen, and Jorg Schwenk
described an attack technique against W3C XML Encryption Standard,
when the block ciphers were used in cipher-block chaining (CBC)
mode of operation. A remote attacker, aware of a cryptographic
weakness of the CBC mode could use this flaw to conduct
chosen-ciphertext attacks, leading to the recovery of the entire
plaintext of a particular cryptogram by examining of the differences
between SOAP responses, sent from JBossWS, J2EE Web Services server.
There is no (immediate) security "fix" for this issue, as it is an attack on the standard itself. However, the attack can be prevented by using a symmetric algorithm such as AES-128 or AES-256 with GCM. Support for GCM algorithms is available in Apache Santuario 1.5.0 and Apache WSS4J 1.6.5 (see here).

One problem with using a GCM algorithm via WS-SecurityPolicy is that no AlgorithmSuite policy is defined in the WS-SecurityPolicy 1.3 specification that uses GCM. Until the WS-SecurityPolicy specification is updated to support GCM, Apache CXF has defined its own AlgorithmSuite policies to use GCM algorithms. These AlgorithmSuites are called "Basic128GCM", "Basic192GCM" and "Basic256GCM" in the namespace "http://cxf.apache.org/custom/security-policy", and are exactly the same as the corresponding standard "Basic(128|192|256)" policies, except that GCM is used instead of CBC. For example, to use the AES-128 Algorithm with GCM mode, one would use a policy like:

<sp:AlgorithmSuite>
    <wsp:Policy>
        <sp-cxf:Basic128GCM xmlns:sp-cxf="http://cxf.apache.org/custom/security-policy"/>
    </wsp:Policy>
</sp:AlgorithmSuite>

CXF contains a number of system tests that show how to use these new AlgorithmSuites. The WSDL containing the embedded policies is here, and the test itself is here. This functionality is available from Apache CXF 2.4.7, 2.5.3, and 2.6.0.

In addition to this, the CXF JAX-RS XML Security functionality has been updated so that GCM algorithms can be used for encryption and decryption via the BouncyCastle JCE provider. A test is available here. For more information on the CXF JAX-RS XML Security functionality, checkout Sergey's blog or the CXF wiki page.

Friday, April 20, 2012

Renewing SAML Tokens in the Apache CXF STS

Apache CXF 2.6.0 sees a number of improvements to the functionality of the SecurityTokenService (STS). These include relatively minor tasks such as supporting SymmetricKeys for Entropy and BinarySecret Elements, supporting SecurityTokenReferences in UseKey Elements, and supporting KeyInfo/KeyValue Elements in UseKey Elements. However, the STS also includes two major new features. The first of these new features, the ability to renew (SAML) tokens, is covered in this blog entry.

1) The TokenRenewer interface

Security tokens are renewed in the STS via the TokenRenewer interface. It has the following methods:
  • void setVerifyProofOfPossession(boolean verifyProofOfPossession) - A boolean switch to enable or disable the proof of possession requirement.
  • void setAllowRenewalAfterExpiry(boolean allowRenewalAfterExpiry) - A switch to enable or disable the ability to renew tokens after they have expired.
  • boolean canHandleToken(ReceivedToken renewTarget) - Whether this TokenRenewer implementation can renew the given token.
  • boolean canHandleToken(ReceivedToken renewTarget, String realm) - Whether this TokenRenewer implementation can renew the given token in the given realm.
  • TokenRenewerResponse renewToken(TokenRenewerParameters tokenParameters) - Renew the token using the given parameters
A client can request that the STS renew a security token by invoking the "renew" operation and supplying a token under the "RenewTarget" Element. Assuming that the client request is authenticated and well-formed, the STS will first iterate through a list of TokenValidator implementations to see if they can "handle" the received token. If they can, then the implementation is used to validate the received security token. If no TokenValidator is found that can handle the RenewTarget that was received, then an exception is thrown. Note that this means that for token renewal, it is necessary to configure both a TokenValidator and TokenRenewer implementation that can handle the given token.

After the successful validation of a token, the state of the token is checked. If the state is not valid or expired, then an exception is thrown. The STS then iterates through the configured list of TokenRenewer implementations to see which can renew the given (validated) token. The token is then renewed and returned to the client.

The TokenRenewerParameters class is nothing more than a collection of configuration properties to use in renewing the token, which are populated by the STS operations using information collated from the request, or static configuration, etc. The TokenRenewerResponse class holds the results from the (successful) token renewal, including the DOM representation of the renewed token, the token Id, the new lifetime of the renewed token, and references to the renewed token. 

2) The SAMLTokenRenewer

The SAMLTokenRenewer can renew valid or expired SAML 1.1 and SAML 2.0 tokens. The following properties can be configured on the SAMLTokenRenewer directly:
  • boolean signToken - Whether to sign the renewed token or not. The default is true.
  • ConditionsProvider conditionsProvider - An object used to add a Conditions statement to the token.
  • Map<String, SAMLRealm> realmMap - A map of realms to SAMLRealm objects. See here for an explanation of realms in the SAMLTokenProvider.
  • long maxExpiry - how long a token is allowed to be expired (in seconds) before renewal. The default is 30 minutes.
The SAMLTokenRenewer first checks that the token it extracts from the TokenRenewerParameters is in an expired or valid state, if not it throws an exception. It then retrieves the cached token that corresponds to the token to be renewed. A cache must be configured to use the SAMLTokenRenewer, and the token to be renewed must be in the cache before renewal takes place, for reasons that will become clear in the next section.

2.1) Token validation

Before the received SAML token can be renewed, a number of validation steps (that are specific to renewing SAML tokens) takes place. Two boolean properties are retrieved from the properties of the cached token:
  • org.apache.cxf.sts.token.renewing.allow - Whether the token is allowed to be renewed or not.
  • org.apache.cxf.sts.token.renewing.allow.after.expiry - Whether the token is allowed to be renewed or not after it has expired.
These two properties are set in the SAMLTokenProvider based on a received "<wst:Renewing/>" element when the user is requesting a SAML token via the issue binding. If a user omits a "<wst:Renewing/>" element, or sends "<wst:Renewing/>" or "<wst:Renewing Allow="true"/>", then the token is allowed to be renewed. However, only if the user sends <wst:Renewing OK=True"/>", will the token be allowed to be renewed after expiry. This explains why a TokenStore is required for token renewal, as without access to these two properties it is impossible for the SAMLTokenRenewer to figure out whether the issuer of the token intended for the token to be renewed (after expiry) or not.

If the state of the token is expired, and if the token is allowed to be renewed after expiry, a final check is done against the boolean set via the "setAllowRenewalAfterExpiry" method of TokenRenewer. If this is set to false (the default), then an exception is thrown. So to support token renewal after expiry, you must explicitly define this behaviour on the TokenRenewer implementation. Finally, a check is done on how long ago the SAML Token expired. If it is greater than the value configured in the "maxExpiry" property (30 minutes by default), then an exception is thrown.

The next validation step is to check proof of possession, if this is enabled (true by default). The Subject KeyInfo of the Assertion must contain a PublicKey or X509Certificate that corresponds to either the client certificate if TLS is used, or to the private key that was used to sign some part of the request. Finally, if an "AppliesTo" URI is sent as part of the request, the SAMLTokenRenewer checks that the received Assertion contains at least one AudienceRestrictionURI that matches that address, otherwise it throws an Exception.

2.2) Renewing the SAML Assertion

After the validation steps outlined above have passed, the token is renewed in the following way:
  • A new ID is generated for the token.
  • A new "IssueInstant" is set on the token.
  • A new Conditions Element replaces the old Conditions Element of the token, using the configured ConditionsProvider.
  • The Assertion is (re)-signed if the "signToken" property is true.
The old token is removed from the cache, and the new token is added. Finally, the token is set on the TokenRenewerResponse, along with the token Id, and Lifetime.

3) SAML Token Renewal in action

Finally, let's take a look at a system test in CXF that shows how to renew a SAML Token issued by an STS. The wsdl of the service provider defines a number of endpoints which use the transport binding, with a (endorsing) supporting token requirement which has an IssuedToken policy that requires a SAML token. In other words, the client must request a SAML token from an STS and send it to the service provider over TLS, and optionally use the secret associated with the SAML token to sign the message Timestamp (if an EndorsingSupportingToken policy is specified in the wsdl).

The STS spring configuration is available here. The SAMLTokenRenewer is configured with proof-of-possession enabled, and tokens are allowed to be renewed after they have expired. Let's look at the test code and client configuration. All of the tests follow the same pattern. The client requests a SAML Token from the STS (as per the IssuedToken policy), with a TTL (time-to-live) value of 8 seconds. The client then uses this issued token to make a successful request to the service provider. The test code then sleeps for 8 seconds to expire the token, and tries to invoke on the service provider again. The IssuedTokenInterceptorProvider in the WS-Security runtime in CXF recognises that the token has expired, and sends it to the STS for renewal. The returned (renewed) token is then sent to the service provider.

Wednesday, April 18, 2012

Security Token Caching in Apache CXF 2.6 - part I

This post is the first of a two-part series on how security tokens are cached in Apache CXF 2.6.0, which has just been released. In this particular post I will examine how Apache CXF provides detection against replay attacks on the WS-Security protocol. Apache WSS4J 1.6.5 provides support for detecting and preventing replay attacks.

1) Replay attacks on the WS-Security protocol

A replay attack in this context is when an adversary intercepts a WS-Security enabled message and sends it again to the original intended target of the message. As the message is a direct copy of the original (presumably valid) message, the normal security processing steps should pass without error. Therefore, some additional steps are required on both the initiator and recipient side to protect against these attacks.

2) Message initiator requirements

The initiator should take either or both of the following steps:
  • If the initiator is including a UsernameToken in the message, the initiator should include a nonce in the UsernameToken. A nonce is a random String that can serve as an identifier for the message. The recipient can then cache this value for a certain time period and reject any subsequent message containing this nonce.
  • The initiator should include a Timestamp in the security header of the message. This step alone provides a certain protection against a replay attack if it includes an Expires element, which the recipient should reject if it contains a value prior to the time the message was received at. The Created value of the Timestamp can also serve as the basis of a unique identifier to store in a replay cache.
3) Message recipient requirements

A service provider that uses WS-SecurityPolicy can enforce the message requirements defined above on the client by doing the following:
  • Use a <sp:HashPassword/> OR a <sp13:Nonce/> policy in the UsernameToken policy.
  • Add a <sp:IncludeTimestamp/> to the binding policy.
In addition to this, the recipient must provide a cache to store the UsernameToken nonce values and Timestamp Created values. Note that Timestamp Created values do not provide enough "uniqueness" on their own, as the recipient could receive two valid messages from different clients that were created at the same millisecond in time. Therefore, WSS4J combines the Timestamp Created value with a message Signature value to form a unique identifier. If no message signature is included in the message, then no replay caching is done for Timestamps. However, note that CXF already enforces that a Timestamp must be signed for the Symmetric and Asymmetric WS-SecurityPolicy bindings.

4) Replay caching support in WSS4J

Apache WSS4J 1.6.5 provides support for detecting and preventing replay attacks by introducing the ReplayCache interface. A seperate ReplayCache instance is used to cache UsernameToken nonces and Timestamp Created / Signature Value Strings. WSS4J ships with a sample HashSet based implementation, which is not intended for production use. The default caching time for this implementation is 5 minutes - Timestamps are cached until their expiry time (if it exists), otherwise for 5 minutes.

The ReplayCache implementations to use can be configured via RequestData. No ReplayCache implementation is used by default for backwards compatibility reasons - to enable it you must implement the ReplayCache interface, and set the appropriate methods on RequestData. 

5) Replay caching support in CXF.

Apache CXF 2.6 uses Ehcache to provide a suitable ReplayCache implementation to detect replay attacks. The default cache time for the Ehcache implementation is 60 minutes. No configuration is required for out-of-the-box support for replay attack detection on the message recipient side. Caching is not enabled by default on the inbound initiator side for efficiency reasons. Note that this functionality is available in Apache CXF 2.4.7 and 2.5.3, but is not enabled by default at all for backwards-compatibility reasons. Ehcache is an optional provided dependency for these releases, meaning that you will have to include it as a dependency and enable caching to get replay caching to work. If caching is enabled and Ehcache is not available, then CXF will fall back to using the default HashSet based implementation that ships with WSS4J. Note that this is not intended for production use and will entail performance penalties.

Apache CXF 2.6 provides support for configuring replay caching via the following JAX-WS properties:
  • "ws-security.enable.nonce.cache" - The default value is "true" for message recipients, and "false" for message initiators. Set it to true to cache for both cases.
  • "ws-security.enable.timestamp.cache" - This uses the same logic as above.
  • "ws-security.nonce.cache.instance" - This holds a reference to a ReplayCache instance used to cache UsernameToken nonces. The default instance that is used is the EHCacheReplayCache.
  • "ws-security.timestamp.cache.instance" - This uses the same logic as above.
  • "ws-security.cache.config.file" - Set this property to point to a configuration file for the underlying caching implementation. By default the cxf-ehcache.xml file in the CXF rt-ws-security module is used.

Wednesday, March 21, 2012

UsernameToken Derived Key support in Apache CXF

Support for UsernameToken derived keys has been added to Apache CXF and will be available in the forthcoming 2.4.7 and 2.5.3 releases. UsernameTokens are usually used for authentication, where an initiator places a username and password (plaintext or digested) in the security header of a Soap request. However, it is also possible to exploit the fact that the initiator and recipient share a common secret (the password), by deriving a key from the UsernameToken to perform message level encryption or signature. This functionality provides an alternative to the usual certificate-based approach involved in message level security.

The WS-Security UsernameToken 1.1 profile describes how to derive keys from a UsernameToken. The UsernameToken does not include a password in this case, but includes Username, Salt and (an optional) Iteration elements. The Salt is a 128 bit value, where the high-order 8 bits have the value 01 when it is used for signature, and 02 when used for encryption. This implies that a key derived from a UsernameToken can be used for either signature or encryption, but not both. 

1) Running the UsernameToken derived key system tests in Apache CXF 

The best way to understand how to use this functionality is to take a look at the system tests. To run the UsernameToken derived key system tests in CXF, make sure that the JDK has unlimited security policies installed, and then checkout the CXF trunk via:
svn co https://svn.apache.org/repos/asf/cxf/trunk/
Go into the "trunk" directory, and compile and install CXF via "mvn -Pfastinstall" (this will avoid running tests). Finally go into the WS-Security system tests in "systests/ws-security". The UsernameTokenDerivedTest contains a number of tests that show how to use keys derived from Username Tokens to secure a message exchange. The service and client endpoints are spring-loaded. If you want to see the message exchanges, open src/test/resources/logging.properties, and change the level from WARNING to INFO, and the ConsoleHandler level from SEVERE to INFO. Finally, run the tests via:

        mvn test -Dtest=UsernameTokenDerivedTest

2) WS-SecurityPolicy configuration

The wsdl that defines the service endpoints contains WS-SecurityPolicy expressions that define the security requirements of the endpoints. The following security policies are used for the tests:
  • DoubleItSymmetricProtectionPolicy: This uses a Symmetric binding, where the protection token is a UsernameToken. In other words, a key is derived from the UsernameToken according to the spec, and is used to encrypt or sign the message request.
  • DoubleItSymmetricProtectionDKPolicy: This is the same as above, except that instead of using the UsernameToken derived key directly, another derived key is used instead.
  • DoubleItSymmetricProtectionEncPolicy: This is the same policy as above, except that it is used for encryption and not signature. It does not include a Timestamp requirement, as this would require that the Timestamp be signed.
  • DoubleItTransportEndorsingPolicy: This uses a Transport binding, where a UsernameToken is included as an EndorsingSupportingToken. In other words, the key derived from the UsernameToken is used to sign the Timestamp.
  • DoubleItSymmetricSignedEndorsingPolicy: This uses a Symmetric binding, where a UsernameToken is included as a SignedEndorsingSupportingToken. 
  • DoubleItSymmetricEndorsingEncryptedPolicy: This uses a Symmetric binding, where a UsernameToken is included as a EndorsingEncryptedSupportingToken.
  • DoubleItSymmetricSignedEndorsingEncryptedPolicy: This uses a Symmetric binding, where a UsernameToken is included as a SignedEndorsingEncryptedSupportingToken. 
UsernameToken derived keys are not currently supported with the Asymmetric binding.

Monday, March 5, 2012

Apache WSS4J 1.6.5 released

Apache WSS4J 1.6.5 has been released. The list of issues that were fixed in this release is available here. This is quite a significant release as it contains an upgrade to use Apache Santuario (XML Security for Java) 1.5. This release is intended to be the last major development release on the 1.6.x branch. There are exciting plans for WSS4J 2.0 which I will describe shortly. Here is a summary of some of the main features of this release: 

1) Apache Santuario (XML Security for Java) 1.5.1 upgrade

WSS4J has upgraded the Santuario dependency from 1.4.6 to 1.5.1 and hence picks up the following relevant new features:
  • Support for GCM algorithms has been added via a third-party JCE provider (e.g. BouncyCastle). I will describe this in more detail in a future blog post.
  • Support for Key Transport Algorithms with strong digests is available.
  • More secure validation of incoming signed requests is performed.
  • Better protection against signature wrapping attacks is available.
For more information on the new features associated with Santuario 1.5.0 see here. WSS4J picks up Santuario 1.5.1 which fixes a number of important issues in the 1.5.0 release. 

2) Improvements in validating SAML Assertions

WSS4J contains the following improvements related to validating SAML Assertions:
  • Validation of SAML Condition NotBefore/NotOnOrAfter dates.
  • Validate the received Assertion against the schema/specs.
A bug has also been fixed when creating a SAML Token where the NotOnOrAfter Condition is not set correctly in some cases.  

3) Improvements relating to certificate revocation

There are a number of fixes relating to certificate revocation:
  • Revocation is not performed if the certificate is contained in the keystore.
  • Revocation is now supported before encryption on the sending side.

Friday, March 2, 2012

Apache Santuario (XML Security for Java) 1.5.1 released

Apache Santuario (XML Security for Java) 1.5.1 has been released and is available for download. The release notes are available here. This release fixes two important bugs - a bug in XMLSignatureInput when using a BufferedInputStream, as well as a bug which caused 1.5.0 to continue to require Xalan. It also contains some performance improvements for encryption and decryption.