本次测试从 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 仿真、电动车 / 自动驾驶测试台架 |
本次模糊测试处于 测试预览 / 评估阶段, 全部测试均在本机隔离环境 127.0.0.1 完成:
| 角色 | 国家 / 地区 | 说明 |
|---|---|---|
| 被测软件作者 | 🇨🇦 加拿大 | 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 或外部生产系统进行任何连接或测试。
发现的漏洞仅用于评估该开源软件在畸形 / 恶意诊断输入下的健壮性(拒绝服务面),
所有漏洞验证均在本地隔离环境完成,触发报文细节不公开,符合负责任披露原则。
| 编号 | 漏洞名称 | 严重等级 | 异常类型 | 根因位置 |
|---|---|---|---|---|
| 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(未校验必填字段) |
注:异常率 = (PARSE-EXC + HANDLE-EXC) / 总请求。原始基于 udsoncan 的 ECU 仿真 在模糊测试下 近一半请求触发未处理异常,构成拒绝服务(DoS)面;修复后异常率降至 0%。
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")
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.service 与 req.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.xml | 7884 <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