Repository navigation
Conversation
All seven were reported by the DREAM Security Research Team against v0.8.4.1 (3548c10) and validated against master. Vulnerability discovered by: Adiel Sol, Arad Inbar, Erez Cohen, Nir Somech, Ben Grinberg, Daniel Lubel, Shir Sadon (DREAM Security Research Team) Each has a draft advisory; the GHSA id is cited in the comment at every fix site. CVE ids have been requested and are not assigned yet. GHSA-f3j5-rhhr-85j5 - use-after-free in func_pcre (src/ec_filter.c) The PCRE2 match data was freed before pcre2_get_ovector_pointer() was called on it, and the resulting pointer then drove an allocation size, two memcpy offsets into the pcap buffer, and the packet length delta. The offsets are now copied out of the match data before it is released, which also plugs the leaks on the no-match paths of both level 5 and 6. This is the default build path wherever pcre2 is installed. GHSA-vrjv-f8gv-2h35 - heap overflow in gg_get_version (ec_gg.c) The helper composed up to 44 bytes into a 30-byte allocation via sprintf()/strcat(). Both helpers now build into a private buffer and hand back only a bounded copy. Also fixes user[10]/pass[40], which were one byte short for a u_int32 uin and 41 bytes short for five %X, and the scratch buffers leaked by the short-packet guards. GHSA-v48w-7cvh-c7f4 - SNI heap over-read (ec_sslwrap.c) val_len was read from the ClientHello and passed to strndup() without being checked against the extension length, so it read up to 64KB past the buffer and shipped the result to the upstream server. The reported double free was not reproducible - ae->hostname is freed once and SAFE_FREE() NULLs - but the callback fires twice and leaked the first allocation, so it now releases any previous value before reassigning. GHSA-hq2w-pg4m-6w63 - out-of-bounds read in sslw_remove_sts (ec_sslwrap.c) The search for the end of the STS header used the length of the whole packet from an already-advanced pointer, reading past the buffer, and did not check memmem() for NULL - h_end became 0x2, header_length underflowed and memcpy() got a near-SIZE_MAX length. Bounded and NULL-checked; len still describes the whole packet, as the rebuild below is sized from it. GHSA-j37f-7jx3-rf8j - size_t underflow in ccmp_decrypt (ec_encryption_ccmp.c) len -= WPA_CCMP_TRAILER wrapped for frames shorter than 8 bytes and the decrypt loop then ran ~2^60 times up the stack. Both the outer and inner function now reject undersized frames, and the UINT16_MAX check moved above the VLA it was meant to bound. GHSA-jw9q-j2rm-94j2 - heap over-read in the NTLM parser (ec_http.c) lmResponse/ntResponse/uUser offsets were used as displacements from the decoded message with no bounds checking, letting a peer read 24 bytes from anywhere in a 4GB window and have us log the result. The decoded length is now kept and every offset/length pair validated against it; short blobs are rejected before msgType is read at offset 8. GHSA-w5ch-7c4x-crcc - stack underflow in the telnet dissector (ec_telnet.c) Backspace handling decremented the write pointer with no lower bound, so leading backspaces walked it below the VLA and later characters wrote attacker-chosen bytes underneath it. Bounded by str. Verified with an AddressSanitizer build: the func_pcre use-after-free reproduces end to end via etterfilter + a crafted pcap and is gone after the fix, and extracted harnesses confirm the gg, ccmp and telnet fixes. Existing test suite passes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U7DPkxps63uUMetZEJSTLr
eaescob
force-pushed
the
security/dream-2026-hardening
branch
from
September 8, 2026 17:44
3416996 to
a8c1a50
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes seven memory-safety bugs that a malicious network peer can reach while ettercap is monitoring traffic. All seven were reported by the DREAM Security Research Team against v0.8.4.1 (3548c10) and validated against
master.Each has a draft advisory and the GHSA id is cited in a comment at every fix site. CVE ids have been requested from GitHub and are not assigned yet — I'll amend this description once they land.
func_pcresrc/ec_filter.cgg_get_versionsrc/dissectors/ec_gg.csrc/ec_sslwrap.csize_tunderflow insslw_remove_stssrc/ec_sslwrap.csize_tunderflow inccmp_decryptsrc/ec_encryption_ccmp.csrc/dissectors/ec_http.csrc/dissectors/ec_telnet.cWhat each fix does
func_pcreuse-after-free —pcre2_match_data_free()ran atec_filter.c:593, thenpcre2_get_ovector_pointer()read the freed block at line 625 and the resulting pointer drove theSAFE_CALLOCsize, the marker indices, bothmemcpyoffsets into the pcap buffer, andpo->DATA.len. TheSAFE_CALLOCon the very next line can recycle that block. The offsets are now snapshotted before the match data is released, mirroring how the pcre1 path already used a stackovec[]. Also frees the match data on the no-match paths of bothlevel 5andlevel 6, which leaked. Note this is the default build path wherever pcre2 is installed (EttercapLibCheck.cmake:269).gg_get_versionheap overflow —sprintf(str,"unknown (0x%X)",version)plus both conditionalstrcats produced 44 bytes into a 30-byte allocation. Both helpers now compose into a private buffer and hand back only a bounded copy. While here:user[10]was one byte short for au_int32uin andpass[40]was one short for five%X, and the short-packet guards returned without freeing the three scratch buffers.SNI over-read —
val_lencame off the wire and went straight intostrndup(). The client_hello callback runs before OpenSSL validates extension bodies, so nothing upstream constrained it; it read up to 64KB past the buffer and the result was handed toSSL_set_tlsext_host_name()for the upstream connection.sslw_remove_sts— two defects. The secondmemmemused the length of the whole packet from an already-advanced pointer, so it scanned past the buffer end; and its result was never NULL-checked, soh_endbecame0x2,header_lengthunderflowed, andmemcpygot a near-SIZE_MAXlength.lenitself deliberately still describes the whole packet, since the reconstruction below is sized from it.ccmp_decrypt—len -= WPA_CCMP_TRAILERwrapped to ~SIZE_MAXfor frames under 8 bytes and the loop then wrote AES blocks up the stack. Guarded in both the outer and inner function, and theUINT16_MAXcheck moved above the VLA it was supposed to bound.NTLM parser —
lmResponse.offset,ntResponse.offsetanduUser.offsetwere unchecked 32-bit values added to the decoded message base, so a peer could make us read 24 bytes from anywhere in a 4GB window and hex-encode it into the password we print and log. There was no minimum-size validation at all:base64decode()sizes its output from the input string, so evenmsgTypeat offset 8 was out of bounds for a short blob.Telnet — backspace handling decremented
pwith no lower bound. Theisprint()check only guards the first saved character and is bypassed after one round trip, because the loop stored the un-erased string back intos->data. Boundingpbystralso fixes that, so backspaces are no longer carried forward.A note on the two reported double-frees
The submission described findings 3 and 4 as double-frees. I could not reproduce that.
ae->hostnameis freed exactly once andSAFE_FREE()NULLs as it frees. The real defects are the over-read (3) and the OOB read + NULL-deref +size_tunderflow (4), and that is what the advisories and these fixes describe.Per maintainer request the SNI path still got a defensive guard: the callback fires twice per handshake and used to overwrite
ae->hostnamewithout freeing, so it now releases any previous value before reassigning. That closes the leak and makes a double free unreachable on every path that reaches it.Verification
func_pcreUAF. With apcre_regex(DATA.data, "(hello) (world)", "$2-$1")filter and a crafted pcap, stockmastergives a trace matching the reporter's byte for byte:WRITE of size 13past a 30-byte region), ccmp (len=3→0xFFFFFFFFFFFFFFFB) and telnet (dynamic-stack-buffer-overflow) bugs before, and clean runs after.ctestsuite passes; no new compiler warnings.Not addressed here
Two things surfaced during triage that are out of scope for a security fix:
ef_syntax.l:44definesFUNCTION [a-z_]+\([^)]*\), which stops at the first). Any regex containing a paren fails to compile — including the substitution example we ship inshare/etter.filter.pcre. I relaxed it locally to build the test filter above and reverted it; worth a separate PR.wpa_ccmp_decrypt()reads the MIC fromdata + len, i.e. past the length it was given. That is the existing caller contract and I left it alone, but it deserves a look.🤖 Generated with Claude Code
https://claude.ai/code/session_01U7DPkxps63uUMetZEJSTLr