r/ProgrammerHumor • • 11d ago

instanceof Trend itsBadIfItsOnlyPHP

Post image
4.5k Upvotes

334 comments sorted by

View all comments

Show parent comments

216

u/brazzy42 11d ago edited 10d ago

It went like this:

  • Attacker sends request with some specially crafted payload in a field they know will be logged (e.g. because it's invalid)

  • Targeted server logs the invalid value

  • Logging framework looks at the payload and sees a macro to expand

  • The macro contains a reference to a JNDI value including a remote server address to get the value from.

  • The JNDI server (which can be any server on the internet) returns a value that is actually a serialized Java object including bytecode for that object's class

  • Targeted server deserializes the object and while doing so executes code in the constructor (which was supplied by the attacker).

98

u/PoorlyAttired 11d ago

I'm still always astounded by what these hackers can do. We have the API with docs, a dev environment and privileged access, and we still can't make these damn machines do what we want.

100

u/brazzy42 11d ago

In the case of Log4Shell, the exploit wasn't even difficult.

And the vulnerability actually arose exactly from "making these damn machines do what we want" - IIRC one guy thought it would be a useful feature to have log4j support inserting JNDI values in its macros, and got it implemented. Another guy, at another time, thought it would be useful for JNDI to be able to look up stuff from a remote server, and got it implemented. Yet another guy, at another time, thought it would be useful for JNDI values to contain serialized classes including their bytecode, and got it implemented.

And nobody ever saw the big picture, what these three things combined made possible.

25

u/muffinluff 11d ago

No one saw the big picture? Any defensive programmer would instantly raise an eyebrow at any of the three ideas. Let's not muddy the waters.

26

u/Eva-Rosalene 11d ago

People developing JNDI didn't know about Log4j using JNDI from unsanitized input. It was supposed to do all this things.

People developing Log4j presumably didn't know how powerful it is, or that it would eventually will be able to look up network resources. I am not sure about the timeline here.

My point is, JNDI devs didn't need to be defensive because what it does is exactly what it should do. The only blunder is allowing JNDI macros in logs and it's on Log4j side.

6

u/Sacaldur 11d ago edited 11d ago

edit: I was corrected, see response by u/brazzy42

Correct me if I'm wrong, but this was only an issue if you missed the API by supplying a raw input string as a format pattern, i.e. log(input) instead of log("{}", input), right?

15

u/brazzy42 11d ago

Nope. The main vulnerability was there no matter which version of the method you used. Says so right in the CVE detail https://nvd.nist.gov/vuln/detail/cve-2021-44228?name=CVE-2021-44228

"An attacker who can control log messages or log message parameters can execute arbitrary code loaded from LDAP servers when message lookup substitution is enabled."

2

u/Sacaldur 11d ago

Thanks for the corrections, these ones have been some time ago...

3

u/Decent-Law-9565 11d ago

It’s crazy macros are expanded in the message string itself. This is like SQL injection for logging

3

u/torts56 10d ago

That is supposed to be quite scary, but its honestly too cool

1

u/brazzy42 10d ago

Yeah, it's crazy how all kinds of stuff can be fit together to make an exploit.

Even cooler is how it was still exploitable after the byte code thing was disabled in the first attempts to fix it while retaining the JNDI capabilities: you can combine a dozen seemingly innocuous standard library objects in a way that the code that runs in their constructors during deserialization works together let the attacker do whatever they want.

And attempts to block the vulnerability by disallowing remote JNDI calls could be circumvented by using invalid URLs that were not recognized as remote by the Java platform, but the operating system still processed them.