Hot Fixing Log4j JNDI in Java 1.6+ (No updates required)
As corporations continue to deal with patching and updating their systems to deal with log4shell, there are many systems which will become quite a challenge. As the vast majority of you are already aware, a new series of vulnerabilities came out recently targeting the usage of log4j and its built-in functionality to perform JNDI lookups. What is log4j though?
Log4j is an Apache maintained Java library for logging system messages from running code. Log4j has been used for years as the universal standard for outputting messages to system log files in a formatted way.
Recently however, an issue was discovered that could allow attackers to gain access to the machine running the given Java instance. How does this vulnerability work? Like an SQL injection attack, this attack requires that a variable (which is accessible to an attacker) be embedded in a Log4j message. For example, if an HTTP parameter were to be captured by a Log4j logger instance…
In the example above, whatever the user-agent was currently set to would be logged by Log4j. If that user-agent included a malicious JNDI lookup string, game over! The target machine would have likely been successfully broken into. So how do we stop this? Update log4j? Make configuration changes? Update our code to?
The reality in most environments is even if you could update Log4j, there will be a subset of applications so old that the code base is missing. Maybe you’re running a COTS (commercial-off-the-shelf) product and you’re waiting for a fix but don’t know when (or if) it will arrive. Moreover, updating a package or modification to an existing codebase can require robust testing and approval from a change control board. What do we do to act quickly here?
I cannot take credit for this fix, but I am happy to spread the word around and help expand upon it and answer questions where necessary. Years ago, I wrote a byte-code injection framework (SecurePaaS) that could modify classes and inject security controls related to single-sign-on and authorization controls. Over the first initial days I thought of ways to patch this issue through a similar method but apparently NCC had already beaten me to the punch. However, it appears no one is talking about this!
For those of you unfamiliar NCC is a security research group. They have published an essential hot fix that leverages byte-code injection to:
- Disable the internal method handler for jndi: format strings (“lookups”).
- Log a message to System.err (i.e stderr) indicating that a log4j JNDI attempt has been made (including the format string attempted, with any ${} characters sanitized to prevent transitive injections).
- Resolve the format string to “(log4j jndi disabled)” in the log message (to prevent transitive injections).
This fix is deployed as a java agent which can be used with Java 1.6 and later. It does not require system updates nor code changes of any kind. How does it work you say? Lets take a look at the code:
In the example above, whatever the user-agent was currently set to would be logged by Log4j. If that user-agent included a malicious JNDI lookup string, game over! The target machine would have likely been successfully broken into. So how do we stop this? Update log4j? Make configuration changes? Update our code to?
The reality in most environments is even if you could update Log4j, there will be a subset of applications so old that the code base is missing. Maybe you’re running a COTS (commercial-off-the-shelf) product and you’re waiting for a fix but don’t know when (or if) it will arrive. Moreover, updating a package or modification to an existing codebase can require robust testing and approval from a change control board. What do we do to act quickly here?
I cannot take credit for this fix, but I am happy to spread the word around and help expand upon it and answer questions where necessary. Years ago, I wrote a byte-code injection framework (SecurePaaS) that could modify classes and inject security controls related to single-sign-on and authorization controls. Over the first initial days I thought of ways to patch this issue through a similar method but apparently NCC had already beaten me to the punch. However, it appears no one is talking about this!
For those of you unfamiliar NCC is a security research group. They have published an essential hot fix that leverages byte-code injection to:
- Disable the internal method handler for jndi: format strings (“lookups”).
- Log a message to System.err (i.e stderr) indicating that a log4j JNDI attempt has been made (including the format string attempted, with any ${} characters sanitized to prevent transitive injections).
- Resolve the format string to “(log4j jndi disabled)” in the log message (to prevent transitive injections).
This fix is deployed as a java agent which can be used with Java 1.6 and later. It does not require system updates nor code changes of any kind. How does it work you say? Lets take a look at the code:
In the example above, whatever the user-agent was currently set to would be logged by Log4j. If that user-agent included a malicious JNDI lookup string, game over! The target machine would have likely been successfully broken into. So how do we stop this? Update log4j? Make configuration changes? Update our code to?
The reality in most environments is even if you could update Log4j, there will be a subset of applications so old that the code base is missing. Maybe you’re running a COTS (commercial-off-the-shelf) product and you’re waiting for a fix but don’t know when (or if) it will arrive. Moreover, updating a package or modification to an existing codebase can require robust testing and approval from a change control board. What do we do to act quickly here?
I cannot take credit for this fix, but I am happy to spread the word around and help expand upon it and answer questions where necessary. Years ago, I wrote a byte-code injection framework (SecurePaaS) that could modify classes and inject security controls related to single-sign-on and authorization controls. Over the first initial days I thought of ways to patch this issue through a similar method but apparently NCC had already beaten me to the punch. However, it appears no one is talking about this!
For those of you unfamiliar NCC is a security research group. They have published an essential hot fix that leverages byte-code injection to:
- Disable the internal method handler for jndi: format strings (“lookups”).
- Log a message to System.err (i.e stderr) indicating that a log4j JNDI attempt has been made (including the format string attempted, with any ${} characters sanitized to prevent transitive injections).
- Resolve the format string to “(log4j jndi disabled)” in the log message (to prevent transitive injections).
This fix is deployed as a java agent which can be used with Java 1.6 and later. It does not require system updates nor code changes of any kind. How does it work you say? Lets take a look at the code:
In the example above, whatever the user-agent was currently set to would be logged by Log4j. If that user-agent included a malicious JNDI lookup string, game over! The target machine would have likely been successfully broken into. So how do we stop this? Update log4j? Make configuration changes? Update our code to?
The reality in most environments is even if you could update Log4j, there will be a subset of applications so old that the code base is missing. Maybe you’re running a COTS (commercial-off-the-shelf) product and you’re waiting for a fix but don’t know when (or if) it will arrive. Moreover, updating a package or modification to an existing codebase can require robust testing and approval from a change control board. What do we do to act quickly here?
I cannot take credit for this fix, but I am happy to spread the word around and help expand upon it and answer questions where necessary. Years ago, I wrote a byte-code injection framework (SecurePaaS) that could modify classes and inject security controls related to single-sign-on and authorization controls. Over the first initial days I thought of ways to patch this issue through a similar method but apparently NCC had already beaten me to the punch. However, it appears no one is talking about this!
For those of you unfamiliar NCC is a security research group. They have published an essential hot fix that leverages byte-code injection to:
- Disable the internal method handler for jndi: format strings (“lookups”).
- Log a message to System.err (i.e stderr) indicating that a log4j JNDI attempt has been made (including the format string attempted, with any ${} characters sanitized to prevent transitive injections).
- Resolve the format string to “(log4j jndi disabled)” in the log message (to prevent transitive injections).
This fix is deployed as a java agent which can be used with Java 1.6 and later. It does not require system updates nor code changes of any kind. How does it work you say? Lets take a look at the code:
In the example above, whatever the user-agent was currently set to would be logged by Log4j. If that user-agent included a malicious JNDI lookup string, game over! The target machine would have likely been successfully broken into. So how do we stop this? Update log4j? Make configuration changes? Update our code to?
The reality in most environments is even if you could update Log4j, there will be a subset of applications so old that the code base is missing. Maybe you’re running a COTS (commercial-off-the-shelf) product and you’re waiting for a fix but don’t know when (or if) it will arrive. Moreover, updating a package or modification to an existing codebase can require robust testing and approval from a change control board. What do we do to act quickly here?
I cannot take credit for this fix, but I am happy to spread the word around and help expand upon it and answer questions where necessary. Years ago, I wrote a byte-code injection framework (SecurePaaS) that could modify classes and inject security controls related to single-sign-on and authorization controls. Over the first initial days I thought of ways to patch this issue through a similar method but apparently NCC had already beaten me to the punch. However, it appears no one is talking about this!
For those of you unfamiliar NCC is a security research group. They have published an essential hot fix that leverages byte-code injection to:
- Disable the internal method handler for jndi: format strings (“lookups”).
- Log a message to System.err (i.e stderr) indicating that a log4j JNDI attempt has been made (including the format string attempted, with any ${} characters sanitized to prevent transitive injections).
- Resolve the format string to “(log4j jndi disabled)” in the log message (to prevent transitive injections).
This fix is deployed as a java agent which can be used with Java 1.6 and later. It does not require system updates nor code changes of any kind. How does it work you say? Lets take a look at the code:
By leveraging a common byte-code modification framework known as byte-buddy, the agent runs at system launch and looks at every piece of code before being loaded into the JVM. Every time a new class is attempting to load, an NCCs agent checks if the class is an instance of org.apache.logging.log4j.core.lookup.JndiLookup. If it is, it modifies the lookup method, changing it to log the attempt (via System.err), skip all further functionality and return as if the method executed normally.
How can you leverage this fix? You can compile the code in a few short moments and attach it to every JVM in your environment via the javaagent runtime parameter. Will this break anything in my environment? Highly unlikely as the class isn’t removed, just the method functionality is modified. The only way this would hurt your code base is if you used Log4j to perform JNDI lookups in the first place, in which case you have a much bigger problem on your hands. The best part is, you can even use this on COTS solutions (assuming you have access to the Java runtime environment). Does this circumvent change board requirements? That greatly depends on your organization and what your change board considers a “change” that must be reviewed. Lastly, is this going to solve all my problems forever? No, eventually when an appropriate fix is out, I highly recommend making the appropriate code changes and package updates.
A traditional vulnerability scanner will still see your system as vulnerable even though it isn’t, which I think is a good thing as it should remind you that this isn’t a permanent solution but something to help get over the hump of dealing with this problem. Furthermore, I cannot make any guarantees that this will completely stop an attack. With any luck though, it will help reduce the burden of this vulnerability and the attack vector greatly. Please take great care during this time and review the source code from the NCC group below.
Source Code: https://github.com/nccgroup/log4j-jndi-be-gone
Questions? Contact Shadow-Soft for help!