CASFilter

Using CASFilter

See Using CASFilter for configuration and usage instructions.

CASFilter FAQ

Why do I have to configure the CASFilter explicitly with the name of the protected server or service?

Shawn's explanation

The README of the Java Servlet filter states that it would be more secure to specify the server name

edu.yale.its.tp.cas.client.filter.serverName
for the protected service explicitly than determining it automatically.

What exactly are the security issues that have been considered here?

The only way to determine the hostname "automatically" is to rely on the HTTP request's "Host" header, which is under the control of the client. Service X could receive an otherwise legitimate service ticket for service X, and it could then pass this service ticket onto client Y but pass the HTTP host header "Host: X". Service Y will then validate the ticket against CAS reporting that it's service X; CAS will determine that the ticket matches X and respond with a positive authentication. This allows an illicit proxy from service X to service Y. (Note that the end user would need to visit service X for the exploit to work; service X wouldn't be able to compromise service Y with respect to artibrary users' authentications.)

The clients (not just the filter) address this problem by requiring either a statically configured hostname or a statically configured service URL. There are other ways around this exploit (e.g., it won't work on a web server configured to respond only to one particular hostname, but this is atypical), but explicit configuration in the clients was deemed to be most likely to lead to a secure result.

This is explained in more detail in the "HISTORY" file that comes with the CAS client distribution. Note that an appropriately written client gives the user no choice; you say the README says "it would be more secure" to set the service URL manually, but with respect to end users of the filter, this is a requirement, not a recommendation. (The filter will fail to run unless you configure a hostname or a URL.)

Andrew's explanation

Suppose the Adversary builds or compromises web application A.

Suppose you deploy web application B, which trusts the "host" header to assert the host.

A uses CAS authentication. The user U visits A, authenticates via CAS, obtains a service ticket TA to access A.

So far, so good. The user exposed her username and password to CAS server, not to A, so the Adversary didn't get the password.

The service associated wiith TA is A. The Adversary could have specified service B at CAS login, but then CAS would have redirected back to B with TB, and A wouldn't have the opportunit to intercept TB. A can only obtain TA.

However, instead of validating TA, A presents TA to B, forging the host header on the request to indicate a host of A.

B validates TA, specifying to CAS a host of A, because B believes it is A (trusted the HOST header asserting this). So the validation succeeds. Adversary's application A has successfully authenticated as U to B.

Applications must assert the service identifier on ticket validation to ensure that the ticket they are validating was intended to authenticate to the application validating the ticket. Allowing the web client presenting the service ticket to assert the hostname, to effectively assert the service identifier, defeats this protection.

And another explanation

The exploit involves the user authenticating to Host A, which instead of validating the ticket forges a request to Host B with a Host: header indicating A, and thereby executes an illicit proxy to Host B, authenticating as the user to host B despite the end user not having acquired a service ticket for B and host A not having acquired a PGT, PT targetted to B, B having had a chance to validate that PT and decide whether A is an authorized proxy, in the usual way.

If B relies on the Host header, then A can forge the request such that B believes that it (B) is A, and so A can use service (or proxy) tickets intended to authenticate to A to instead illicitly authenticate to B.

B's defense against this attack is stalwart self-awareness. By knowing that it is B, it will name itself as B when validating tickets with CAS, and so the CAS server will fail to validate tickets issued for the purpose of authenticating to A when B attempts to validate them.

Originally answered by Shawn Bayern on the CAS mailing list.

How do I use the authorizedProxy parameter to CASFilter?

The authorizedProxy must be the url to which CAS sends the proxy granting ticket. CAS actually validates the certificate at this url. The applicaton in the middle tier uses ProxyTicketReceptor servlet to receive the proxy granting ticket. This is the url you supply to the CASFilter as an authorized proxy to instruct it to accept authentication proxied using proxy tickets derived from ProxyGrantingTickets sent to that authorizedProxy URL by CAS.

New with casclient 2.0.11, you can specify multiple authorized proxies as a whitespace-delimited list.

Originally answered by: Susan Bramhall on the CAS mailing list.

Why doesn't the CASFilter allow me to consider the entire proxy chain?

A: Why does the CASFilter only allow me to configure a list of authorized most previous proxies? I want to use some other criteria, considering, say, the entire proxy chain in determining whether to accept proxied authentication.

Is there a particular reason that the multiple proxy check only looks at the first proxy from ProxyTicketValidator.getProxyList()? It seems to me that you'd want to check every one of the proxies in the list, not just the first one.

Answer:
Not quite right:
Andrew Petro wrote:

I think the thought is something like this: each successive service to which authentication is proxied need only check the previous entry in the proxy chain. It was the responsibility of the previous entry in the chain (which I'm deciding to trust) to decide whether to trust whatever service it was that proxied credentials to it.

A better thought:
Shawn Bayern wrote:

Hi Andrew -

I could see how you might interpret the old version of the filter as suggesting this intent, but the simple answer is that it's really just a limitation in the functionality of the filter and ought to be adjusted by someone who has time to think through the best way of offering the appropriate level of configurability. As you know quite well, we didn't spend a lot of time on making the filter configurable in the past.

CAS specifically makes the whole proxy chain available via proxyValidate because any service, at any stage, might want to use the whole chain (or any part of it) to inform its access-control determinations. The mechanism was designed specifically with the expectation that the final client (the last back-end system) would be able to make access-control determinations using the whole chain. If you have time, the filter should reflect this design.

Update:
New with Java CAS Client 2.1.0, the CASFilter exposes the entire proxy chain as part of the CASReceipt it places into the session. Subsequent filters, servlets, or even JSP pages can examine this CASReceipt and the associated List of services through which authentication was proxied.

Meta information:

This question originally asked and answered on the CAS list by Bill Dimmick, Shawn Bayern, and Andrew Petro.