A few days ago, a new remote code execution vulnerability was disclosed for Apache Tomcat. Affected versions are:
- Apache Tomcat 10.x < 10.0.0-M5
- Apache Tomcat 9.x < 9.0.35
- Apache Tomcat 8.x < 8.5.55
- Apache Tomcat 7.x < 7.0.104
In other words, all versions of tomcat 7, 8, 9 and 10 released before April 2020. This most certainly means you have to update your instance of tomcat in order not to be vulnerable.
Prerequisites
There are a number of prerequisites for this vulnerability to be exploitable.
- The
PersistentManager
is enabled and it’s using aFileStore
- The attacker is able to upload a file with arbitrary content, has control over the filename and knows the location where it is uploaded
- There are gadgets in the
classpath
that can be used for a Java deserialization attack
Tomcat PersistentManager
First some words about the PersistentManager
. Tomcat uses the word “Manager” to describe the component that does session management. Sessions are used to preserve state between client requests, and there are multiple decisions to be made about how to do that. For example:
- Where is the session information stored? In memory or on disk?
- In which form is it stored? JSON, serialized object, etc.
- How are sessions IDs generated?
- Which sessions attributes do we want to preserve?
Tomcat provides two implementations that can be used:
- org.apache.catalina.session.StandardManager (default)
- org.apache.catalina.session.PersistentManager
The StandardManager
will keep sessions in memory. If tomcat is gracefully closed, it will store the sessions in a serialized object on disk (named “SESSIONS.ser
” by default).
The PersistentManager
does the same thing, but with a little extra: swapping out idle sessions. If a session has been idle for x seconds, it will be swapped out to disk. It’s a way to reduce memory usage.
You can specify where and how you want swapped sessions to be stored. Tomcat provides two options:
FileStore
: specify a directory on disk, where each swapped session will be stored as a file with the name based on the session IDJDBCStore
: specify a table in the database, where each swapped session will be stored as individual row
Configuration
By default, tomcat will run with the StandardManager
enabled. An administrator can configure to use the PersistentManager
instead, by modifying conf/context.xml
:
<Manager className="org.apache.catalina.session.PersistentManager"
maxIdleSwap="15">
<Store className="org.apache.catalina.session.FileStore"
directory="./session/" />
</Manager>
When there is no Manager
tag written in context.xml
, the StandardManager
will be used.
The exploit
When Tomcat receives a HTTP request with a JSESSIONID
cookie, it will ask the Manager
to check if this session already exists. Because the attacker can control the value sent in the request, what would happen if he put something like “../../../../../../tmp/12345
“?
- Tomcat requests the
Manager
to check if a session with session ID “../../../../../../tmp/12345
” exists - It will first check if it has that session in memory.
- It does not. But the currently running
Manager
is aPersistentManager
, so it will also check if it has the session on disk. - It will check at location
directory + sessionid + ".session"
, which evaluates to “./session/../../../../../../tmp/12345.session
“ - If the file exists, it will deserialize it and parse the session information from it
From the line in the stacktrace of the above image marked in red we see that the PersistentManager
tries to load the session from the FileStore
. The blue line then shows that it tries to deserialize the object. The error is thrown after deserialization succeeded but when it tried to interpret the object as a session (which it is not). The malicious code has already been executed at that point.
Of course, all that is left to exploit the vulnerability is for the attacker to put a malicious serialized object (i.e. generated by ysoserial) at location /tmp/12345.session
It doesn’t make much sense to create an exploit as it’s just one HTTP request. There is however a very quick and convenient PoC written by masahiro311, see this GitHub page.
Conclusion
This attack can have high impact (RCE), but the conditions that need to be met make the likelihood of exploitation low.
PersistentManager
needs to be enabled manually by the tomcat administrator. This is likely to happen only on websites with high traffic loads (but not too high, as it will be more likely that aJDBC Store
is used instead of aFile Store
)- The attacker has to find a separate file upload vulnerability to place the malicious serialized file on the server.
- There have to be libraries on the
classpath
which are vulnerable to be exploited by a Java deserialization attack (e.g. gadgets).
However, a large range of versions of tomcat are affected.
To learn more about advanced web application attacks like these, register for our virtual course at BlackHat USA 2020: Practical Web Application Hacking Advanced.
Source:
Stay connected