ANT-2026-Y5M37QY4 · wireshark/wireshark

heap-buffer-overflow medium

CVE-2026-15165 GHSA-3q2h-7599-7r76

Severity Claude high · Security research firm high · Maintainer medium

Discovered by Claude Mythos Preview

REPORT

Anthropic's analysis, sealed at approval. Disclosure to the maintainer was performed by Ada Logics.

ANT-2026-Y5M37QY4: TLS ECH transcript reconstruction heap overflow

In Wireshark's TLS dissector, ssl->ech_transcript.data is allocated at packet-tls-utils.c:10066 with size hello_length + 4 (the outer ClientHello size). The extension-copy loop at :10087-10114 then processes the decrypted inner ClientHello and, for every 0xfd00 (ech_outer_extensions) entry, resets outer_offset and tvb_memcpys the referenced outer extension into the transcript with no destination bound and no single-use enforcement. An attacker ships a pcapng whose DSB embeds ECH_SECRET/ECH_CONFIG (auto-loaded via packet-tls.c:4720/5187), so the inner CH decrypts with zero user configuration; an inner CH with many tiny 0xfd00 entries each referencing the same large outer extension writes ~N*K attacker-controlled bytes into a ~K-sized heap buffer. A secondary infinite loop occurs when a 0xfd00 extension has length 0 and ech_offset never advances.

Target

Project: wireshark/wireshark
Location: epan/dissectors/packet-tls-utils.c:10087
Discovery: static analysis — not yet dynamically reproduced

Technical Details

The transcript buffer is sized once to the outer ClientHello length, but the copy loop neither bounds-checks the destination nor enforces RFC's at-most-one ech_outer_extensions rule, and it re-initializes outer_offset per 0xfd00 entry so the same large outer extension can be memcpy'd repeatedly. tvb_memcpy only validates the source tvb, not the destination, so repeated copies overrun the wmem_file_scope heap allocation with attacker-controlled TLS extension bytes.

Reproduction

  1. Craft a pcapng with a Decryption Secrets Block containing ECH_SECRET and ECH_CONFIG lines (auto-loaded by tls_secrets_block_callback).
  2. Include a TLS ClientHello with an ECH payload that decrypts under the embedded secret (attacker controls HPKE key/ciphertext so auth tag validates).
  3. In the decrypted inner ClientHello, place many small 0xfd00 ech_outer_extensions entries each referencing the same ~60 KB outer extension.
  4. Victim opens the file; the ECH reconstruction loop repeatedly memcpy's the large outer extension into the outer-CH-sized ech_transcript buffer.
  5. Heap is overflowed by hundreds of kilobytes of attacker-controlled bytes.

[No reproducer or sanitizer output attached — request from security-cvd@anthropic.com if needed.]

Suggested Fix

Bound total bytes written into ech_transcript.data to the allocated size, process ech_outer_extensions at most once, and ensure every loop iteration strictly advances the inner-extension cursor.

Acknowledgement

This vulnerability was discovered by Claude, Anthropic's AI assistant, and triaged by the Anthropic security team in collaboration with Anthropic Research. Please direct questions to security-cvd@anthropic.com and reference ANT-2026-Y5M37QY4.


Reference: ANT-2026-Y5M37QY4
Anthropic CVD Policy: https://www.anthropic.com/coordinated-vulnerability-disclosure

SECURITY RESEARCH FIRM ANALYSIS

Triage and disclosure were performed by Ada Logics.

Verdict
true positive
Severity
high
UPSTREAM FIX

The change that resolved this finding.

diff --git a/epan/dissectors/packet-tls-utils.c b/epan/dissectors/packet-tls-utils.c
index ac725a4cbb1..8eb743b7929 100644
--- a/epan/dissectors/packet-tls-utils.c
+++ b/epan/dissectors/packet-tls-utils.c
@@ -10283,6 +10283,7 @@ ssl_dissect_hnd_hello_ext_ech(ssl_common_dissect_t *hf, tvbuff_t *tvb, packet_in
                     ssl->ech_transcript.data_len += 2;
                     uint32_t extensions_end = ech_offset + tvb_get_ntohs(ech_tvb, ech_offset) + 2;
                     ech_offset += 2;
+                    bool ech_outer_extensions_found = false;
                     while (extensions_end - ech_offset >= 4) {
                         uint16_t ext_type = tvb_get_ntohs(ech_tvb, ech_offset);
                         ech_offset += 2;
@@ -10295,6 +10296,16 @@ ssl_dissect_hnd_hello_ext_ech(ssl_common_dissect_t *hf, tvbuff_t *tvb, packet_in
                             ssl->ech_transcript.data_len += 4 + ext_len;
                             ech_offset += ext_len;
                         } else if (ext_len > 0) {
+                            if (ech_outer_extensions_found) {
+                                ssl_debug_printf("Illegal parameter; only a single \"ech_outer_extensions\" extension is allowed\n");
+                                /* This could lead to a buffer overflow by
+                                 * making the post-copying ClientHelloInner
+                                 * longer than ClientHelloOuter and is
+                                 * illegal, so skip this and don't copy. */
+                                ech_offset += ext_len;
+                                continue;
+                            }
+                            ech_outer_extensions_found = true;
                             unsigned num_ech_outer_extensions = tvb_get_uint8(ech_tvb, ech_offset);
                             ech_offset += 1;
                             uint32_t ech_outer_extensions_end = ech_offset + num_ech_outer_extensions;

https://github.com/wireshark/wireshark/commit/39a3c437378890840e201d773ba52b2cdb762bc9

TIMELINE

Recorded dates, in order.

  1. 2026-04-02 Discovered or logged
  2. 2026-07-04 Sent to maintainer
  3. 2026-07-08 Patch released
  4. 2026-09-28 Publicly revealed
PROVENANCE

SHA-3-512 hash:

ea3625713c4457cf94a19766c6904d638aff57a96dbaad5756946453a48334f437e06603c95fb73fe513646b06ee7a82a17187f74dc84bff22ac74c72a24bd23

Committed 2026-07-22 07:34 UTC

Revealed 2026-09-28 20:35 UTC

Verify (download preimage.json)

Show preimage JSON
{
  "ant_id": "ANT-2026-Y5M37QY4",
  "bug_class": "Heap Buffer Overflow",
  "claude_severity": "high",
  "commit_sha": null,
  "created_at": "2026-04-16T14:11:13+00:00",
  "description": "In Wireshark's TLS dissector, `ssl->ech_transcript.data` is allocated at packet-tls-utils.c:10066 with size `hello_length + 4` (the outer ClientHello size). The extension-copy loop at :10087-10114 then processes the decrypted inner ClientHello and, for every 0xfd00 (ech_outer_extensions) entry, resets `outer_offset` and `tvb_memcpy`s the referenced outer extension into the transcript with no destination bound and no single-use enforcement. An attacker ships a pcapng whose DSB embeds `ECH_SECRET`/`ECH_CONFIG` (auto-loaded via packet-tls.c:4720/5187), so the inner CH decrypts with zero user configuration; an inner CH with many tiny 0xfd00 entries each referencing the same large outer extension writes ~N*K attacker-controlled bytes into a ~K-sized heap buffer. A secondary infinite loop occurs when a 0xfd00 extension has length 0 and `ech_offset` never advances.",
  "discovered_at": "2026-04-02T00:00:00+00:00",
  "location": "epan/dissectors/packet-tls-utils.c:10087",
  "poc_sha256": null,
  "preimage_version": 1,
  "project": "wireshark/wireshark",
  "reproduction": [
    "1. Craft a pcapng with a Decryption Secrets Block containing ECH_SECRET and ECH_CONFIG lines (auto-loaded by tls_secrets_block_callback).",
    "2. Include a TLS ClientHello with an ECH payload that decrypts under the embedded secret (attacker controls HPKE key/ciphertext so auth tag validates).",
    "3. In the decrypted inner ClientHello, place many small 0xfd00 ech_outer_extensions entries each referencing the same ~60 KB outer extension.",
    "4. Victim opens the file; the ECH reconstruction loop repeatedly memcpy's the large outer extension into the outer-CH-sized ech_transcript buffer.",
    "5. Heap is overflowed by hundreds of kilobytes of attacker-controlled bytes."
  ],
  "technical_details": "The transcript buffer is sized once to the outer ClientHello length, but the copy loop neither bounds-checks the destination nor enforces RFC's at-most-one `ech_outer_extensions` rule, and it re-initializes `outer_offset` per 0xfd00 entry so the same large outer extension can be memcpy'd repeatedly. `tvb_memcpy` only validates the source tvb, not the destination, so repeated copies overrun the wmem_file_scope heap allocation with attacker-controlled TLS extension bytes.",
  "title": "TLS ECH transcript reconstruction heap overflow",
  "vendor_severity": "high"
}