Archives May 2020

Apache Tomcat RCE by deserialization (CVE-2020-9484) – write-up and exploit

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.

  1. The PersistentManager is enabled and it’s using a FileStore
  2. The attacker is able to upload a file with arbitrary content, has control over the filename and knows the location where it is uploaded
  3. 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 ID
  • JDBCStore: 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“?

  1. Tomcat requests the Manager to check if a session with session ID “../../../../../../tmp/12345” exists
  2. It will first check if it has that session in memory.
  3. It does not. But the currently running Manager is a PersistentManager, so it will also check if it has the session on disk.
  4. It will check at location directory + sessionid + ".session", which evaluates to “./session/../../../../../../tmp/12345.session
  5. If the file exists, it will deserialize it and parse the session information from it
The web application will return HTTP 500 error upon exploitation, because it encounters a malicious serialized object instead of one that contains session information as it expects.

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 a JDBC Store is used instead of a File 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.

And don’t forget to follow us on twitter: @redtimmysec

References

Speeding up your penetration tests with the Jok3r framework – Review

As penetration testers doing tests on web applications and infrastructure, we use a lot of tools to speed up our jobs. We scan the network with nmap, if we find a web server we might fire off nikto and dirbuster and for an exposed RMI port we try remote deserialization attacks with BaRMIe. Still, it’s a sequential activity: we try one tool one-after-another. What if we had a framework that would

  • Have all tools available and up to date
  • Run tools, analyze their output and run other relevant tools

This is the aim of the jok3r framework (https://www.jok3r-framework.com/). According to it’s front page it aims to “automate as much stuff as possible in order to quickly identify and exploit ‘low-hanging fruits’ and ‘quick win’ vulnerabilities on most common TCP/UDP services and most common web technologies”

We put the tool to the test and see if it’s really useful or just a waste of time.

Setting up

Jok3r conveniently runs in a docker container with all tools pre-installed. Setting up is just a matter of running a docker pull command and executing the container. Because a lot of tools are there, the compressed size (what you will pull) is around 9 GB. Uncompressed it takes about 16GB on disk.

Usability

Once pulled, you can run the container which brings you to a bash shell in an ubuntu based image. After that, each command to jok3r has to be given like this:

python3 jok3r.py [command]

That’s a little inconvenient, compared to tools like Metasploit which have their own interactive interpreter. I guess you could write a wrapper yourself, but it’s disappointing that it’s not there by default.

Overview of all tools available

Running python3 jok3r.py toolbox --update-all --fast will auto-update all tools.

Unfortunately after running all updates (which sometimes needed manual confirmations even though –fast parameter was given), jok3r.py didn’t run anymore because of an updated python library (cmd2) that was incompatible. We reported this issue at https://github.com/koutto/jok3r/issues/43

Testing

Jok3r uses the concept of a ‘mission’ to describe a security test. By running python3 jok3r.py db, we get into an interactive shell (so part of the framework does use it.. why not everything?), where we can define the mission name, target IPs, and specific scans we want to enable/disable. It’s also possible to import nmap results from an xml file, but unfortunately we got a parser error when trying to do that.

Once we defined the target, we can run python3 jok3r.py attack -t https://www.example.com/ --add2db <mission> to run all security checks. Jok3r will now run each and every tool suitable for a http endpoint one-by-one (more than 100). It’s smart enough to parse the output of recon tools, so it can skip vulnerability checks and exploits later on. For example, when it finds no instance of a wordpress application, wpscan is skipped.

Starting the security checks on our target

Unfortunately, some tools will hang and have to be killed with ctrl-c. That makes it unsuitable for a fire-and-forget approach, as you have to kill tasks from time to time.

We tested an http service, for which it has about 100 checks. There are checks available for ftp, java-rmi, mysql, oracle, rdp, smb, snmp, ssh and some more smaller services, however the number of checks done for these is very small (around 7 on average). It looks like jok3r is mainly geared towards pen testing web applications.

Reporting

When the scan is finished, you can generate an HTML report which will conveniently list the output of the tools, as well as found vulnerabilities. This interface is very suitable for browsing results, rather than looking at the command line output.

The clickable HTML report lists the output of each tool

Conclusion

The concept of jok3r is very interesting, and using the tool definitely speeds up pen tests. It’s beneficial mainly for infrastructure tests where you need to scan a large number of IPs, which would be a lot of work to do manually. Be aware that the number of services it can scan is limited.

If jok3r was truly fire-and-forget, it would have been a convenient way to get some extra recon done. But unfortunately it depends on 3rd party tools which can crash or hang, and the user has to manually intervene. Therefore, in our opinion it doesn’t add much value over tools like nessus or service scans from nmap.

Hey! Red Timmy Security will be at Blackhat Las Vegas this year too! Check out our trainings!

Practical Web Application Hacking Advanced 1-2 August and 3-4 August 2020.