munotes®

A Worked Case Study: Log4Shell

Get access to whole semester resourcesSemester Pass

Chapter Eighteen

Syllabus topic Module 1, "Vulnerability Research and Disclosure Mechanisms: ... Analyze a real vulnerability case study"

Pages 82 to 86 of 578

In one line

Log4Shell (CVE-2021-44228) was a flaw in Log4j, a near-ubiquitous Java logging library, by which merely writing an attacker-controlled string to a log could cause the server to fetch and run code from a machine the attacker chose. It scores 10.0, the maximum, and it is the standard case study for supply-chain risk.

In examination wording: Log4Shell was a remote code execution vulnerability disclosed in December 2021 in Apache Log4j 2, arising from the library's message-lookup substitution feature performing JNDI lookups on attacker-controlled input, allowing an unauthenticated remote attacker to cause the logging host to retrieve and execute a remote class.

Why this case study

Heartbleed was a mistake. Log4Shell was, in a sense, the software doing what it was built to do, and that is why it is worth a chapter:

  1. The dangerous behaviour was a documented feature, not a bug in the ordinary sense, so code review looking for mistakes would not have flagged it.
  2. The trigger was logging, the one thing every application does with untrusted input, and does deliberately.
  3. It affected an enormous number of systems that had no idea they contained Log4j.
  4. It is the clearest illustration of scope change and of why that metric exists.
  5. Its defences illustrate the whole toolkit: patching, configuration, egress filtering, and inventory.

The mechanism, at concept level

Three ordinary design decisions combined into a catastrophe. Understanding the combination is the point; no single element is obviously wrong.

First, Log4j supported "lookups" in log messages. To make logging convenient, the library could substitute values into a message: a special marker in the text would be replaced with, say, an environment variable or a system property. This is a feature, documented and intended.

Second, one of those lookups could use JNDI. JNDI (the Java Naming and Directory Interface) is a standard Java mechanism for looking things up in a directory service, and it is capable of fetching an object from a remote server and materialising it in the running process. Again, a feature, and one with legitimate uses in enterprise Java.

Third, the substitution was applied to the message content itself, not just to the format string the developer wrote. So if an application logged a string that came from a user, and that string contained a lookup marker, the lookup was performed.

Put together: an attacker sends a request containing a crafted string in any field the application happens to log, a username, a search term, a user-agent header, an HTTP header of almost any kind. The application logs it, as it is supposed to. Log4j sees the marker, performs a JNDI lookup to a server the attacker specified, retrieves a Java class from it, and the process loads it. The attacker is now running code on the server.

munotes.in82

A Worked Case Study: Log4Shell

No authentication was needed, because applications log requests before and regardless of authentication. No user interaction was needed. And the attacker did not need to find a vulnerable input field in the usual sense, because any logged field would do, which made it nearly impossible to defend by filtering one place.

In the classification vocabulary, the root weakness is improper neutralisation of attacker-controlled input leading to code execution, with an element of unsafe deserialisation or remote class loading through JNDI.

A worked example: reading Log4Shell with the module's tools

Which properties broke? All three. The attacker could read data (confidentiality), alter it (integrity) and destroy or disable the service (availability), because running arbitrary code on a host gives all of it. Contrast Heartbleed, which broke only confidentiality, and the difference in score follows immediately.

The CVSS vector. AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H:

  • Attack Vector Network: any request reaching the application.
  • Attack Complexity Low: reliable, and the trigger string was short.
  • Privileges Required None: no account needed, because logging happens before authentication.
  • User Interaction None: no victim action required.
  • Scope Changed: this is the metric worth dwelling on. The vulnerable component was a logging library, whose security authority is, notionally, logging. Exploiting it gave control of the entire host process and whatever that process could reach, which is a different security authority altogether. That is exactly what Scope Changed is defined to capture, and it is why this flaw illustrates the metric better than any other.
  • C:H, I:H, A:H: total impact on all three.

The score is 10.0. The calculator in the CVSS chapter reproduced it. Nothing scores higher, and the combination that gets there is total impact plus scope change plus maximal exploitability.

What made it exceptionally hard to handle

Nobody knew where it was. Log4j is a dependency of a dependency of a dependency. Organisations ran Java applications, vendor appliances, cloud services and internal tools that contained it several layers down, often without the vendor knowing either. The first and hardest task was not patching; it was discovery. Teams spent days answering "do we even run this?" before they could begin to fix anything. This is the supply-chain lesson in its purest form, and the direct argument for a software bill of materials, a machine-readable inventory of every component in a product, which turns that multi-day question into a query.

The attack surface was everything. Because any logged string could carry the trigger, and applications log headers, usernames, search terms and error messages, there was no single input to validate. Attempts to block the pattern by filtering failed repeatedly, because the string could be obfuscated in many ways using the library's own nested-lookup capability. This is a general lesson: filtering a dangerous pattern is a weak control when the attacker controls the encoding.

munotes.in83

A Worked Case Study: Log4Shell

Exploitation began immediately and at scale. Because the flaw was trivial to trigger and the details public, mass internet-wide scanning for it started within hours of disclosure. The window between disclosure and exploitation was not days, it was hours, which is the practical demonstration of the point in the disclosure chapter about public disclosure raising short-term risk.

Fixes arrived in stages. The first mitigation turned out to be incomplete, and further advisories and versions followed as related issues were found. Organisations that patched once and stopped were not fully protected, which is a lesson in itself: for a flaw of this shape, track the advisory rather than applying one update.

The defensive analysis

Which control would have prevented it? At the library, not performing lookups on message content, which is what the fix did (the behaviour was disabled by default in later versions). At the application, nothing reasonable: the developers did nothing wrong by logging user input, which is precisely why this case is disturbing.

Which control would have limited it? Egress filtering, and this is the most transferable lesson in the chapter. The exploit required the victim server to make an outbound connection to the attacker's machine to fetch the class. A server that is not permitted to open arbitrary outbound connections to the internet could be triggered but could not complete the attack. Most organisations allow unrestricted outbound traffic from servers because it is convenient; those that did not were substantially protected by a control they had put in place for unrelated reasons.

Two others: least privilege, so that the code ran with limited rights and reached less; and network segmentation, so the compromised host could not reach everything else.

Which control would have detected it? Outbound connection logging, because the tell-tale sign is a server suddenly making connections to an unfamiliar external address. This is a good example of detection being available to organisations that log the right thing, which is usually egress rather than ingress.

Which control made response possible? Inventory, again. The organisations that responded in hours rather than weeks were those that already knew their software components.

Heartbleed and Log4Shell compared

Heartbleed (2014)Log4Shell (2021)
Root causeA coding mistake (missing length check)A feature reached by untrusted input
Weakness classOut-of-bounds readUnsafe lookup leading to code execution
Properties brokenConfidentiality onlyConfidentiality, integrity and availability
ScopeUnchangedChanged
CVSS7.5 High10.0 Critical
Attacker gainsFragments of memory, possibly the keyArbitrary code execution on the host
Trace leftNone in ordinary logsOutbound connection, if egress is logged
Hardest part of responseRe-keying, because exposure was unprovableFinding where the component was installed
Generalisable lessonShared code concentrates risk; invisible attacks force precautionary responseSupply chain; features can be vulnerabilities; egress filtering limits damage
munotes.in84

A Worked Case Study: Log4Shell

Studying the pair is more instructive than either alone, because the contrast isolates what is common: both were in shared components, both were reachable by unauthenticated remote input, and in both cases the decisive factor in recovery was whether the organisation knew what it was running.

What beginners get wrong

  • Calling it a bug in logging. The library did what it was documented to do; the flaw was that a convenience feature was applied to untrusted content. That is a design failure, not a coding slip.
  • Thinking the application developers were careless. Logging user input is normal and correct. This is the case that shows a safe application can be compromised through a dependency.
  • Believing input filtering was a fix. The trigger could be obfuscated using the library's own features, and attempts to block it by pattern failed. Removing the capability was the fix.
  • Assuming a single patch closed it. Follow-up advisories addressed related issues; tracking the advisory was necessary.
  • Missing why Scope is Changed. The vulnerable component was a logging library; the impact was control of the whole host process, which is a different security authority.
  • Overlooking egress filtering. The exploit needed an outbound connection from the victim to the attacker. Blocking that broke the chain, and it is the control most organisations still do not apply.

Quick revision

  • CVE-2021-44228, December 2021, Apache Log4j 2. A documented message-lookup feature performed JNDI lookups on attacker-controlled log content, causing the host to fetch and execute a remote class.
  • Triggered by logging any attacker-supplied string (a header, a username, a search term), before authentication, with no user interaction.
  • Vector AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H, score 10.0. Scope Changed because a logging library's flaw yielded control of the whole host.
  • Hard to handle because organisations did not know they contained it (a dependency of a dependency), the trigger could appear in any logged field, filtering could be obfuscated around, exploitation began within hours, and fixes came in stages.
  • Controls: remove the capability (the real fix); egress filtering, which breaks the required outbound fetch; least privilege and segmentation to limit reach; outbound connection logging to detect; and a software bill of materials to make response possible.
  • Against Heartbleed: a feature rather than a mistake, all three properties rather than one, Scope Changed rather than Unchanged, 10.0 rather than 7.5.

Test yourself

  1. Explain the Log4Shell mechanism and why the application developers were not at fault.
munotes.in85

A Worked Case Study: Log4Shell

Log4j substituted lookups into log message content, and one lookup type used JNDI, which can fetch and load a class from a remote server. Because the substitution applied to the message content, logging an attacker-supplied string caused the host to fetch and execute attacker-chosen code. Developers were not at fault because logging user-supplied input is normal and correct; the dangerous behaviour was inside the dependency.

  1. Why is Scope recorded as Changed, and what does that contribute to the score?

Because the vulnerable component was a logging library, whose security authority is logging, while successful exploitation yielded arbitrary code execution over the entire host process and what it could reach, which belongs to a different authority. Scope Changed raises the impact calculation and multiplies the combined score by 1.08, helping it reach the maximum 10.0.

  1. Why was input filtering an inadequate response?

Because the trigger string could be obfuscated in many forms using the library's own nested-lookup capability, and because the input could arrive in any field the application logged, so there was no single place to filter. The effective fix was to remove the lookup capability.

  1. Which network control would have broken the attack chain even on an unpatched server, and why?

Egress filtering. Exploitation required the victim server to make an outbound connection to the attacker's machine to retrieve the class, so a server not permitted to open arbitrary outbound internet connections could be triggered but could not complete the attack.

  1. Compare Heartbleed and Log4Shell in terms of root cause, properties broken and the hardest part of the response.

Heartbleed was a coding mistake (a missing length check) that broke confidentiality only, and its hardest response problem was re-keying, because exploitation left no trace and could not be disproved. Log4Shell was a documented feature reached by untrusted input, broke all three properties with Scope Changed, and its hardest response problem was discovering where the component was installed, since it was an indirect dependency.

munotes.in86

The rest of this subject

These notes are cut from the University's printed syllabus. Open the syllabus itself for the same subject.

Issue
Done!