EMQX LwM2M 网关安全修复:REGISTER/UPDATE 报告中敏感查询字段的过滤机制
2026/9/24 16:34:17 网站建设 项目流程
  • 后端
  • 物联网
  • 消息队列
  • 通信

【免费下载链接】emqx

The most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles

项目地址:https://gitcode.com/gh_mirrors/em/emqx
点击查看免费下载

本篇技术指南围绕 EMQX 开源仓库中的一个安全修复项展开:LwM2M 网关在把设备的 CoAP REGISTER/UPDATE 请求翻译为 MQTT 消息时,曾可能将 URI 查询参数中携带的passwordsecretprivate_keyaccess_token等敏感字段一并写入上报到 MQTT 的消息体,造成凭据泄露。读完本文,你将理解 LwM2M 网关注册/更新上报的完整数据链路、敏感字段过滤的具体实现位置与判定规则、对应的回归测试用例,以及如何在实际部署中规避同类风险。

修复项背景

本修复记录于 changes/ee/fix-17888.en.md,原文如下:

Fixed an issue where the LwM2M gateway could include sensitive REGISTER query fields such aspassword,secret,private_key, andaccess_tokenin registration/update MQTT reports.

即:修复了 LwM2M 网关可能将 REGISTER 查询字段(如passwordsecretprivate_keyaccess_token)包含在注册/更新 MQTT 报告中的问题。这是典型的信息泄露(sensitive data exposure)类缺陷——敏感凭据本应用于网关侧的身份校验,却因数据透传被意外转发到了 MQTT 消息里。

LwM2M 网关与 REGISTER/UPDATE 上报链路

EMQX 的 LwM2M 网关位于 apps/emqx_gateway_lwm2m,其职责是接收 LwM2M 客户端(基于 UDP/DTLS 传输,当前实现仅支持 v1.0.2,详见 README.md),并将设备的事件与消息翻译成 MQTT Publish 消息。设备上线时会在 CoAP 的/rd资源上发起 REGISTER 请求,之后可通过 UPDATE 请求刷新注册信息,这两类请求的 URI 查询参数中通常携带标准字段:

  • ep:端点名称(Endpoint Name),设备唯一标识;
  • lt:生命周期(Lifetime);
  • lwm2m:协议版本;
  • imeidevice_id:扩展字段(非标准协议字段,源码中已标注FIXME注释);
  • bt等其他厂商扩展参数。

从源码看,网关解析这些查询参数的入口位于 emqx_lwm2m_channel.erl 的enrich_conninfo/2enrich_clientinfo/2(第 508-558 行):enrich_conninfo提取eplt等用于连接信息;enrich_clientinfo则额外提取imei作为用户名、password用于网关侧认证,其中password属于“非标准协议字段”的扩展用法。

设备完成注册后,网关会将会话注册信息打包成#{<<"msgType">> => <<"register">>, <<"data">> => RegInfo}结构发布到 MQTT(对应register_init/2,见 emqx_lwm2m_session.erl 第 465-478 行);UPDATE 请求则走update/5流程(第 416-463 行),同样以<<"update">>msgType发布。上报的 MQTT 主题由translators.register/translators.update配置决定(见 emqx_lwm2m_schema.erl 第 155-167 行 与uplink_topic/1的读取逻辑)。

问题就出在RegInfo的构造上:如果直接沿用解析出的完整查询参数 Map,那么设备在 REGISTER/UPDATE 请求里携带的任何键值(包括敏感凭据)都会被原样写进data字段并发布到 MQTT——订阅了注册/更新主题的任何 MQTT 客户端都能看到这些敏感信息。

修复实现:drop_sensitive_reg_info 敏感字段过滤

本次修复的核心实现在 emqx_lwm2m_session.erl 中新增的drop_sensitive_reg_info/1函数:

drop_sensitive_reg_info(RegInfo) -> maps:filter( fun(Key, _Value) -> not emqx_utils_redact:is_sensitive_key(Key) end, RegInfo ).

该函数遍历注册信息 Map,凡是被emqx_utils_redact:is_sensitive_key/1判定为敏感键的键值对一律剔除。它在两条路径上被调用:

  • 首次 REGISTER 路径:append_object_list/2(第 311-319 行)在合并 URI 查询参数与 payload 中的对象列表之后、进行lt类型修正之前,先调用drop_sensitive_reg_info(append_object_list2(Query, Payload))完成过滤,确保register_init/2中发布的RegInfo不含敏感字段;
  • UPDATE 路径:update/5(第 425 行)在将新查询参数与旧注册信息合并后,同样执行drop_sensitive_reg_info(maps:merge(OldRegInfo, RegInfo)),既过滤了本次 UPDATE 请求新带来的敏感字段,也兜底清除了历史注册信息中残留的敏感数据。

两条路径都经过统一过滤,因此 REGISTER 与 UPDATE 两种上报消息(以及由reregister/3触发的重注册)均不再携带敏感字段。

敏感键判定规则:emqx_utils_redact:is_sensitive_key/1

过滤所依赖的判定函数位于 apps/emqx_utils/src/emqx_utils_redact.erl。is_sensitive_key/1是一个覆盖多种数据形态(原子、字符串、二进制)的敏感键白名单,与本次修复直接相关的条目包括:

键名匹配形态
passwordpassword/"password"/<<"password">>
secretsecret/"secret"/<<"secret">>
private_keyprivate_key/"private_key"/<<"private_key">>
access_tokenaccess_token/"access_token"/<<"access_token">>

该模块同时覆盖了access_key_idaccess_key_secretapi_keyapi_secretjwttoken等大量常见凭据键名(见 第 34-102 行)。这意味着 LwM2M 网关的过滤机制不只是针对修复说明中列举的四个字段——凡是查询参数中出现的、命中该敏感键表的键(无论以字符串还是二进制形式传入),都会被drop_sensitive_reg_info/1一并剔除,为上报链路提供了较为全面的防护。

值得说明的是,过滤仅作用于上报到 MQTT 的注册信息RegInfo)。password等字段在网关内部依然会被enrich_clientinfo/2读取并用于连接认证(见 emqx_lwm2m_channel.erl 第 540-548 行),即敏感信息仍可在“网关内部消费”,只是不再被转发到 MQTT 主题上。

回归测试验证

修复配套了完整的回归测试,位于 apps/emqx_gateway_lwm2m/test/emqx_lwm2m_SUITE.erl 的case02_update_deregister/1用例(第 821-944 行)。该用例构造的 REGISTER 请求故意携带了全部四类敏感参数:

coap://127.0.0.1:~b/rd?ep=~ts&lt=345&lwm2m=1 &password=public&secret=top&private_key=priv&access_token=token

随后网关应返回{ok, created},同时上报的 MQTT 报告(主题为lwm2m/<endpoint>/up/resp)中data字段应只包含标准字段alternatePathepltlwm2mobjectList,并断言不存在任何敏感字段:

assert_no_secret_register_fields(#{<<"data">> := Data}) -> ?assertEqual( #{}, maps:with( [ <<"password">>, <<"secret">>, <<"private_key">>, <<"access_token">> ], Data ) ).

maps:with/2会提取data中命中的键组成新 Map,断言其等于空#{},即上述四个键一个都不允许出现(见 第 6300-6312 行)。同一用例随后发起 UPDATE 请求并再次调用assert_no_secret_register_fields(Update)断言 UPDATE 报告同样干净,与源码中update/5的过滤逻辑一一对应,形成了 REGISTER 与 UPDATE 双向的回归保障。

配置参考与安全实践

结合修复后的行为,在生产环境使用 LwM2M 网关时可以从以下几点入手规避敏感信息风险:

  1. 避免在 REGISTER/UPDATE 查询参数中携带凭据。从源码看,标准 LwM2M 注册协议并不要求这些字段(emqx_lwm2m_channel.erl中已将imei/password等标注为“不属于标准协议”的 FIXME 扩展)。即便本次修复保证了它们不会被转发到 MQTT,凭据出现在 CoAP 查询参数中本身也会增加被记录、被截获的风险。若确有认证需求,应优先使用网关的认证链(emqx_gateway_ctx:authenticate/2)配合正式机制处理。

  2. 确认上报主题不被无关订阅者监听。REGISTER/UPDATE 报告发布到translators.register/translators.update配置的主题(默认示例见 README.md 中的up/respup/update),应结合 EMQX 的 ACL 规则限制这些主题的订阅权限。

  3. 按需控制 UPDATE 上报频率。网关提供update_msg_publish_condition配置(默认always,可设为contains_object_list使仅当 UPDATE 携带对象列表时才发布),见 emqx_lwm2m_schema.erl 与 emqx_lwm2m_session.erl 第 451-463 行 的should_publish_update/1判定逻辑。合理配置可减少不必要的数据落盘与转发面。

  4. 升级并关注日志中的脱敏行为。本次修复与仓库既有的emqx_utils_redact脱敏体系一致,网关在记录错误日志时也会调用emqx_utils:redact/1对查询参数脱敏(见 emqx_lwm2m_channel.erl 第 553-555 行)。建议使用包含该修复的版本,确保注册/更新上报与日志两条路径都不再泄露敏感查询字段。

小结

本次安全修复通过在 LwM2M 会话层的 REGISTER 与 UPDATE 两条数据链路上统一引入drop_sensitive_reg_info/1,借助emqx_utils_redact:is_sensitive_key/1的敏感键表过滤,确保passwordsecretprivate_keyaccess_token等凭据不会进入上报到 MQTT 的data字段;配套的case02_update_deregister回归用例对两类报告做了断言兜底。对于自行基于 EMQX 网关协议栈做二次开发的场景,本文所述的“内部消费、外部过滤”模式同样值得参考:敏感字段可以在网关内用于认证,但在跨协议转发时必须显式剥离。

  • 后端
  • 物联网
  • 消息队列
  • 通信

【免费下载链接】emqx

The most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles

项目地址:https://gitcode.com/gh_mirrors/em/emqx
点击查看免费下载
上一篇:5个简单步骤:用Reset Windows Update Tool彻底解决Windows更新故障
下一篇:Windows更新卡住怎么办?5分钟终极修复指南:Reset Windows Update Tool完整解析

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询