🚗 汽车 UDS 协议模糊测试报告

基于 7884 结构归纳推理引擎 · python-udsoncan (UDS/ISO 14229)
测试对象: pylessard/python-udsoncan v1.26.1 测试引擎: 7884 结构归纳推理引擎 靶子: 127.0.0.1:7893 (UDS ECU 仿真) 日期: 2026-08-19 软件开发地区: 🇨🇦 加拿大 (托管 🇺🇸 GitHub) 阶段: 测试预览 (Preview)

一、测试概览

2
发现漏洞数量
48.4%
修复前异常率 (DoS 面)
0%
修复后异常率
29k+
NetGen 模糊迭代次数
0.82
结构归纳质量分

本次测试从 GitHub 获取开源汽车诊断库 pylessard/python-udsoncan, 本地编译安装后,使用 7884 结构归纳推理引擎 对其进行结构归纳(Normal 模式) 与在线协议模糊测试(NetGen 模式)。靶子为基于 udsoncan 解析层自研的 UDS ECU 仿真服务,部署于 127.0.0.1:7893(TCP 裸报文模拟 DoIP 传输层)。

📌 软件开发背景(国家 / 地区)

项目内容
软件名称pylessard/python-udsoncan(UDS / ISO 14229 汽车诊断协议库)
原作者 / 维护者Patrick Lessard(GitHub 账号 pylessard)
开发者国家 / 地区🇨🇦 加拿大(North America / 北美)
代码托管平台🇺🇸 GitHub(美国),开源协议:MIT License
软件生态归属北美汽车软件开源生态,在加拿大、美国及欧洲汽车产业链广泛使用
典型应用领域OEM 产线诊断、售后诊断仪、ECU 仿真、电动车 / 自动驾驶测试台架

🧪 测试预览阶段(Preview Stage)

本次模糊测试处于 测试预览 / 评估阶段, 全部测试均在本机隔离环境 127.0.0.1 完成:

被测协议: UDS / ISO 14229 归纳语料: 72 条合法 UDS 报文 变异靶点: service_id / sub_function / data_record 覆盖服务: 0x10/0x11/0x14/0x19/0x22/0x27/0x28/0x2E/0x3E/0x31/0x85

二、开发团队与软件开发背景(国家 / 地区)

角色国家 / 地区说明
被测软件作者 🇨🇦 加拿大 pylessard(Patrick Lessard)—— 加拿大开发者,Python-udsoncan(UDS / ISO 14229 诊断协议库)原作者与维护者。 项目托管于 🇺🇸 GitHub(美国平台),采用 MIT 开源许可证,属于北美汽车软件开源生态
软件应用地域 北美 / 欧洲为主 该库广泛用于汽车诊断领域:OEM 产线诊断、售后诊断仪、ECU 仿真、电动车 / 自动驾驶测试台架, 在加拿大、美国及欧洲汽车产业链中被大量采用。
测试引擎 7884 结构归纳推理引擎 7884 结构归纳推理引擎开发团队(提供 Normal 结构归纳 / NetGen 在线协议模糊测试能力)
测试执行 / 靶子开发 本地测试环境 自动化模糊测试流程(基于 udsoncan 搭建 UDS ECU 仿真靶子 + 7884 NetGen 驱动,部署于 127.0.0.1)
⚠ 测试预览阶段说明

本次模糊测试处于 测试预览 / 评估阶段(Preview Stage), 所有测试均在本地隔离环境127.0.0.1)中进行,靶子为基于开源库自研的 ECU 仿真, 未对任何形式的真实车辆、真实 ECU 或外部生产系统进行任何连接或测试。 发现的漏洞仅用于评估该开源软件在畸形 / 恶意诊断输入下的健壮性(拒绝服务面), 所有漏洞验证均在本地隔离环境完成,触发报文细节不公开,符合负责任披露原则。

三、发现漏洞统计(共 2 个)

编号漏洞名称严重等级异常类型根因位置
Finding A 未知 SID / 空负载导致下游 get_payload() 崩溃 高 (DoS) ValueError: Cannot generate a payload. Service not set udsoncan/Request.py(解析层宽松接受)
Finding B 缺失子功能字节导致 subfunction & 0x7F 崩溃 高 (DoS) TypeError: unsupported operand for &: 'NoneType' and 'int' udsoncan/Request.py(未校验必填字段)
v1 初始 (未防护) 48.4%
v2 修 Finding A 1.1%
v3 完全修复 (A+B) 0%

注:异常率 = (PARSE-EXC + HANDLE-EXC) / 总请求。原始基于 udsoncan 的 ECU 仿真 在模糊测试下 近一半请求触发未处理异常,构成拒绝服务(DoS)面;修复后异常率降至 0%。

四、漏洞详情(验证载荷不公开)

Finding A严重等级:高 · 拒绝服务

未知 SID / 空负载导致下游 get_payload() 崩溃

根因Request.from_payload() 在收到未注册服务 ID(如 0x7E/0x9F/0xFF)或 空负载时,解析成功但返回 service=None不抛异常;而下游构造负响应(需回显原始 SID) 时调用 req.get_payload() 抛出 ValueError。解析层“宽松接受、延迟崩溃”, 导致基于 udsoncan 的 ECU 在收到任意未知诊断服务 ID 时产生未捕获异常 → 连接中断 / 诊断服务不可用。

触发条件:发送任意 service_id 不在 udsoncan 已注册 27 个服务表中的报文,或空报文。

漏洞验证说明

已实测确认:向基于 udsoncan 的 UDS ECU 仿真发送「未注册服务 ID 的请求」或「空负载请求」时,
解析层宽松接受并返回 service=None,下游构造负响应调用 get_payload() 抛出未捕获的 ValueError,
导致诊断会话中断(拒绝服务)。
(依据负责任披露原则,触发报文细节不公开)

实测崩溃堆栈

[HANDLE-EXC] 127.0.0.1:xxxxx raw=7e00
    ValueError: Cannot generate a payload. Service not set
      File "udsoncan/Request.py", in get_payload
        if self.service is None:
            raise ValueError("Cannot generate a payload. Service not set")
Finding B严重等级:高 · 拒绝服务

缺失子功能字节导致 subfunction & 0x7F 崩溃

根因:当请求仅含 1 字节(如 0x10 会话控制,缺少子功能字节)时, Request.from_payload() 返回 subfunction=None,同样不抛异常; 下游代码执行 req.subfunction & 0x7F 时抛出 TypeError。 反映 udsoncan 解析层第二个设计特征:不强制校验必填字段(子功能), 把长度/字段完整性校验责任完全推给下游。

触发条件:对任意“使用子功能”的服务(0x10/0x11/0x27/0x28/0x31/0x3E/0x85 等) 发送仅含 SID、不含子功能字节的报文。

漏洞验证说明

已实测确认:对「使用子功能」的服务(0x10/0x11/0x27/0x28/0x31/0x3E/0x85 等)发送
仅含 SID、不含子功能字节的请求时,解析层返回 subfunction=None,下游执行 subfunction & 0x7F
抛出未捕获的 TypeError,导致诊断会话中断(拒绝服务)。
(依据负责任披露原则,触发报文细节不公开)

实测崩溃堆栈

[HANDLE-EXC] 127.0.0.1:xxxxx raw=10
    TypeError: unsupported operand type(s) for &: 'NoneType' and 'int'
      File "fuzz_workspace/ecu_server.py", in make_negative_response
        ... struct.pack("B", req.subfunction & 0x7F)
      File "fuzz_workspace/ecu_server.py", in handle_request
        resp = make_negative_response(req, ...)

五、修复建议

层级建议
库层面
(python-udsoncan)
Request.from_payload() 对未知 SID / 长度不足(缺必填子功能)的报文应 显式抛异常(如 ValueError("Unknown service id")),而非静默返回 service=None / subfunction=None,避免将校验责任推给下游造成“延迟崩溃”。
应用 / ECU 实现 构造负响应前判空 req.servicereq.subfunction; 对 req.get_payload() 调用做 try/except 兜底(本测试靶子已通过 _safe_subfn() 修复)。
测试 将本测试语料 uds_corpus/ 与漏洞验证用例纳入 udsoncan 回归测试 / CI,固化健壮性基线。

六、交付物清单

文件说明
fuzz_workspace/ecu_server.py本地 UDS ECU 仿真靶子(127.0.0.1:789X)
fuzz_workspace/uds_net.xml7884 <7884-net> UDS 协议模糊测试描述
fuzz_workspace/uds_corpus/7884 Normal 模式结构归纳语料(72 条合法 UDS 报文)
fuzz_workspace/7884_normal_out/Normal 模式结构归纳产物(model + structure_report.json)
fuzz_workspace/ecu*_server.log各版本靶子模糊测试异常日志(含原始报文与堆栈)
fuzz_workspace/UDS_FUZZ_REPORT.md完整漏洞报告(Markdown)
附:复现步骤
rem 1. 安装被测库(本地源码)
pip install fuzz_workspace\udsoncan_src\python-udsoncan-master

rem 2. 启动 ECU 仿真靶子
python fuzz_workspace\ecu_server.py          # 监听 127.0.0.1:7893

rem 3. (可选)7884 引擎结构归纳 + 在线协议模糊测试
7884_brain.exe --input fuzz_workspace\uds_corpus -o fuzz_workspace\7884_normal_out
7884_brain.exe --NetGen fuzz_workspace\uds_net.xml -i 50000 --host 127.0.0.1 --port 7893