news 2026/9/26 15:47:40

Mosquitto CVE-2017-9868 安全公告解读:持久化文件权限漏洞的成因、修复与防护实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Mosquitto CVE-2017-9868 安全公告解读:持久化文件权限漏洞的成因、修复与防护实践
  • 物联网
  • 消息队列
  • 后端
  • 网络/通信

【免费下载链接】mosquitto

Eclipse Mosquitto - An open source MQTT broker

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

导读:本文以 Eclipse Mosquitto 官方安全公告(security-advisory-cve-2017-9868.md)为主体,系统梳理 CVE-2017-9868 的漏洞成因、影响版本、官方修复方案与管理员缓解措施,并结合当前仓库源码中的restrict_read文件权限防护机制与 ChangeLog.txt 中的修复记录,深入剖析持久化文件为何可能泄露敏感信息、现代 Mosquitto 又是如何从根源上杜绝该问题的。读完本文,你将掌握该漏洞的完整背景、可落地的加固命令,以及从源码层面理解 Mosquitto 持久化文件的安全设计。

一、漏洞概览:CVE-2017-9868 是什么

CVE-2017-9868 是 Eclipse Mosquitto 历史上的一个本地信息泄露漏洞,影响Mosquitto 0.15 至 1.4.12(含 1.4.12)的所有版本。

漏洞核心一句话可以概括为:

当 broker 启用持久化(persistence)功能时,生成的持久化数据库文件会被创建为"世界可读"(world readable)权限,从而可能将敏感信息暴露给本机上的任意用户。

也就是说,任何能够登录该主机的本地账户(普通用户、低权限服务账户等),只要知道持久化文件的位置,都可以读取其中的内容,而不需要 broker 运行账户的授权。该问题已于Mosquitto 1.4.13版本正式修复,官方同时为类 Unix 操作系统(不包含 Windows)发布了独立补丁。

需要强调其本质属性:这是一个本地(local)权限类漏洞,攻击面是"同一台机器上的其他本地用户",而非远程网络攻击。但正因为 Mosquitto 常被部署在共享主机或包含多租户用户的服务器上,其实际风险不容忽视。

二、漏洞根因:持久化数据库为何"裸奔"

要理解这个漏洞,先要理解 Mosquitto 的持久化机制到底保存了什么。

2.1 持久化功能保存的内容

在 mosquitto.conf 中,持久化相关的核心配置如下:

# 如果启用持久化,每 autosave_interval 秒将内存中的数据库保存到磁盘。 # 若设为 0,持久化数据库只在 mosquitto 退出时写入。参见 autosave_on_changes。 # 注意:可通过向 mosquitto 发送 SIGUSR1 信号强制立即写入。 #autosave_interval 1800 #autosave_on_changes false # 将持久化消息数据保存到磁盘(true/false)。 # 这会保存所有消息的信息,包括订阅、当前传输中的消息(in-flight)以及保留消息。 # retained_persistence 是此选项的同义词。 #persistence false # 持久化数据库使用的文件名(不含路径)。 #persistence_file mosquitto.db # 持久化数据库的位置。 # 默认是空字符串(当前目录)。 # 在 Linux 等系统上以正式服务方式运行时,建议设置为 e.g. /var/lib/mosquitto。 # 也可以通过 MOSQUITTO_PERSISTENCE_LOCATION 环境变量在启动 broker 前定义。 # 若配置项与环境变量同时设置,环境变量优先。 #persistence_location

如注释所述,持久化文件保存的内容包括:客户端会话与订阅信息、当前 in-flight(传输中)的 QoS 1/2 消息、保留消息(retained messages)及其载荷、以及消息队列。这些数据对 broker 在重启后恢复运行状态至关重要。

2.2 敏感信息为什么值得保护

问题在于:持久化数据库不是无足轻重的缓存文件,它承载的是业务数据本身:

  • 保留消息与排队消息的载荷(payload):可能是传感器读数、指令、告警等业务数据,MQTT 场景下常涉及物联网设备控制指令或遥测信息;
  • 订阅主题与客户端标识:反映系统内部的主题命名空间、设备分布拓扑,是攻击者侦察内网结构与设备类型的重要情报;
  • 会话与队列状态:可用于推断设备上线规律、通信模式。

当持久化文件以世界可读权限落盘时,任何本地用户只要执行一次cat /var/lib/mosquitto/mosquitto.db就能拿到上述信息——这正是 CVE-2017-9868 的核心危害。

2.3 从源码看当时的缺陷背景

从当前仓库源码中,可以看到修复后的实现路径。持久化数据库的写入由 src/persist_write.c 中的逻辑完成:

if(db.config->persistence_filepath == NULL) return MOSQ_ERR_INVAL; log__printf(NULL, MOSQ_LOG_INFO, "Saving in-memory database to %s.", db.config->persistence_filepath); return mosquitto_write_file(db.config->persistence_filepath, true, &persist__write_data, &shutdown, &persist__log_write_error);

注意这里的第二个参数true——它对应restrict_read(限制读取)标志,即当前版本的 Mosquitto 在写持久化文件时明确要求收紧文件权限。而在 CVE-2017-9868 修复之前(1.4.12 及更早版本),持久化文件在类 Unix 系统上经由普通fopen/open创建,权限受默认 umask 约束。若运行环境 umask 为 022 等宽松值,新建文件的权限即为 0644(-rw-r--r--),任何本地用户都可读取,从而触发本漏洞。

同理,持久化文件的读取入口 src/persist_read.c 也以restrict_read=true的方式打开文件:

if(!db.config->persistence || db.config->persistence_filepath == NULL){ return 0; } fptr = mosquitto__fopen(db.config->persistence_filepath, "rb", true);

而持久化文件路径本身由 src/conf.c 在配置解析阶段拼接生成——将persistence_location与persistence_file组合为完整路径(Unix 下为location/file形式),默认位置是 broker 当前工作目录下的mosquitto.db。这也解释了为什么官方公告建议将权限控制重点放在持久化文件所在目录上。

三、官方修复方案:1.4.13 版本

3.1 修复记录的证据

在仓库根目录的 ChangeLog.txt 中,可以找到该漏洞修复的官方记录:

1.4.13 - 20170627 ================= Security: - Fix CVE-2017-9868. The persistence file was readable by all local users, potentially allowing sensitive information to be leaked. This can also be fixed administratively, by restricting access to the directory in which the persistence file is stored. Broker: ... - Set persistence file to only be readable by owner, except on Windows. Closes #468.

这段变更记录与安全公告完全吻合,并补充了两个关键信息:

  1. 修复版本:1.4.13 于 2017-06-27 发布,即公告发布(2017-06-26)的次日;
  2. 修复范围:"Set persistence file to only be readable by owner,except on Windows"——即持久化文件权限收紧为"仅所有者可读",且明确排除 Windows 平台,与公告中"补丁适用于类 Unix 操作系统(即不含 Windows)"的表述一一对应。原因在于 Windows 采用 ACL 而非 Unix 权限位模型,权限语义不同,因而单独处理。

3.2 补丁的适用前提

官方为类 Unix 系统发布了独立补丁,供无法立即升级到 1.4.13 的用户先行修复。无论选择补丁还是升级,其效果一致:确保持久化文件在创建时不再被赋予其他用户可读的权限。对于 Windows 部署,由于文件权限模型不同,公告明确不适用该补丁,此时应直接升级到 1.4.13 或更高版本,并通过目录级访问控制(ACL)限制访问。

3.3 修复后的验证方式

升级或打补丁后,可对正在运行的新版 Mosquitto 做如下验证:待持久化文件被写出后,检查其权限位应只包含所有者读写权限(-rw-------,即 0600):

ls -l /var/lib/mosquitto/mosquitto.db # 期望输出类似:-rw------- 1 mosquitto mosquitto ... mosquitto.db

若仍显示-rw-r--r--等包含"他人可读"位的权限,则说明环境未正确应用修复,应检查 broker 版本与启动目录,并配合下一节的目录加固措施。

四、管理员缓解措施:目录权限加固

对于无法立即升级或打补丁的运维场景,官方公告给出了一个纯管理层面的缓解手段:

通过移除持久化文件所在目录的"世界读"权限来缓解问题。在许多系统中,可通过如下命令实现:

chmod 700 /var/lib/mosquitto

4.1 为什么"锁目录"能生效

原理很简单:即使持久化文件本身的权限位是 0644(世界可读),但如果它所在的目录权限被收紧为 0700(仅属主可读/写/执行),则其他本地用户连进入该目录、列出文件名、通过路径打开文件的能力都没有——Unix 文件系统的路径解析要求对沿途每个目录都拥有执行(x)权限。chmod 700 /var/lib/mosquitto将目录权限从默认的 755 收紧为 700,即只有目录属主(通常是mosquitto系统用户)可以访问。

4.2 加固后的权限自查

执行加固后,可通过以下命令确认目录与文件的最终状态:

ls -ld /var/lib/mosquitto # 期望输出:drwx------ ... /var/lib/mosquitto ls -l /var/lib/mosquitto/mosquitto.db

需要注意两点前提:

  • 目录属主必须是 broker 运行账户:chmod 700只对目录属主有效,若目录属主不是运行 mosquitto 的用户,broker 本身将无法读写持久化文件,导致启动失败或持久化写入失败;
  • 该方法属于缓解而非根治:它依赖管理员正确维护目录权限,若未来目录权限被重新放宽,或持久化文件被迁移到其他未加固目录,风险将回归。因此官方修复(1.4.13+)才是最终方案。

五、源码级纵深防御:当前版本如何从根源杜绝此类问题

虽然 CVE-2017-9868 已在 1.4.13 修复,但深入当前仓库源码,可以看到 Mosquitto 在文件权限安全上的完整防护设计,这正是理解该漏洞"修复后形态"的最佳窗口。

5.1restrict_read:统一的受限文件打开机制

核心实现在 common/misc_mosq.c 的mosquitto__fopen()函数中。当调用方传入restrict_read=true时,类 Unix 路径采用如下策略:

old_mask = umask(0077); int open_flags = O_NOFOLLOW; for(size_t i = 0; i<strlen(mode); i++){ if(mode[i] == 'r'){ open_flags |= O_RDONLY; }else if(mode[i] == 'w'){ open_flags |= O_WRONLY; open_flags |= (O_TRUNC | O_CREAT | O_EXCL); }else if(mode[i] == 'a'){ open_flags |= O_WRONLY; open_flags |= (O_APPEND | O_CREAT); }... } int fd = open(path, open_flags, 0600); if(fd < 0) return NULL; fptr = fdopen(fd, mode); umask(old_mask);

该实现体现了四层防护:

  1. umask(0077):在创建文件期间将进程 umask 临时收紧为 0077,屏蔽"组/其他"位的所有权限,防止环境默认 umask(如 022)把权限放宽;
  2. open(path, ..., 0600):显式指定新建文件权限为 0600(仅属主读写),与 umask 双重保证;
  3. O_CREAT | O_EXCL:以独占方式创建,若文件已存在则创建失败,避免覆盖他人文件或符号链接;
  4. O_NOFOLLOW:拒绝跟随符号链接,防止攻击者用符号链接诱导 broker 在敏感位置写入。

而在 Windows 路径(common/misc_mosq.c)下,则通过SECURITY_ATTRIBUTES与BuildExplicitAccessWithNameA显式构造仅当前用户(GetUserNameA获取)拥有GENERIC_ALL权限的 DACL,实现"仅所有者可访问"的等价语义——这正是 ChangeLog 中"except on Windows"背后的工程实现。

5.2 对既有危险文件的启动警告

除了新建文件时收紧权限,当前版本在打开已有文件时也会执行安全检查(common/misc_mosq.c):

if(statbuf.st_mode & S_IRWXO){ log__printf(NULL, MOSQ_LOG_WARNING, "Warning: File %s has world readable permissions. Future versions will refuse to load this file.\n" "To fix this, use `chmod 0700 %s`.", path, path); }

即:若持久化文件(或密码文件、ACL 文件等其他敏感文件)已存在且带有"其他人可读"权限位,broker 会在日志中打出 WARNING,提示管理员执行chmod 0700 <file>修复,并预告未来版本将直接拒绝加载此类文件。该警告同样出现在 src/net.c 对 TLS keylog 文件的处理中,说明restrict_read是贯穿 broker 全部敏感文件操作的统一安全策略。

5.3 写入链路的原子替换

持久化数据库的实际落盘由 common/misc_mosq.c 的mosquitto_write_file()完成。从源码结构看,其流程是:先以restrict_read=true方式打开一个临时文件写入数据,再替换为目标文件。这种"写临时文件 + 重命名"的模式确保:

  • 持久化文件在任意时刻都处于完整、一致的状态(避免进程中断产生半截数据库);
  • 新生成的目标文件继承了受限的 0600 权限,不会出现"旧文件权限被保留"的权限继承问题。

这一设计恰好回应了 CVE-2017-9868 的教训:权限安全必须在文件创建的每一个路径上都显式保证,而不是依赖运行环境默认值。

5.4 持久化生命周期中的调用点

最后,把整个链路串起来看(对应 src/database.c 与 src/mosquitto.c):

  • broker 启动时调用db__open(),在WITH_PERSISTENCE编译开关下执行persist__restore()(src/persist_read.c),以restrict_read=true方式读取persistence_filepath;
  • 定时保存或退出保存时,src/persist_write.c 以restrict_read=true方式经mosquitto_write_file()写回磁盘;
  • 期间若检测到文件存在世界可读权限,立即输出修复指引日志。

读写两端均强制收紧权限,配合启动时的存量文件检查,构成了针对"持久化文件泄露"的完整纵深防御。

六、受影响判断与加固自检清单

如果你管理着 Mosquitto 部署,可按以下清单快速判断自己是否处于 CVE-2017-9868 影响范围,并完成加固:

# 1. 确认 broker 版本(低于 1.4.13 则受影响,1.4.12 及以下均需处理) mosquitto -h | head -n 1 # 2. 确认持久化是否启用(mosquitto.conf 中 persistence 是否 true) grep -E '^\s*persistence' /etc/mosquitto/mosquitto.conf # 3. 定位持久化文件并检查其权限 # 默认路径为工作目录下的 mosquitto.db,或由 persistence_location 指定 ls -l /var/lib/mosquitto/mosquitto.db # 4. 收紧持久化目录权限(官方公告给出的管理缓解措施) chmod 700 /var/lib/mosquitto # 5. 若发现文件本身权限过宽,同步收紧文件权限 chmod 600 /var/lib/mosquitto/mosquitto.db

判断结论的三条路径:

场景处理方式
版本 ≤ 1.4.12 且启用持久化升级到 1.4.13+(或应用官方补丁),并执行目录加固
版本 ≥ 1.4.13已内置权限收紧(Unix 下持久化文件为 0600),仍建议确认目录权限
Windows 部署补丁不适用,直接升级到 1.4.13+,并通过目录 ACL 限制访问

七、总结

CVE-2017-9868 是一个典型的"文件权限默认值"引发的本地信息泄露漏洞:Mosquitto 0.15~1.4.12 在启用持久化时,以受 umask 支配的默认权限创建持久化数据库,导致订阅、保留消息、in-flight 消息等敏感数据可能被任何本地用户读取。官方在 1.4.13 中修复(持久化文件仅属主可读,Windows 除外),并提供了类 Unix 系统补丁;管理员亦可通过chmod 700 /var/lib/mosquitto收紧持久化目录权限作为缓解。

从当前仓库源码(common/misc_mosq.c、src/persist_write.c、src/persist_read.c)可以看到,现代 Mosquitto 已把"敏感文件权限"内置为统一的restrict_read机制:umask(0077)+open(..., 0600)+O_NOFOLLOW+O_EXCL四重保障新文件权限,并对存量危险文件输出chmod 0700修复警告。这一演进路径也给所有以文件落盘的系统一个可复用的安全范式:永远不要依赖运行环境的默认 umask,敏感文件权限必须在每次创建时显式声明。

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

【免费下载链接】mosquitto

Eclipse Mosquitto - An open source MQTT broker

项目地址:https://gitcode.com/gh_mirrors/mo/mosquitto
点击查看免费下载
上一篇:Tiger框架组件作用域管理:@Scope注解的实战技巧
下一篇:Unity翻译革新实战:XUnity Auto Translator全流程解决方案

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/26 15:47:16

基于YOLOv8的机场跑道FOD监测系统:从训练到部署全流程

简介&#xff1a;这是一套面向计算机、人工智能、自动化等专业学生与教师的机场跑道FOD&#xff08;异物&#xff09;监测系统完整项目&#xff0c;基于YOLOv8目标检测框架实现&#xff0c;可用于毕业设计、课程设计或大作业演示。资源包共97个文件&#xff0c;以70个Python源码…

作者头像 李华
网站建设 2026/9/26 15:46:31

LLMs基准评测新范式:用GPT-Fathom拆解GPT-4演进路径的配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/26 15:43:35

偶发Bug排查实战:串口假故障、蓝牙断开与烧录失败的定位方法

偶发 bug 这东西&#xff0c;只要干过嵌入式或者硬件调试的人&#xff0c;基本都见过它最磨人的一面&#xff1a;你盯着它的时候它不出现&#xff0c;你一松手、合上电脑、客户开始演示&#xff0c;它准时来。更麻烦的是&#xff0c;你反复抓日志抓不到&#xff0c;复现概率又低…

作者头像 李华