引言
9 月 25 日,安全公司 Ridge Security 公开了一个编号为 CVE-2026-42542 的高危漏洞,受影响的是国产开源时序数据库 TDengine。攻击方式简单到有点反直觉:只要向默认端口 6030 发一个畸形数据包,不需要账号、不需要登录、不需要任何交互,数据库服务进程就会直接崩溃。
9 月 28 日,TDengine 官方发布修复版本 3.4.1.6,Dark Reading 等权威技术媒体跟进报道。截至目前,官方口径是没有观测到在野利用,安全公司自己写的验证程序也没有公开。
这条新闻出来之后,很多人的第一反应是:"不就是崩一下嘛,又不是被偷数据,重启一下就好了。"
这个判断恰恰是本文要拆解的核心误区。TDengine 的官方客户名单里有西门子、中石化这类工业企业,全球运行实例超过 73 万。对一块跑在车间、充电桩、车联网后台的时序数据库来说,"崩溃重启"这四个字的含义,和一台闲置的测试机完全不同。
一、事件复盘
漏洞基本信息
根据 Ridge Security 披露与 TDengine 官方修复公告,这个漏洞的要素如下:
- 编号:CVE-2026-42542,CVSS 评分 7.5,高危
- 受影响版本:3.4.0.0 至 3.4.1.5
- 修复版本:3.4.1.6
- 攻击前提:能访问目标机器的 TCP 6030 端口,不需要任何凭据
- 确认后果:远程拒绝服务,服务进程崩溃
- 在野利用:暂无证据;安全公司的验证程序未公开
时间线
整个漏洞从发现到修复并不算拖沓。CVE 编号在 6 月 10 日就已经分配,说明披露流程早就启动;9 月 25 日 Ridge Security 公开技术细节并提示工业场景风险;9 月 28 日官方补丁随版本发布,权威媒体同期报道,国内技术资讯也在 9 月 29 日跟进。从"细节公开"到"补丁可用"之间只隔了三天,这个节奏在开源项目里属于正常偏快。
为什么安全公司专门点名工业场景
Ridge Security 在报告里说了一句被多家媒体引用的话:这个漏洞不是"某个奇特的失败",而是一个普通的失败,出现在了一个重要的地方。
他们发现这个问题的场景也很说明问题——研究人员本来在测一批物联网和工业控制环境里常用的开源软件。这类软件有个共同点:传统 IT 安全工具通常不怎么看它们。TDengine 的设计中心正是工业遥测、能源电力、车联网、大规模设备监控。这些部署有两个让人不太舒服的特征:数据在业务上是关键路径,而维护窗口要么很窄,要么根本不存在。
顺带一提的另一件事
研究人员在审计同一批代码路径时,还观察到 TDengine 的密码哈希默认使用 MD5。他们明确说明,这一项不构成漏洞,也不属于 CVE-2026-42542 的范围,但认为值得向社区提出——MD5 早已被认为不适合用于口令存储,对拿到凭据库之后的离线爆破几乎不设防。
二、技术核心拆解
崩在哪:一个长度字段减一个头长度
TDengine 的服务端进程叫 taosd,它默认在 TCP 6030 端口上说一套自研的二进制 RPC 协议。这条协议上的每一条消息,开头都是一个固定大小的消息头,内部结构名叫 STransMsgHead。这个头里带了一个长度字段 msgLen,作用是告诉服务端:头后面还跟着多少字节的数据。
问题出在连接处理的早期。在任何身份验证发生之前,服务端会调用一个叫 uvConnMayGetUserInfo() 的函数,从收到的消息里把用户身份信息取出来。要取这部分内容,它得先算清楚头后面的负载有多少字节。
它用的方法是看起来最自然的那一种:用消息长度减去消息头长度。
这行减法就是崩塌的起点。msgLen 是一个有符号的 32 位整数,而且数值完全由发送方控制;消息头长度则是一个无符号的 size_t。 在 C 语言的类型提升规则下,当 msgLen 比需要的偏移量还小时,这个减法不会变成负数,而是回绕成一个接近 2 的 64 次方的巨大数值。
这个巨大数值紧接着被当作长度传给了 memcpy。内存拷贝照着这个天文数字往下读,直接越过堆上那块缓冲区的边界,进程以段错误退出。
用大白话说:服务端打算"从这一堆数据里切出后 100 字节",结果算成了"切出后面 1844 亿亿字节",然后它真的去切了。
Ridge Security 对修复的描述是:大约三行的改动,在 uvConnMayGetUserInfo() 的最前面加一段校验,确认消息长度至少等于头长度加上偏移量,做完这个检查再往下走算术。需要补充的偏移量是 64 字节还是 192 字节,取决于具体的消息变体。
为什么"只是崩溃"这个结论也不完全准确
官方确认的影响是拒绝服务,攻击者能做的确定的事就是让服务崩掉。这一点没必要夸大。
但从技术属性上看,这个漏洞的底层原语并不是"逻辑错误导致退出",而是由攻击者影响长度而触发的堆缓冲区越界写。这正是历史上被一步步发展成远程代码执行的那一类原语。Ridge Security 的表述很克制——他们确认的是未鉴权的远程拒绝服务,底层机制是堆内存破坏,同时提醒防守方:应该按"内存破坏原语"的严重程度来安排响应,而不只是按"崩溃"来安排。
这是一个专业机构在说:别把评分 7.5 当成"就这样了"。
重启策略会把临时故障变成长期故障
还有一个容易被忽略的工程细节。如果 taosd 挂在 systemd 或者某个进程守护工具下,并且配置了自动重启,那么崩溃之后它会自己回来——攻击者只需要把同一个数据包反复发送,就能让这个数据库长期停在"崩溃、重启、再崩溃"的循环里。
对一块时序数据库来说,崩溃还不是一次干净的失败。在途的写入会丢。 对工业遥测和设备监控来说,丢写入就等于丢可见性;而一个宕掉的监控系统,同时也是一个不会报警的监控系统。
三、常见技术误区
误区一:只是崩溃,不偷数据,算不上严重
这是本次事件里最普遍的判断,也是最需要纠正的一个。
在通用 IT 语境里,一个"只能把服务打崩"的漏洞确实常被排在数据泄露、权限提升之后。但在 TDengine 的主场——工业遥测、能源电力、车联网、充电桩——"看不见"本身就是一类严重事故。设备读数断了,异常检测模型就没有输入,告警面板就是一片空白。业务方在系统恢复前,无法判断现场到底正常还是异常。
再叠加两个技术事实:崩溃伴随在途写入丢失,以及崩溃-重启循环可以用一个数据包无限维持。这就不是一个"重启就好"的问题,而是一个"可以被人按着按到停摆"的问题。
误区二:6030 端口没对公网开放,就跟我没关系
"我这是内网服务器"是第二常见的自我安慰。
Ridge Security 的提示很直接:6030 是默认端口,常规网络扫描很容易发现暴露的实例;而已经进入内网的攻击者,同样可以用标准手段把 TDengine 系统找出来。
更现实的是,很多"内网"并没有想象中那么小:
- 云主机的安全组往往只放行了业务需要的几个端口,内网互通并未收紧,6030 在内网里依旧可达;
- 用 Docker 或者 Kubernetes 跑的 TDengine,容器默认监听 0.0.0.0,宿主机端口映射和集群网络会把它带出单机范围;
- 一体机、工控整机这类交付物里预装了 TDengine,它就在那儿,但运维的资产清单上可能根本没有这一行。
安全公司的措辞是:暴露面取决于网络可达性。在大多数架构里,6030 不光是"不该对公网开放",也不该在网络内部被广泛可达。
误区三:数据库漏洞是运维的事,跟开发者无关
第三个误区出在职责划分上,而这次它恰好是最关键的一环。
TDengine 是国产开源项目,被大量嵌进应用交付物里:写进 docker-compose 的默认镜像、打进攻克集成环境的部署脚本、作为边缘端组件随一体机出厂。这些默认配置是开发者定的,不是运维定的。 默认口令是不是 root/taosdata、6030 有没有绑到 0.0.0.0、测试环境有没有直接连到公网地址,全都在代码和编排文件里。
顺带说回研究人员提到的 MD5 哈希:如果口令是默认的、哈希又是 MD5,那么一旦凭据库外流,爆破几乎不构成门槛。这两个问题单独看都不致命,叠在一起就是另一回事。
四、实操指引
第一步:先确认自己有没有装、装的是哪个版本
# 客户端与服务端版本
taos -V
taosd -V
# 或者在 taos shell 里查
taos -s "select server_version();"
只要版本落在 3.4.0.0 到 3.4.1.5 之间,就在受影响范围内。 需要注意的一点是,TDengine 常常内嵌在别人给的整机或镜像里,内部系统、合作方交付物、边缘设备都要一起清点,这也是安全公司特别提醒的那句:内嵌部署最容易被漏掉。
第二步:能升级就先升级
升级到 3.4.1.6 或更高版本是唯一的真正修复,防火墙和 ACL 都只是临时缓解。这一点在安全公司的报告里说得很明白:其余所有手段都是让风险变得够不着,而不是把它修掉。
第三步:确实没法马上升级,就先关掉可达性
这个漏洞需要网络能碰到 6030 端口才成立,因此切断这条可达路径,就能在没打补丁的情况下消掉这个暴露面。
# 看看到底哪些端口在监听
ss -tunlp | grep -E '6030|6041'
- 用主机防火墙规则或者网络 ACL,把 6030 限制为只有真正需要和数据库通信的应用主机可以访问,而不是整段内网随便来;
- 云主机同步检查安全组入站规则,内网互通规则也要一并核对;
- TDengine 的端口不止一个。除 6030 之外,还存在集群节点通信、数据同步、taosAdapter 的 REST 服务等端口。做暴露面梳理时不要只盯着 6030 一个数字,把实际监听列表拉出来逐个对;
- 顺手检查一下 taosAdapter 的 REST 服务是否也被开放到了不该开放的范围。
第四步:观察有没有已经在被打
如果有实例曾经莫名其妙重启过、日志里出现过段错误,值得回头翻一下:
- 查看 taosd 的运行日志和系统日志中的崩溃记录;
- 确认进程守护配置里的自动重启策略——它会让崩溃看起来像"偶发重启",把攻击痕迹盖掉;
- 在防火墙或流量侧观察 6030 端口有没有来源异常的连接尝试。
第五步:顺手修掉那两个"不算漏洞"的老习惯
- 不要用默认口令。root/taosdata 这种出厂凭据在互联网上是公开信息;
- 关注 MD5 口令哈希这件事的后续进展,在项目支持更强算法时切换过去;
- 在生产环境里,数据库端口的暴露范围,应该由架构设计决定,而不是由安装包的默认值决定。
五、结尾
这个漏洞的技术内核,是一行存在了几十年的经典错误:用一个由外部控制的数值去做减法,然后拿结果当内存长度用。 它没有花哨的攻击链,没有精妙的绕过,甚至补丁只有三行。Ridge Security 自己都强调,这不是什么罕见的失败,而是一个普通的失败,出现在了一个重要的地方。
值得记住的是这句话背后的判断逻辑:漏洞的严重程度不只由漏洞本身决定,还由它站在什么位置上决定。 同样一个单包崩溃,站在一台测试机上和站在一座工厂的数据底座上,是两件完全不同的事。
对普通开发者来说,这次事件最实际的提醒是两件事。第一,去确认一下自己项目里有没有这个组件,包括那些跟着交付物一起进来的。第二,养成看一眼默认配置的习惯——默认端口、默认口令、默认监听地址,这些最不起眼的默认值,往往是暴露面的真正来源。
话题标签