CAS Vulnerability Disclosure


Remember

This post is NOT new. I am just collecting it here so it’s publicly available. This was originally published as a secret gist on Github in April 2016.

Overview

This is an Apereo CAS project vulnerability disclosure, describing an issue in CAS’s attempts to deserialize objects via the Apache Commons Collections library.

Affected Deployments

The attack vector specifically applies to all deployments of CAS v4.1.x and v4.2.x deployments where the out-of-the-box default configuration of CAS is used for managing object serialization, encryption and signing of data.

You are NOT affected by this issue, if:

  • You have deployed a different CAS version, lower than v4.1.0.
  • You have deployed CAS v4.1.x or v4.2.x, BUT you have removed the default CAS configuration for encryption/signing and have regenerated the appropriate settings for your own deployment.

Exploiting the vulnerability hinges on getting the JVM to de-serialize Java objects from arbitrary serialized data. If the above conditions describe your deployment, we STRONGLY recommend that you take necessary action to patch your deployment based on the below instructions.

Severity

This is a very serious issue where successfully exercising this vulnerability allows the adversary to inject arbitrary code. This disclosure is about a specific exploit path involving a bugged version of Apache Commons Collections. This exploit path is only an instance of a larger JVM Java object deserialization security concern.

Patching

Patch releases are now available to address CAS v4.1.x and v4.2.x deployments. Upgrades to the next patch version for each release should be a drop-in replacement, with some effort to appropriately reconfigure CAS encryption/signing settings via the cas.properties file.

CAS 4.1.x

Overlay

Modify your CAS overlay to point to version 4.1.7.

A snippet of a pom.xml for a CAS overlay follows:

...

<dependencies>
    <dependency>
        <groupId>org.jasig.cas</groupId>
        <artifactId>cas-server-webapp</artifactId>
        <version>${cas.version}</version>
        <type>war</type>
        <scope>runtime</scope>
    </dependency>
</dependencies>

<properties>
    <cas.version>4.1.7</cas.version>
</properties>
...

TGC Settings

Locate your cas.properties file and find the tgc.* settings.

  • If your CAS deployment is NOT using the default encryption/signing keys provided by CAS and you have regenerated new keys and have replaced the default, you can safely ignore this step and leave your key configuration of signing/encryption in place without any further changes.

  • If your CAS deployment IS using the default encryption/signing keys provided by CAS and you have NOT regenerated new keys to replace the default, you MUST take action to regenerate the keys.

You can choose one of the two approaches described below to handle key regeneration.

1) Let CAS Generate Keys

Blank/comment out the following tgc settings:

# tgc.encryption.key=
# tgc.signing.key=

Build and deploy your CAS deployment once. Upon startup, CAS will notice that no keys are defined, and it will appropriately generate keys for you automatically. Your CAS logs will then show the following snippet:

WARN [org.jasig.cas.util.BaseStringCipherExecutor] - <Secret key for encryption is not defined. CAS will attempt to auto-generate the encryption key>
WARN [org.jasig.cas.util.BaseStringCipherExecutor] - <Generated encryption key ABC of size ... . The generated key MUST be added to CAS settings.>
WARN [org.jasig.cas.util.BaseStringCipherExecutor] - <Secret key for signing is not defined. CAS will attempt to auto-generate the signing key>
WARN [org.jasig.cas.util.BaseStringCipherExecutor] - <Generated signing key XYZ of size ... . The generated key MUST be added to CAS settings.>

You should then grab each generated key for encryption and signing, and put them inside your cas.properties file for each now-enabled setting:

tgc.encryption.key=ABC
tgc.signing.key=XYZ

2) Manually Generate Keys

Using a git client, clone and build the following project:

git clone https://github.com/mitreid-connect/json-web-key-generator.git
cd json-web-key-generator
mvn clean package
cd target

# Encryption Key
java -jar json-web-key-generator-0.3-SNAPSHOT-jar-with-dependencies.jar -t oct -s 256

#
# Full key:
# {
#   "kty": "oct",
#   "k": "ABC"
# }
#

# Signing Key
java -jar json-web-key-generator-0.3-SNAPSHOT-jar-with-dependencies.jar -t oct -s 512

# Full key:
# {
#   "kty": "oct",
#   "k": "XYZ"
# }

You should then grab each generated key for encryption and signing, and put them inside your cas.properties file for each now-enabled setting:

tgc.encryption.key=ABC
tgc.signing.key=XYZ

Webflow Settings

Locate your cas.properties file and find the webflow.* settings. If you do not see them in your configuration, go ahead and define them:

# webflow.encryption.key=
# webflow.signing.key=

You can choose one of the two approaches described below to handle key regeneration.

1) Let CAS Generate Keys

Blank/comment out the following webflow settings:

# webflow.encryption.key=
# webflow.signing.key=

Build and deploy your CAS deployment once. Upon startup, CAS will notice that no keys are defined, and it will appropriately generate keys for you automatically. Your CAS logs will then show the following snippet:

WARN [org.jasig.cas.util.BinaryCipherExecutor] - <Secret key for encryption is not defined. CAS will attempt to auto-generate the encryption key>
WARN [org.jasig.cas.util.BinaryCipherExecutor] - <Generated encryption key ABC of size ... . The generated key MUST be added to CAS settings.>
WARN [org.jasig.cas.util.BinaryCipherExecutor] - <Secret key for signing is not defined. CAS will attempt to auto-generate the signing key>
WARN [org.jasig.cas.util.BinaryCipherExecutor] - <Generated signing key XYZ of size ... . The generated key MUST be added to CAS settings.>

You should then grab each generated key for encryption and signing, and put them inside your cas.properties file for each now-enabled setting:

webflow.encryption.key=ABC
webflow.signing.key=XYZ

2) Manually Generate Keys

Using a git client, clone and build the following project:

git clone https://github.com/mitreid-connect/json-web-key-generator.git
cd json-web-key-generator
mvn clean package
cd target

# Encryption Key
java -jar json-web-key-generator-0.3-SNAPSHOT-jar-with-dependencies.jar -t oct -s 96

#
# Full key:
# {
#   "kty": "oct",
#   "k": "ABC"
# }
#

# Signing Key
java -jar json-web-key-generator-0.3-SNAPSHOT-jar-with-dependencies.jar -t oct -s 512

# Full key:
# {
#   "kty": "oct",
#   "k": "XYZ"
# }

You should then grab each generated key for encryption and signing, and put them inside your cas.properties file for each now-enabled setting:

webflow.encryption.key=ABC
webflow.signing.key=XYZ

XML Configuration

If you have manually overridden the cas-servlet.xml file, you will need to make sure the following blocks are present in the configuration:


Note that the Person Directory project requires the following configuration in CAS overlays:

```xml

Note that the Person Directory project requires the following configuration in CAS overlays:

```xml
<bean id="loginFlowStateTranscoder" class="org.jasig.spring.webflow.plugin.EncryptedTranscoder"
        c:cipherBean-ref="loginFlowCipherBean" />

<bean id="loginFlowCipherBean" class="org.jasig.cas.web.flow.CasWebflowCipherBean"
    c:cipherExecutor-ref="webflowCipherExecutor" />

<bean id="webflowCipherExecutor" class="org.jasig.cas.util.BinaryCipherExecutor"
    c:encryptionSecretKey="${webflow.encryption.key:}"
    c:signingSecretKey="${webflow.signing.key:}"/>

Re-adjust the beans accordingly, and remove the built-in keystore.

Finally

Rebuild and redeploy your CAS overlay.

CAS 4.2.x

Modify your CAS overlay to point to version 4.2.1.

A snippet of a pom.xml for a CAS overlay follows:

...

<dependencies>
    <dependency>
        <groupId>org.jasig.cas</groupId>
        <artifactId>cas-server-webapp</artifactId>
        <version>${cas.version}</version>
        <type>war</type>
        <scope>runtime</scope>
    </dependency>
</dependencies>

<properties>
    <cas.version>4.2.1</cas.version>
</properties>
...

TGC Settings

Locate your cas.properties file and find the tgc.* settings.

  • If your CAS deployment is NOT using the default encryption/signing keys provided by CAS and you have regenerated new keys and have replaced the default, you can safely ignore this step and leave your key configuration of signing/encryption in place without any further changes.

  • If your CAS deployment IS using the default encryption/signing keys provided by CAS and you have NOT regenerated new keys to replace the default, you MUST take action to regenerate the keys.

You can choose one of the two approaches described below to handle key regeneration.

1) Let CAS Generate Keys

Blank/comment out the following tgc settings:

# tgc.encryption.key=
# tgc.signing.key=

Build and deploy your CAS deployment. Upon startup, CAS will notice that no keys are defined, and it will appropriately generate keys for you automatically. Your CAS logs will then show the following snippet:

WARN [org.jasig.cas.util.BaseStringCipherExecutor] - <Secret key for encryption is not defined. CAS will attempt to auto-generate the encryption key>
WARN [org.jasig.cas.util.BaseStringCipherExecutor] - <Generated encryption key ABC of size ... . The generated key MUST be added to CAS settings.>
WARN [org.jasig.cas.util.BaseStringCipherExecutor] - <Secret key for signing is not defined. CAS will attempt to auto-generate the signing key>
WARN [org.jasig.cas.util.BaseStringCipherExecutor] - <Generated signing key XYZ of size ... . The generated key MUST be added to CAS settings.>

You should then grab each generated key for encryption and signing, and put them inside your cas.properties file for each now-enabled setting:

tgc.encryption.key=ABC
tgc.signing.key=XYZ

Rebuild and redeploy your CAS overlay.

2) Manually Generate Keys

Using a git client, clone and build the following project:

git clone https://github.com/mitreid-connect/json-web-key-generator.git
cd json-web-key-generator
mvn clean package
cd target

# Encryption Key
java -jar json-web-key-generator-0.3-SNAPSHOT-jar-with-dependencies.jar -t oct -s 256

#
# Full key:
# {
#   "kty": "oct",
#   "k": "ABC"
# }
#

# Signing Key
java -jar json-web-key-generator-0.3-SNAPSHOT-jar-with-dependencies.jar -t oct -s 512

# Full key:
# {
#   "kty": "oct",
#   "k": "XYZ"
# }

You should then grab each generated key for encryption and signing, and put them inside your cas.properties file for each now-enabled setting:

tgc.encryption.key=ABC
tgc.signing.key=XYZ

Webflow Settings

Locate your cas.properties file and find the webflow.* settings. If you do not see them in your configuration, go ahead and define them:

# webflow.encryption.key=
# webflow.signing.key=

You can choose one of the two approaches described below to handle key regeneration.

1) Let CAS Generate Keys

Blank/comment out the following webflow settings:

# webflow.encryption.key=
# webflow.signing.key=

Build and deploy your CAS deployment once. Upon startup, CAS will notice that no keys are defined, and it will appropriately generate keys for you automatically. Your CAS logs will then show the following snippet:

WARN [org.jasig.cas.util.BinaryCipherExecutor] - <Secret key for encryption is not defined. CAS will attempt to auto-generate the encryption key>
WARN [org.jasig.cas.util.BinaryCipherExecutor] - <Generated encryption key ABC of size ... . The generated key MUST be added to CAS settings.>
WARN [org.jasig.cas.util.BinaryCipherExecutor] - <Secret key for signing is not defined. CAS will attempt to auto-generate the signing key>
WARN [org.jasig.cas.util.BinaryCipherExecutor] - <Generated signing key XYZ of size ... . The generated key MUST be added to CAS settings.>

You should then grab each generated key for encryption and signing, and put them inside your cas.properties file for each now-enabled setting:

webflow.encryption.key=ABC
webflow.signing.key=XYZ

2) Manually Generate Keys

Using a git client, clone and build the following project:

git clone https://github.com/mitreid-connect/json-web-key-generator.git
cd json-web-key-generator
mvn clean package
cd target

# Encryption Key
java -jar json-web-key-generator-0.3-SNAPSHOT-jar-with-dependencies.jar -t oct -s 96

#
# Full key:
# {
#   "kty": "oct",
#   "k": "ABC"
# }
#

# Signing Key
java -jar json-web-key-generator-0.3-SNAPSHOT-jar-with-dependencies.jar -t oct -s 512

# Full key:
# {
#   "kty": "oct",
#   "k": "XYZ"
# }

You should then grab each generated key for encryption and signing, and put them inside your cas.properties file for each now-enabled setting:

webflow.encryption.key=ABC
webflow.signing.key=XYZ

Finally

Rebuild and redeploy your CAS overlay.

Clustered CAS Deployments

If you are running a cluster of CAS nodes, please be advised that the newly generated keys for all settings (regardless of the method of generation, whether CAS or you) MUST be shared with all CAS nodes in form of either a centralized or replicated/shared cas.properties file.

Failure to do so will completely break CAS functionality.

If you only have a single-node CAS deployment, there is nothing further for you to do.

Support

If you have questions on the details this vulnerability and how it might be reproduced, please contact security@apereo.org or cas-appsec-public@apereo.org.

Resources

Misagh Moayyed

Related Posts

Apereo CAS - Microsoft Office 365 SAML2 Integration

Learn how to integrate Microsoft Office 365 with Apereo CAS running as a SAML2 identity provider.

Apereo CAS - HappyFox SAML2 Integration

Learn how to integrate HappyFox with Apereo CAS running as a SAML2 identity provider.

Apereo CAS - Cisco Webex SAML2 Integration

Learn how to integrate Cisco Webex with Apereo CAS running as a SAML2 identity provider.

Apereo CAS - VMware Identity Manager SAML2 Integration

Learn how to integrate VMware Identity Manager with Apereo CAS running as a SAML2 identity provider.

CAS 6.0.0 RC4 Feature Release

...in which I present an overview of CAS 6.0.0 RC4 release.

Apereo CAS - Scripting Multifactor Authentication Triggers

Learn how Apereo CAS may be configured to trigger multifactor authentication using Groovy conditionally decide whether MFA should be triggered for internal vs. external access, taking into account IP ranges, LDAP groups, etc.

Apereo CAS 6.0.x - Building CAS Feature Modules

An overview of how various CAS features modules today can be changed and tested from the perspective of a CAS contributor working on the codebase itself to handle a feature request, bug fix, etc.

CAS 6.0.x Deployment - WAR Overlays

Learn how to configure and build your own CAS deployment via the WAR overlay method, get rich quickly, stay healthy indefinitely and respect family and friends in a few very easy steps.

Apereo CAS - Jib at CAS Docker Images

Learn how you may use Jib, an open-source Java containerizer from Google, and its Gradle plugin to build CAS docker images seamlessly without stepping too deep into scripting Dockerfile commands.

Apereo CAS 6 - Administrative Endpoints & Monitoring

Gain insight into your running Apereo CAS 6 deployment in production. Learn how to monitor and manage the server by using HTTP endpoints and gather metrics to diagnose issues and improve performance.