CVE-2014-4172 Workaround Filter

In which I share a Java Servlet Filter that blocks the CVE-2014-4172 illicit proxy vulnerability to which old Java CAS client libraries are prone, as an alternative to upgrading to the latest Java CAS Client 3.3.

What problem is being solved here?

On August 11th 2014, the CAS project disclosed CVE-2014-4172 .

This is a vulnerability in some CAS client libraries whereby an Adversary in possession of a valid Service Ticket can use that Service Ticket to illicitly authenticate to a service other than that the ticket was intended for. That is, this is an illicit proxy vulnerability.

Java CAS Client 3.3.2 and later fixes this vulnerability, and Java CAS Client 3.3.3 also has changes that should restore Servlet 2.5 / Tomcat 6 compatibility that Java CAS Client 3.2.x enjoyed. Java CAS Clients earlier than v 3.3.2 are probably vulnerable.

Upgrading to the latest Java CAS Client is a good way to address this vulnerability in your usages and keeping up with CAS client releases has other advantages, of course. You should probably go ahead and do that.

However. Maybe you've got an application using an older Java CAS Client and you'd like to defer dealing with upgrading to Java CAS Client 3.3. If you're using the renew CAS client feature, for instance, the configuration is a bit different in the 3.3 version, so you'd have to deal with that, and the Maven dependencies are a bit different (you can probably deal with that with <exclude> elements in your Maven pom.xml), but you might conceivably be using some of that SAML support that one excludes to get those dependencies to mesh, and, well, this is more than zero complexity.

Maybe you're using a really old version of a Java CAS Client, maybe the old Yale client or even a third party client, such that switching to the Jasig / Apereo Java CAS Client, well, that's a fair amount of change.

The problem being solved here is blocking the vulnerability for any CAS clients in any Java Servlet web application without having to change that CAS client.

How does this solve the problem?

The CAS protocol expects certain CAS protocol request parameters to have certain kinds of values. The vulnerability involves CAS client libraries improperly handling cases where these request parameters have certain unexpected kinds of values.

This Filter blocks the vulnerability by detecting CAS protocol request parameters having characteristics they ought not to have, and throwing an Exception to abort the request handling in those cases.

How can I locally apply the Filter and thereby block this vulnerability?

Patching your application in place as deployed might or might not be appropriate in your situation. Only you can decide whether you should first do this, or if you should skip to the steps below for patching your source and re-build and re-deploy, or for that matter if you should skip all of this and just upgrade to Java CAS Client v 3.3.2 or later and thereby not need this Filter.

A. Patching an application in place

A.0. Back up your deployed application and stop Tomcat

You should, of course, have a complete backup of your application, including the webapp as deployed into your Servlet container, before making changes.

You should probably also stop your servlet container before making these changes. If you're trying to make these changes in place without restarting, well, then you're probably already expert in doing that for your application and your servlet container, and good luck. :)

A.1. Add the .class file

Grab the RequestParameterEnforcementFilter.class file. (That's the .class file generated from compiling uPortal 4.0-patches as of commit c6e7d82b1380fef72ca772af7964494f4b8e9583 .)

Drop it into the directory

/WEB-INF/classes/org/jasig/portal/security/firewall/

within your web application as deployed to Tomcat (in your Tomcat's webapps directory, presumably).

A.2. Declare the Filter in web.xml

The Filter by default checks all parameters whether they are expected in the CAS protocol or not, but you should configure it to only check the CAS parameters you're using so as to minimize the chance of messing with intended request parameter usages in other aspects of your application. So you end up with a <filter> declaration like

<filter>  
  <filter-name>requestParameterFilter</filter-name>
  <filter-class>org.jasig.portal.security.firewall.RequestParameterPolicyEnforcementFilter</filter-class>
  <init-param>
    <param-name>parametersToCheck</param-name>
    <param-value>ticket SAMLArt pgtIou pgtId</param-value>
  </init-param>
</filter>  

.

If you're just using the traditional CAS protocol without acquiring proxy tickets, you could just check the ticket parameter.

A.3. Map the Filter in web.xml

This is really important: the Filter must be mapped in front of the CAS client filters, servlets, or whatever form your potentially bugged CAS client takes. This means that it must appear above the Java CAS Client filter mappings in web.xml and must cover the same servlets and paths.

For example, uPortal 4.0 uses the CAS Validate Filter mapped as

<filter-mapping>  
  <filter-name>CAS Validate Filter</filter-name>
  <url-pattern>/Login</url-pattern>
</filter-mapping>

<filter-mapping>  
  <filter-name>CAS Validate Filter</filter-name>
  <url-pattern>/CasProxyServlet</url-pattern>
</filter-mapping>  

so therefore the correct requestParameterFilter mapping is

<filter-mapping>  
  <filter-name>requestParameterFilter</filter-name>
  <url-pattern>/Login</url-pattern>
  <url-pattern>/CasProxyServlet</url-pattern>
</filter-mapping>  

.

In applications other than uPortal, the expected request paths to which CAS protocol parameters are presented will differ, or might even be all paths (denoted as

<url-pattern>/*</url-pattern>  

).

Note that the filter-name here must exactly match the filter-name of the filter declaration above.

And note again that the requestParameterFilter filter-mapping MUST be earlier in the web.xml file than the CAS client filter-mappings.

A.4. Restart your servlet container

If you stopped your servlet container to make these changes, of course you'll need to start it again to bring your application back online.

If you're bravely making these changes in place, maybe they'll work, or maybe you'll end up having to re-start your servlet container anyway.

A.5. Verify that the Filter is working

For uPortal, you might test this with a URL like

https://portal.yale.edu/Login?SAMLArt=testvalue%26anothertestvalue  

The request should fail with a stack trace in the log.

B. Adding the Filter to source so that it is included on future builds

In addition to or instead of patching your application in place, you might update the source from which you build to include this Filter.

B.1. Add the Filter Java file to your source directory

Somewhere in your project is your Java source code. Add folders so that the package "org.jasig.portal.security.firewall" is represented, and then add RequestParameterPolicyEnforcementFilter.java to that directory.

In uPortal, this is in uportal-war/src/main/java, so you end up with the path uportal-war/src/main/java/org/jasig/portal/security/firewall/ and then the RequestParameterPolicyEnforcementFilter.java within that folder.

(If you're using uPortal and Git, you could use Git to cherry-pick the commits or even merge the patches branch to pick up this Filter.)

B.2. Optionally, also add the JUnit test

There is a JUnit test. Maybe you want it. Maybe you don't.

B.3. Add the Filter declaration to web.xml

As in step A.2 above.

B.4. Add the Filter mapping to your web.xml

As in step A.3 above.

B.5. Build from source

Build your updated application from its updated source code however you do that. In uPortal, you'd typically do that with mvn package.

B.6. Deploy the new version of your application

Deploy your new web application however you typically do that. In uPortal this typically involves the ant deployWar target (and that target incorporates the building step above so that there's something built available to deploy).

B.7. Verify that the Filter is working

As in step A.5. above.

Why should I trust the linked binary file?

You shouldn't. By all means, build it from source locally. The easiest way to do that is probably to grab and build uPortal's 4.0 patches branch and then grab the .class file that's dropped in the Maven target directory as a result.

How might this solution become cleaner in the future?

There are two promising directions.

The primary area of promise is the cas-server-security-filter project, which might incorporate this Filter and ship a .jar file including it, and that .jar might even become available in Maven Central. Note that the package of the Filter as proposed there differs from the package of the Filter described in this blog post, so pulling in that .jar once it's available won't conflict with the Java class you ad-hoc applied using the instructions here, but the web.xml filter declarations will need to change to declare the new package for the Filter if you switch to that version. Anyway, that should be well documented in that Filter distribution, so follow those instructions when they're available.

The other promising direction is that the Filter will ship in uPortal starting with the 4.0.15 and 4.1.1 releases, so uPortal environments built on those versions and later pick up the Filter class without having to add it.

Of course, adopters of those versions still need to be sure their web.xml actually declares and maps the filter and does so in front of the Java CAS Client filters.

Cover photo: filter : CC-BY-2.0