A 12-byte mailbox slot that accepts packages of any size, on devices that guard power plants
CVE-2026-8836 is a stack-based buffer overflow in the lwIP lightweight TCP/IP stack, versions 2.0.1 through 2.2.1. The vulnerable function snmp_parse_inbound_frame() in src/apps/snmp/snmp_msg.c copies the msgAuthenticationParameters field from an incoming SNMPv3 packet into a fixed 12-byte stack buffer (SNMP_V3_MAX_AUTH_PARAM_LENGTH) — but the original code used the attacker-supplied tlv.value_len as the copy length instead of the constant. A bounds-check assertion existed in source but was commented out. Any unauthenticated attacker who can reach UDP port 161 on a device running lwIP with LWIP_SNMP and LWIP_SNMP_V3 compiled in can smash the stack and, on typical embedded targets lacking ASLR/DEP, achieve reliable code execution.
The vendor CVSS 9.8 CRITICAL reflects the raw mechanics: network-reachable, no auth, no interaction, full CIA impact. That score is *technically correct* for devices in the vulnerable configuration. Where it oversells reality is the population denominator. LWIP_SNMP is disabled by default at compile time — the majority of lwIP deployments (ESP32 IoT widgets, consumer routers, hobby boards) never compile the SNMP agent in. Of those that do, a further subset enables LWIP_SNMP_V3. The devices that *do* enable SNMPv3 are disproportionately industrial controllers, network-managed equipment, and OT assets — exactly the high-value targets where code execution has safety and operational consequences. CISA's own ICS advisory ICSA-26-265-02 confirms lwIP deployment across Chemical, Energy, Healthcare, Transportation, and Water/Wastewater sectors. The severity is real for ICS/OT operators; it is largely irrelevant for the broader embedded ecosystem that never touches SNMP.
4 steps from start to impact.
Identify lwIP device with SNMPv3 on UDP/161
msgSecurityParameters). Devices running lwIP's SNMP agent will respond with their snmpEngineID, confirming the service is live. Shodan/Censys can be used passively for internet-facing targets; on internal OT networks, a simple nmap -sU -p161 suffices.- Target device has
LWIP_SNMP=1andLWIP_SNMP_V3=1compiled into firmware - UDP port 161 is reachable from the attacker's network position
- LWIP_SNMP is disabled by default — most lwIP devices never compile the SNMP agent
- SNMPv3 requires additional compile-time flag and USM credential provisioning
- Well-segmented OT networks restrict management-plane access to dedicated VLANs
Craft malicious SNMPv3 message with oversized auth parameters
msgAuthenticationParameters OCTET STRING exceeds the 12-byte SNMP_V3_MAX_AUTH_PARAM_LENGTH. The PoC repo *Hunt-Benito/lwip-snmpv3-stack-overflow-cve-2026-8836-critical-embedded-rce* on GitHub provides a Python script that automates this. The crafted packet is sent via a single UDP datagram — no session state required.- Knowledge of the target's SNMPv3 engine ID (obtained in step 1)
- Ability to send a single UDP packet to port 161
- Each embedded platform has a different stack layout, so the payload must be tailored per hardware/firmware combination
- The PoC repo has 0 stars/forks and only 2 commits — it may be a malware lure rather than a verified exploit; defenders should audit the code before running it
Trigger stack buffer overflow in snmp_parse_inbound_frame()
snmp_parse_inbound_frame() calls snmp_asn1_dec_raw() using the attacker-controlled tlv.value_len as the buffer size instead of the safe constant SNMP_V3_MAX_AUTH_PARAM_LENGTH. The oversized auth parameter overwrites the stack frame, corrupting the return address. Because the overflow happens *during parsing, before authentication validation*, no valid SNMPv3 credentials are needed.- Device is running vulnerable lwIP version (2.0.1–2.2.1) with SNMPv3 enabled
- Stack canaries or other compile-time hardening (rare on embedded but possible with newer toolchains) would turn this into a crash rather than code execution
Achieve code execution on embedded target
- Target lacks ASLR/DEP/stack canaries (common on Cortex-M, MIPS, Xtensa embedded targets)
- Attacker has a working payload for the specific hardware platform
- Hardware diversity across the lwIP ecosystem means a universal exploit is impractical — each target requires reverse-engineering the firmware memory map
- Some newer SoCs (e.g., Cortex-M33 with TrustZone, ESP32-S3 with PMS) do have partial memory protection
LWIP_SNMP_V3=0 or disable SNMPv3 via device configuration. This completely eliminates the vulnerable code path. Where SNMPv2c is unacceptable due to cleartext credentials, pair with the VLAN restriction above. Deploy within 30 days.msgAuthenticationParameters OCTET STRING TLV length exceeds 12 bytes (0x0C). This detects exploitation attempts in transit but does not prevent a fast single-packet attack. Use as a detection layer alongside network segmentation. Deploy within 30 days.- SNMPv3 authentication credentials (USM users/passwords) — the overflow occurs *during parsing of the authentication field*, before any credential validation. Strong SNMPv3 passwords do not prevent exploitation.
- Host-based endpoint protection (EDR/AV) — lwIP runs on bare-metal or minimal-RTOS embedded devices that cannot run endpoint agents. There is no host-based detection surface.
- TLS/DTLS wrapping — SNMP uses UDP transport natively; wrapping it in TLS is not standard practice and not supported by lwIP's SNMP implementation.
The supporting signals.
| In-the-Wild Exploitation | No known exploitation. Not listed in CISA KEV. No campaigns attributed in Proofpoint, Mandiant, or CrowdStrike reporting as of September 2026. CISA ICS advisory ICSA-26-265-02 covers lwIP but for a different CVE (CVE-2026-91018, double-free). |
|---|---|
| Proof-of-Concept | One GitHub repo: Hunt-Benito/lwip-snmpv3-stack-overflow-cve-2026-8836-critical-embedded-rce — Python exploit script. Caution: 0 stars, 0 forks, 2 commits — pattern consistent with fake-PoC malware lures common in 2025–2026. Audit before executing. Not indexed on pocindex.io (404). No ExploitDB or Metasploit module found. |
| EPSS | 0.01557 (1.56%) — low exploitation probability. Consistent with a niche embedded target rather than a mass-exploited vuln. |
| KEV Status | Not listed. No CISA Known Exploited Vulnerabilities entry as of 2026-09-27. |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (9.8). The vector is technically accurate *for affected configurations* but does not account for the compile-time optionality of SNMP. CVSS v4.0 scored 9.3 (adjusts for automatable exploitation). |
| Affected Versions | lwIP 2.0.1 through 2.2.1 (any build with LWIP_SNMP=1 and LWIP_SNMP_V3=1). Versions prior to 2.0.1 did not include the SNMPv3 USM handler. |
| Fixed Version | Patched in commit 0c957ec (2026-05-13). No tagged release yet — downstream consumers (Espressif IDF, Zephyr, Mbed OS, Siemens firmware) must backport. Debian tracker shows lwip package tracking the fix. |
| Exposure Data | No specific Shodan/GreyNoise tags for this CVE. General SNMP/161 exposure on embedded devices is substantial (millions of hosts globally), but identifying lwIP-specific SNMP stacks from banner data is unreliable. The vulnerable population is a small subset of all SNMP-exposed devices. |
| Disclosure | Published 2026-05-18. Patch commit dated 2026-05-13 (5-day pre-disclosure window). Reporter not publicly credited on VulDB or NVD; CISA credits Eric Evenchick of Tetrel Security for separate lwIP vuln ICSA-26-265-02. |
| ICS Sector Impact | CISA confirms lwIP deployment across Chemical, Communications, Critical Manufacturing, Energy, Financial Services, Healthcare, Transportation, Water/Wastewater. Devices using lwIP+SNMPv3 in these sectors are the highest-risk population. |
Sources.
Why this verdict
- Compile-time gate eliminates the majority of the installed base.
LWIP_SNMPis disabled by default. The firmware must be explicitly compiled withLWIP_SNMP=1ANDLWIP_SNMP_V3=1. Most lwIP deployments (ESP32 IoT projects, consumer routers, hobby boards) never enable SNMP. This single gate likely removes 70–85% of all lwIP instances from the vulnerable population — a decisive downward pressure from 9.8. - No authentication required — pre-auth RCE on devices that lack OS-level exploit mitigations. The overflow fires during packet parsing, before any credential validation. Most embedded targets (Cortex-M, MIPS, Xtensa) lack ASLR, DEP, and stack canaries. This is an upward pressure that prevents further downgrade.
- No in-the-wild exploitation, not KEV-listed, EPSS 1.56%. There are no confirmed campaigns, no reliable weaponized tooling (the sole PoC repo is unverified and potentially a lure), and the EPSS score reflects low near-term exploitation probability. This supports the downgrade from CRITICAL.
- Hardware diversity creates per-target friction. Unlike a single-binary server exploit, lwIP runs on dozens of CPU architectures and RTOS configurations. Each target requires a bespoke payload. Mass exploitation across heterogeneous embedded fleets is impractical without significant R&D investment per platform.
- Role multiplier: ICS/OT controllers are the canonical high-value deployment. Devices that *do* compile in SNMPv3 are disproportionately industrial controllers, managed switches, and OT-grade equipment — the exact deployment roles where code execution means safety/operational impact (blast radius: operational → plant-scale). CISA's ICSA-26-265 advisory series confirms lwIP presence across 8 critical-infrastructure sectors. This population exceeds the 1% threshold for a HIGH floor. The component itself is a general-purpose TCP/IP stack (not canonically ICS-only), so the 10% threshold for a CRITICAL floor is not met — but the HIGH floor holds.
- Role multiplier: workstation/dev-board role is irrelevant. Maker projects and dev boards overwhelmingly do not compile SNMP. The blast radius on these targets is negligible (host-only, no downstream impact). This role does not influence the verdict.
Why not higher?
The compile-time SNMP requirement is the decisive gate. lwIP itself is not canonically a high-value-role-only component — it is a general-purpose embedded TCP/IP stack deployed across all roles from hobby boards to PLCs. The ≥10% installed-base threshold for a CRITICAL floor requires that the component *primarily* occupies the high-value role, which lwIP does not. Additionally, the absence of in-the-wild exploitation, no KEV listing, and hardware diversity all argue against CRITICAL.
Why not lower?
The HIGH floor is binding. Devices that *do* enable SNMPv3 are disproportionately ICS/OT assets where code execution has safety and operational consequences (plant shutdowns, falsified sensor data, physical process manipulation). CISA confirms sector-wide deployment. The pre-auth nature of the overflow and the lack of exploit mitigations on embedded targets mean that for the affected subset, exploitation is reliable and consequences are severe. Dropping to MEDIUM would require evidence that fewer than 1% of lwIP+SNMPv3 deployments occupy ICS/OT roles, which contradicts CISA's own sector analysis.
Crowdsourced verification payload.
Run this script from any workstation that has network access to the target device. Requires Python 3.6+ and no external dependencies. Invoke as: python3 check_cve_2026_8836.py <target_ip>. No special privileges needed — it sends a single UDP packet to port 161 and analyzes the response. It determines whether the target responds to SNMPv3 discovery (indicating a potentially vulnerable SNMP agent is active) but cannot remotely determine the exact lwIP version — pair with firmware inventory for definitive assessment.
#!/usr/bin/env python3
"""check_cve_2026_8836.py — Detect lwIP SNMPv3 exposure for CVE-2026-8836.
Sends an SNMPv3 engine discovery probe to the target on UDP/161.
If the target responds, it is running an SNMPv3 agent and MAY be
vulnerable if the underlying stack is lwIP 2.0.1–2.2.1.
Exit codes:
0 = VULNERABLE (SNMPv3 agent responded — verify firmware version)
1 = PATCHED (no SNMPv3 response — SNMP not enabled or not v3)
2 = UNKNOWN (network error or ambiguous result)
Usage: python3 check_cve_2026_8836.py <target_ip>
"""
import socket
import sys
# SNMPv3 engine discovery request (msgSecurityParameters empty)
# This is a minimal valid SNMPv3 GET with no auth, requesting engineID
SNMPV3_DISCOVERY = bytes.fromhex(
'303e' # SEQUENCE
'020103' # msgVersion: 3
'3011' # msgGlobalData SEQUENCE
'0204deadbeef' # msgID
'020300ffff' # msgMaxSize: 65535
'040104' # msgFlags: reportable, noAuthNoPriv
'020103' # msgSecurityModel: USM (3)
'0400' # msgSecurityParameters: empty OCTET STRING
'3020' # SEQUENCE (scoped PDU)
'0400' # contextEngineID: empty
'0400' # contextName: empty
'a012' # GET-REQUEST PDU
'020401020304' # request-id
'020100' # error-status: 0
'020100' # error-index: 0
'3004' # varbind list
'3002' # varbind
'0600' # OID: empty (discovery)
)
def main():
if len(sys.argv) != 2:
print('Usage: python3 check_cve_2026_8836.py <target_ip>')
sys.exit(2)
target = sys.argv[1]
port = 161
timeout = 5
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(timeout)
sock.sendto(SNMPV3_DISCOVERY, (target, port))
try:
data, addr = sock.recvfrom(4096)
if len(data) > 10 and data[0] == 0x30:
# Check for msgVersion == 3 in response
if b'\x02\x01\x03' in data[:10]:
print(f'VULNERABLE — {target}:{port} responded to SNMPv3 discovery.')
print(' An SNMPv3 agent is active. If this device runs lwIP 2.0.1–2.2.1,')
print(' it is vulnerable to CVE-2026-8836 (pre-auth stack overflow).')
print(' ACTION: Check firmware version against vendor advisory.')
sock.close()
sys.exit(0)
else:
print(f'PATCHED — {target}:{port} responded but not SNMPv3 (likely v2c only).')
print(' The SNMPv3 USM code path (CVE-2026-8836) is not reachable.')
sock.close()
sys.exit(1)
else:
print(f'UNKNOWN — {target}:{port} sent unrecognized response ({len(data)} bytes).')
sock.close()
sys.exit(2)
except socket.timeout:
print(f'PATCHED — {target}:{port} did not respond to SNMPv3 discovery within {timeout}s.')
print(' SNMP is not enabled or port is filtered. CVE-2026-8836 is not reachable.')
sock.close()
sys.exit(1)
except Exception as e:
print(f'UNKNOWN — network error: {e}')
sys.exit(2)
if __name__ == '__main__':
main()