10.01.2022 von Joscha Cepok

The most recent version of Apache Tomcat (9.0.56) is vulnerable to session hijacking attacks. A log function enabled by default logs the complete cookie content of the client under certain circumstances. This includes potentially sensitive cookie content such as JSON Web Tokens (JWT). Cloud architecture and microservices increase the severity of the problem. This article shows how the problem occurs and how to patch correctly.

Logging by Libs & Frameworks

Developers use logs throughout their daily work to support them in tracking processes, errors and bugs. What may and may not be logged is defined by the European General Data Protection Regulation GDPR. Above all, personal data may not be logged directly, but only via references. Libraries such as Log4J are often used to avoid writing your own logging system. Log4J in particular has been getting a lot of attention since the CVE in December 2021. However, there are numerous libraries and frameworks that log data, especially in the event of an error. This article takes a closer look at Apache Tomcat Web Server and how it logs and explains how it potentially leads to sensitive data being captured in an easily accessible manner.

Apache Tomcat Web Server is, as the name suggests, a server that is primarily used for HTTP(S) communication. On the client side data is packed, on the server side extracted. The communication is encrypted, a data loss in the network is accordingly unlikely. On the server, the data is extracted and converted. Errors may occur if the client has not encoded everything as the server expects. In this case the cookie header is relevant. It may contain sensitive information. How do you deal with it if it does not meet the expectations and the cookie parser cannot interpret it completely? In this case the following error message is issued by Tomcat:

cookie.invalidCookieValue=A cookie header was received that contained an invalid cookie [{0}]. That cookie will be ignored.

The placeholder {0}, which makes it possible to understand why the parsing failed, needs a little more attention.

Hijacking a session

Logging {0} in case of an error means that invalid cookie values will cause all cookies to be logged. This can be dramatic if the cookie header contains a JSON Web Token that is used to identify an authenticated person – content that should only be visible on the client and nowhere else. If this token does not contain any attributes apart from the best practice, which ensures that the cookie can only be used on the client, anyone who has access to it can hijack that session. For this, not much more is necessary than to store the cookie manually in the developer console accordingly in the client under the correct domain, path and with the appropriate flags. How does this work? Let's take a closer look at the JSON Web Token, which usually looks like this:

eyJhbGciOiJSUzUxMiJ9.eyJpZCI6Im15UmVmZXJlbmNlIiwidmFsaWRVbnRpbCI6IjIwMjEtMDEtMTEgMTM6MzciLCJncm91cHMiOiJkZXYsYWRtaW4sc3VwcG9ydCx2aWV3T25seSJ9.jCurOHz-RwdSU6FuqxuhXgFQ6RlZzOjLOE2QQ9-eD_LWAlTPnoEY9LgoCSY8m65AXY2Ln12Nr3NPtIQmSDqGopESp9eO9MSC--SWWJNFWTd-lhyuyUkNWukJwybWWJ7gHRsEfdgVxet_8KmTQRij0VqHkQxHEmY-kaDQpBzHgbfJr3Z6quQ5hCaxLKGUKrcOIUBZGq4I3EM7GVuzaUm_JF5tKTBSe8pgVVHbvIF4IXBxFXLbPDfevjSrJV0Ao1psTp8Wr5MeqnVHBp5PPKn7CiAtJ_yPec5IfBlNb4WBshO_oah2ywcrqxyGSr2Jwsmsrw3q5kTU87Ooo7AKgAajJw

The structure is the following: encoding.content.signature. This is only an encoded and unencrypted form. The token can be decoded on sites like jwt.io. The signature ensures that the token has not been tampered with. The decoded content looks like this:

{
    "id": "myReference",
    "validUntil": "2021-01-11 13:37",
    "groups": "dev,admin,support,viewOnly"
}

The content reveals the person, privileges and valid session length. This is precisely the core problem: the cookie is logged in plain text and can therefore be easily copied and used by anyone without client binding.
In the public part of the platform, it can be used to navigate through the platform as a client, and in the administrative back-office systems, depending on privileges, it can systematically trigger actions to sabotage operations or tap data.
This problem was already discovered by Jamie Tanna and documented in his blog. In a direct exchange with Tanna, it became clear that the problem is significantly exacerbated by other boundary conditions and thereby the severity of the problem only becomes visible.

Does this affect me?

All systems that use Apache Tomcat Web Server and use client-side cookies for identification may be affected.

Two conditions must be fulfilled for session information to be tapped:

  1. Clients send malformed cookies
  2. Tomcat logs this cookie information in plain text

In this case, sending malformed cookies results in cookie content being logged in plain text. This is because the Tomcat cookie parser logs the entire content instead of just the misformatted portion of the cookie header. For example, a cookie header like this

01.01.1970;cookie1=value1;sensitiveCookie=jsonWebToken

already causes Tomcat's own cookie parser to fail to read the last value. Since it is not a key-value pair Tomcat logs the following line:

A cookie header was received that contained an invalid cookie [01.01.1970;cookie1=value1;sensitiveCookie=jsonWebToken]. That cookie will be ignored.

All persons who can read the log are now able to impersonate someone else with this cookie. In the default configuration, this entry is logged at the INFO level at server startup, and then only as a DEBUG.

In cloud-native architectures using microservices this behavior leads to seeing not just one INFO message every few days, but multiples of that per day. When this logging strategy was adopted in 2014, server restarts were still rare and the approach acceptable. However, it has not aged well as processes have changed, making server restarts commonplace.

The contributing factors are:

  • Continuous Delivery (multiple deployments per day)
  • simultaneous operation in multiple server centers (failover)
  • multiple instances per zone

How do I fix the problem?

There are several ways to fix the problem:

  • Replace the converter
  • suppress the log line or
  • modify the error message.

In this article only a lightweight solution will be considered, as it is completely sufficient - namely to simply suppress the log line by modifying the configuration:

logging.level.org.apache.tomcat.util.http.parser.Cookie: OFF

If the logger is located under a different path, this must be adjusted accordingly.

Conclusion

Tomcat's default cookie converter can log sensitive information, but by simply suppressing the error message, the attack can be prevented quickly and efficiently. If systems are affected that use a JSON Web Token, it is worth considering following best practices and storing attributes in the content to ensure that the cookie only works on the client.

Update from 14 January 2022

The Apache Tomcat dev team has now analyzed the issue. They came to the conclusion to not treat it as a CVE:

“Our only official feedback on your publication is that we do not consider it a security vulnerability that warrants a CVE, coordinated disclosure”.

Regardless, the behavior was changed on 10 January. Now, in case of an error only malformed cookies are logged. These changes are sufficient, to prevent sensitive cookies to be logged. The change is expected to make it into the next Tomcat release.


You are viewing the English version of this article. Click here to change to the German version.

Der Autor