The Log4Shell vulnerability exposed a remote code execution condition in multiple versions of the popular Apache Log4J2 logging library. Disclosure of the vulnerability and patch release were followed shortly by broad exploitation. Attackers reportedly ranged from hobbyists to mature adversaries. Obfuscation of attack traffic and sophisticated weaponization of the exploit soon followed.
Companies were faced with the task of identifying whether any impacted version of Log4J2 was packaged in Java applications running in their environment. This included custom built applications, open source projects and commercial solutions. Given the continuing popularity of the Java programming language the scope of the problem is significant.
Identifying vulnerable Log4J2 components in custom code, and in environments built through Infrastructure as Code, solves part of the problem scope. However, the issue caused reverberations across the technology and information security communities as it highlighted the difficulty of identifying libraries and frameworks packaged into running Java applications.
Scanning is not enough. Detecting Log4J2 files on the filesystem is insufficient for proving vulnerability or exploitability. Java libraries can be packaged inside executables, where names or hashes of files on the file system are not indicative of absence of the library. Additionally, setting up dynamic testing to determine exploitability is non-trivial and insufficient to identify vulnerability.
In collaboration with FOX Corporation, Praetorian developed a client and reporting server to identify systems vulnerable to Log4j at scale. This work is based on Stripe’s Remediation Tools, but with additional support for Windows endpoints, in depth fingerprints, and a server for collecting the results for a more deployment-friendly rollout.
The tool is divided up into three components, the detector, responsible for examining a target and determining if there is a currently-running java process that has loaded a vulnerable version of Log4j, the server, responsible for collecting the results, and a log reader, which can quickly parse the server messages and output a list of reported vulnerable hosts.
The inspiration for the improvements to this tool came from Praetorian’s collaboration with FOX Corporation, who suggested that a server component would allow IT teams to quickly deploy and collect the results across a number of different environments.
Additionally, this fingerprinting process can be done on any Java dependency, paving the way for future issues to be rapidly discovered and reported on in the same way.
How it Works
Like the Stripe tool that foreran this project, the detector locates Java processes on the target host and then lists all open files and checks them for the log4j jar. Once found, it will attempt to compare that JAR with known vulnerable versions of log4j. We have compiled a list of fingerprints for every Log4j JAR distributed by Apache. Additionally, we’ve fingerprinted each class unique to each version of Log4j to improve detection of a vulnerable instance.
For example, in Log4j 2.15.0, the
org.apache.logging.log4j.core.net.JndiManager class was updated to add code that allowlists the JNDI protocol, hostname, and class name. In 2.16.0, this class was updated again to add the
isJndiEnabled method, allowing JNDI to be disabled by default. Both of these changes resulted in a unique SHA256 hash of the underlying compiled class file in the JAR. We built an internal tool which searches for all unique class file hashes and uses these to identify Log4j versions in cases where the JAR is inlined or modified from the Apache version.
To maximize the number of successful detector runs, the tool is designed to handle various endpoint network configurations. At a high level, there are three types of network restrictions companies might encounter:
- No egress to the Internet (e.g. a system in an isolated network)
- Limited egress to the Internet (e.g. firewall rules allowing outbound web traffic only)
- No line of sight to internal systems (e.g. an employee laptop that is WFH)
To optimize for these three main cases, companies can deploy two instances of the report server. One to an internal system and one to a public cloud environment. A machine with network restrictions #1 or #2 could use the internal system, provided that the security team added firewall rules to access this system. A machine with no line of sight to internal systems could use the cloud hosted reporting server.
Both reporting servers can aggregate results locally and send real-time data to the same endpoint for further processing. By splitting the servers, companies can reach more endpoints for analysis while still centralizing reporting and correlation of results.
For endpoint deployment, Go’s ability to provide statically-linked binaries for a number of different OS/architecture combinations maximizes the coverage across networks. This also allows for the rapid development of deployment artifacts, as any IT stack can drop a single binary onto a target and run it. This makes deployment of the tool via IT monitoring and endpoint tools like Tanium/SCCM/Ansible/Puppet/Chef extremely straightforward. Additionally,to improve failure resiliency, the client output can be redirected to a file on the local system and collected via the same IT stack if the client/server model is not usable for a target environment.
Go to the Github Repo