FEATURED · 精选文章

ClickHouse v25.8.25.37-lts 发布解读:安全加固、格式解析器健壮性与备份恢复修复全览

发布时间 / 2026/9/19 5:47:55
来源 / 创域科博编辑部
栏目 / 资讯中心
ClickHouse v25.8.25.37-lts 发布解读:安全加固、格式解析器健壮性与备份恢复修复全览 ClickHouse v25.8.25.37-lts 发布解读安全加固、格式解析器健壮性与备份恢复修复全览【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHousev25.8.25.37-lts 是 ClickHouse 25.8 LTS 分支的一个补丁版本对比基线为 v25.8.24.21-lts全部变更均通过官方 backport回移植机制进入稳定分支。本版的核心主题是安全与健壮性修复了 HTTP 响应头 CRLF 注入、复制表部件获取协议的路径遍历等多个安全漏洞针对 Arrow、Parquet、ORC、Avro、MsgPack、JSON 等大量输入格式的解析器补齐了堆越界读取、栈溢出与资源耗尽防护同时修复了 BACKUP/RESTORE、命名集合、MongoDB 存储、windowFunnel等场景下的崩溃。阅读完本文你将完整掌握该版本 28 项用户可见缺陷修复的触发条件、根因与验证方法并能据此评估是否应当升级。本文所有变更均出自仓库内 docs/changelogs/v25.8.25.37-lts.md并结合源码给出实现层证据。一、版本概况与发布背景v25.8.25.37-lts 是一个面向 LTS 稳定分支的累积补丁发布相比前一个补丁版本 v25.8.24.21-lts其变更清单集中在三大类类别数量说明Bug Fix用户可见缺陷28官方稳定版中可被用户观察到的错误行为本版全部修复Build/Testing/Packaging Improvement4依赖升级与构建/打包改进NOT FOR CHANGELOG / INSIGNIFICANT4不进入正式变更日志的内部改动值得注意的细节是每一条 Bug Fix 都标注了对应的 backport 追踪 issue 与原始 PR 编号例如Backported in #105448表示该修复的移植过程由 issue #105448 跟踪。这种原始 PR backport issue双编号机制是 ClickHouse 对 LTS 分支做细粒度、可追溯移植的标准做法——确保补丁只包含最小必要变更从而降低稳定分支回归风险。从修复主题看本版本呈现出两个鲜明特征面向不可信输入的格式解析器加固多达十余项修复集中在ArrowColumnToCHColumn、Parquet、ORC、Avro、MsgPack、BSON 等格式读取路径上属于典型的安全边界强化对动态类型Dynamic / JSON 子类型的持续打磨Dynamic 子列、singleValueOrNull反序列化等多项崩溃被修复反映 25.8 系列引入的新类型体系仍在快速成熟中。二、安全漏洞修复本版最值得关注的部分2.1 HTTP 处理器的 query_id CRLF 注入漏洞修复内容HTTPHandler在处理X-ClickHouse-Query-Id请求头时不再信任用户直接传入的原始值而是先执行清理移除所有 ASCII 控制字符含0x7F从而阻止通过query_id向 HTTP 响应头响应中的X-ClickHouse-Query-Id会回显该值注入 CRLF 换行符。原始 PR 编号 #100500。源码佐证在 src/Server/HTTPHandler.cpp 中可以清晰看到修复落点String query_id params.get(query_id, request.get(X-ClickHouse-Query-Id, )); /// Sanitize query_id: remove ASCII control characters to prevent CRLF injection /// into HTTP response headers (the query_id is reflected in X-ClickHouse-Query-Id). std::erase_if(query_id, [](unsigned char c) { return isControlASCII(c) || c 0x7F; }); context-setCurrentQueryId(query_id);query_id既可以从 URL 参数query_id传入也可以从X-ClickHouse-Query-Id请求头传入两者在 src/Server/HTTPHandler.cpp 处被原样回写到响应头。CRLF 注入的危害在于攻击者可以将任意 HTTP 头字段例如Set-Cookie或伪造的响应体拼接到响应中从而实施响应拆分Response Splitting攻击。修复后控制字符被std::erase_if就地清除任何换行/回车都无法进入响应头。验证方式向 HTTP 接口发送带非法query_id的请求后观察响应头中X-ClickHouse-Query-Id已不包含\r、\n等控制字符。2.2 复制表部件获取协议的路径遍历漏洞修复内容replicated表在跨副本拉取数据部件part fetch的协议中存在两处路径遍历path traversal问题恶意副本可借此把文件写入部件目录之外。原始 PR 编号 #107606。修复后部件获取过程中对目标路径做了严格校验确保文件名落在预期的部件目录内。这类漏洞的典型危害链是攻击者控制一个副本节点 → 诱导其他副本从该节点拉取部件 → 利用../等路径穿越写出任意文件 → 进一步发展为代码执行或数据破坏。对于多副本部署的用户此修复属于强烈建议优先升级的范畴。2.3 输出内容中的密钥泄露防护EXPLAIN 隐藏加密函数参数修复内容当format_display_secrets_in_show_and_select设置处于默认关闭状态时EXPLAIN actions、EXPLAIN header、EXPLAIN PIPELINE的输出将隐藏encrypt、decrypt、HMAC等函数的密钥类参数。原始 PR 编号 #108386。此前即使SHOW与SELECT的明文展示已被屏蔽EXPLAIN 系列命令仍可能在计划文本中暴露密钥明文。修复统一了所有 EXPLAIN 变体的脱敏行为避免运维排查问题时把密钥打进日志。相关设置定义与默认值可在 src/Core/Settings.cpp 附近的设置声明区找到。2.4 深嵌套输入的统一栈溢出防护修复内容读取深度嵌套的 schema 或值时MsgPack、BSON、ORC、Parquet、JSON、DeltaLake、Iceberg、Paimon八种格式此前可能触发服务器栈溢出SIGSEGV。修复后这类输入会被显式拒绝并抛出异常。原始 PR 编号 #107341。从源码结构看ClickHouse 对这些格式的解析深度控制依赖全局解析深度设置max_parser_depth默认值DBMS_DEFAULT_MAX_PARSER_DEPTH在 src/Functions/FunctionSQLJSON.h、src/Functions/QueryTokenizationImpl.h 等处均能看到parser_settings.max_parser_depth的传递链路。递归式反序列化的风险在于攻击者只需构造几层深的嵌套结构即可耗尽栈空间属于典型的低成本、高影响攻击面因此本版本在多个格式读取器中统一引入了深度上限拒绝机制。三、格式解析器加固堆越界与空指针修复矩阵3.1 Arrow / ArrowStream / Arrow IPC本版修复最集中的区域Arrow 家族相关修复多达 4 项是本次发布中修复密度最高的模块全部集中在 src/Processors/Formats/Impl/ArrowColumnToCHColumn.cpp 及其头文件 src/Processors/Formats/Impl/ArrowColumnToCHColumn.h 覆盖的读取路径上修复项触发条件影响堆缓冲区溢出#105449Arrow/ArrowStream 文件中字符串或二进制列的中间偏移被篡改越界读可导致崩溃或信息泄露空指针解引用#105449读取带 geo 标签geo-tagged的 Arrow 列服务器崩溃多处堆 OOB 读取#106395恶意 Arrow 文件声明比缓冲区更多的行数、list/struct/map 子长度与父节点不一致、list 偏移非单调、有效性位图被截断读取超出堆分配范围任何具备SELECT权限的用户均可通过file()、format()、表函数或 ArrowFlight 输入触发空 String/Binary 列兼容#107764Apache Arrow Java 19.0.0含 Apache Spark产出的空String/Binary列此前报INCORRECT_DATA错误现可正常读取其中 #106395 的修复思路值得展开在一切裸指针访问之前先验证全部数据缓冲区——包括数据缓冲区、offset 缓冲区、view-struct 缓冲区与有效性位图缓冲区同时对 list/struct/map 的形状与偏移做一致性检查。这本质上把信任输入 → 解析的模式改成了校验输入 → 解析的模式。考虑到 ClickHouse 的file()、format()表函数以及 ArrowFlight 接口都允许用户直接投喂任意文件这类防御对多租户环境尤其重要。3.2 ParquetDataPageV2 长度处理与深嵌套 schema修复内容#106739原生 Parquet 读取器的DataPageV2页面中定义级别definition level与重复级别repetition level的长度计算存在堆越界读Parquet 文件若带深度嵌套的 schema此前可导致栈溢出。同一 PR 还修复了资源耗尽问题解析 GeoParquet 的 WKB/WKT 几何数据、以及 Avro 字符串/字节数据时的内存分配此前忽略了max_memory_usage限制恶意输入可通过少量数据撬动超大内存分配。修复后这些路径的分配均纳入查询级内存配额管控。3.3 ORC 与 Avro边界检查补齐ORC reader 缺失边界检查#107580为 ORC 读取器补充缺失的边界校验防止畸形 ORC 文件触发越界访问。Avro 嵌套类型反序列化栈溢出检查#102417Avro 读取器在反序列化嵌套类型时增加栈溢出检查深度过大的记录不再耗尽栈。3.4 其他格式相关修复decodeHTMLComponent堆缓冲区溢出#106741解码包含扩展型 HTML 实体nGt;、nLt;的字符串时发生堆缓冲区溢出任何用户一条SELECT即可触发服务器崩溃。源码注释印证了根因在 src/Functions/decodeHTMLComponent.cpp 中明确写着这两个实体是 5 字节的输入、解码后成为 6 字节的 UTF-8 序列——即输入短、输出长的扩展示例旧代码输出缓冲按 5 字节预分配即导致越界。该函数基于 src/Functions/HTMLCharacterReference.gperf 生成的查找表工作实体表及其生成实现位于 src/Functions/HTMLCharacterReference.generated.cpp。PostgreSQL wire 协议整型下溢#107485解析 PostgreSQL 协议消息时若消息长度字段小于 4size - 4发生整型环绕wraparound导致超大的resize/ignore操作。Elf 与 DWARF 解析缺失边界检查#107579为符号化所需的 ELF/DWARF 解析补充边界检查。四、崩溃修复从 Dynamic 列到 windowFunnel 聚合4.1 Dynamic 类型与 JSON 子类型的多路径崩溃Dynamic 列在 25.8 系列中持续迭代本版一口气修复了 3 处修复项场景根因方向SIGSEGV#105464从ALTER 后的压缩 Memory 表读取 Dynamic 子列子列元数据与压缩块状态不一致SEGFAULT#105535JSON 类型的singleValueOrNull反序列化空值路径上缺少空指针保护OOB 读#105666展平flattenedDynamic 列的 Native 格式反序列化偏移计算越界此外还有一处与 Dynamic 联动的修复对Map执行has且 key 为Dynamic类型、查找参数为LowCardinality时如has(map(a::Dynamic, ...), toLowCardinality(b))此前在 release 构建中 SIGSEGV、debug 构建中触发类型不匹配断言现已修复#107956。4.2 windowFunnel 聚合函数的越界事件类型修复内容#107412对精心构造的聚合函数状态aggregate-function state做最终化时若其中包含超出范围的事件类型windowFunnel此前会发生堆缓冲区溢出任何用户一条SELECT即可触发服务器崩溃。windowFunnel是漏斗分析的核心聚合函数其内部状态由时间戳-事件对构成。在 src/AggregateFunctions/AggregateFunctionWindowFunnel.cpp 中可以看到其状态核心是TimestampEvents events_list——一组按时间排序的事件列表事件类型被用作下游数组的下标。若状态被恶意构造为含越界事件编号旧代码在下标访问时即越界。修复在最终化阶段加入范围校验。由于该函数使用广泛转化漏斗分析是 ClickHouse 的招牌场景这条修复对任何线上使用windowFunnel的集群都有实际意义。4.3 VALUES 插入与 CREATE TABLE 语法路径的崩溃VALUES 子句元组尺寸不一致#105582在同一个 VALUES 子句中向 String 列插入不同大小的元组此前导致崩溃如INSERT ... VALUES ((a,b),(c,))之类混排场景。CREATE TABLE ... TO INNER UUID 空 ENGINE#105579任何具备CREATE TABLE权限的用户通过 HTTP 或原生协议发送CREATE TABLE ... TO INNER UUID ...且不带 ENGINE 子句时解析器会解引用空指针导致服务器崩溃客户端同样崩溃。修复后解析器改为抛出规范的BAD_ARGUMENTS错误。4.4 MongoDB 集合名校验与命名集合重载MongoDB 空集合名 / NUL 字节崩溃#105776mongodb表函数、MongoDB 存储引擎与 MongoDB 字典源在集合名为空或含 NUL 字节时崩溃。源码中的校验逻辑清晰可见src/Storages/StorageMongoDB.cpp/// It treats the name as a NUL-terminated C string, so any embedded NUL truncates it and can produce an /// effectively empty collection name, which aborts the process inside the driver. throw Exception(ErrorCodes::BAD_ARGUMENTS, MongoDB collection name must be non-empty and must not contain NUL characters);根因是底层 mongo-c-driver 将集合名按 C 字符串NUL 结尾处理内嵌 NUL 会截断名称、产生空集合名进而在驱动内部中止进程。修复后改为在进入驱动前抛出BAD_ARGUMENTS异常。后台命名集合重载异常#92717使用 ZooKeeper 存储的命名集合named collections在后台重载时存在未捕获异常现已修复。4.5 访问控制与权限相关system.dictionaries返回 0 行#106105部分撤销SHOW DICTIONARIES权限后system.dictionaries系统表错误地返回 0 行现已修复。ZooKeeper 读取期间持有互斥锁#107097访问实体access entities刷新过程中不再在 ZooKeeper 读取期间持有 mutex消除该路径上的锁竞争与潜在阻塞。4.6 查询优化器相关optimize_using_constraints与相关子查询#106349当基于约束的优化optimize_using_constraints设置默认关闭定义见 src/Core/Settings.cpp与关联子查询correlated subqueries组合使用时此前可能崩溃或报NOT_FOUND_COLUMN_IN_BLOCK错误现已修复。五、BACKUP/RESTORE 修复Keeper 重试与重复部件本版针对ReplicatedMergeTree的备份恢复路径做了两项重要修复RESTORE 使用专用 Keeper 重试预算#104610恢复复制表时部件挂载part attachment操作改用backup_restore_keeper_max_retries作为重试上限而不是常规插入路径的 Keeper 重试预算。这意味着 BACKUP/RESTORE 这类长事务操作不会因一次临时的 ZooKeeper 抖动而在中途整体失败。该设置的定义与语义在 src/Core/SettingsChangesHistory.cpp 中有明确记录backup_restore_keeper_max_retries, 20, 1000, Should be big enough so the whole operation BACKUP or RESTORE operation wont fail because of a temporary [Zoo]Keeper failure in the middle of it.该设置在设置变更历史中出现于多个版本默认值为 20上限 1000同时派生出backup_restore_keeper_max_retries_while_initializing与backup_restore_keeper_max_retries_while_handling_error两个阶段化子设置默认 0~20。RESTORE 保留重复内容部件#107652从备份恢复ReplicatedMergeTree表时包含重复内容的部件此前会被静默去重deduplicated而丢失现在会原样保留确保备份的字节级一致性。相关实现位于 src/Backups/RestorerFromBackup.cpp配合 src/Backups/BackupEntriesCollector.cpp 与 src/Backups/BackupKeeperSettings.cpp 构成完整的备份/恢复 Keeper 设置链路。对依赖备份做容灾恢复的用户这两项修复直接关系到恢复数据的完整性与恢复流程的可靠性建议在升级后针对复制表做一次备份 → 清空 → 恢复 → 校验行数的回归验证。六、构建/测试/打包改进与依赖升级本版集中升级了一批 bundled 依赖全部由 ClickHouse 维护者统一提交依赖版本变化说明libxml22.15.1 → 2.15.3上游安全修复postgres嵌入式测试工具REL_18_4跟随 PostgreSQL 18.4krb51.22.2Kerberos 库升级curl8.20.0bundled curl 升级对应 contrib/curl-cmake 体系mariadb-connector-c3.1.29保留全部 ClickHouse 相关补丁mongo-c-driver2.3.0归类为 NOT FOR CHANGELOG但同样完成升级在NOT FOR CHANGELOG / INSIGNIFICANT类别中还包括发布分支跳过test_numbers_check测试#105492、修复test_mysql_dotnet_client的锚点#105636、以及 bump cc-debian13 镜像 digest 以消除 libssl3t64 的 CVE-2026-45447。从构建体系看ClickHouse 的三方依赖通过 contrib/update-submodules.sh 与各*-cmake子模块统一管理例如 contrib/curl-cmake 下的构建接入点这类零散依赖升级 统一 backport的做法保证了 LTS 分支既能吃到上游安全修复又不引入破坏性 API 变更。七、升级建议与验证清单综合本版变更建议按以下优先级规划升级1. 立即评估升级安全相关HTTPX-ClickHouse-Query-IdCRLF 注入#100500复制表部件获取路径遍历#107606EXPLAIN 密钥参数泄露#108386多条由单一SELECT即可触发的服务器崩溃decodeHTMLComponent#106741、windowFunnel#107412、深嵌套多格式栈溢出#107341。2. 重点回归验证功能相关使用 Arrow/Parquet/ORC 文件导入的链路特别是来自 SparkArrow Java 19.0.0的文件使用windowFunnel的漏斗分析查询使用 Dynamic / JSON 类型的表特别是 ALTER 与 Native 格式读写MongoDB 存储引擎/字典/表函数BACKUP/RESTORE 复制表流程重点验证重复部件与 Keeper 抖动下的恢复。3. 修复行为变化的确认system.dictionaries在部分撤销SHOW DICTIONARIES权限后的行数EXPLAIN 系列输出中对encrypt/decrypt/HMAC密钥参数的脱敏表现深嵌套输入从崩溃变为抛出异常的行为转变——应用侧可能需要对这类异常做捕获处理。需要特别说明的是本版的多数格式解析器修复Arrow、Parquet、ORC、MsgPack 等均属于可从不可信输入触发的攻击面。凡是开放了 HTTP 接口、允许用户通过file()/format()表函数或 ArrowFlight 投喂数据的环境都应将此版本视为安全补丁版而不是普通的例行升级。附本版 Bug Fix 速查表PR模块问题类型一句话摘要#92717命名集合崩溃/异常ZooKeeper 存储的后台重载未捕获异常#100500HTTP安全query_id CRLF 注入#102417Avro栈溢出嵌套类型反序列化#104610BACKUP/RESTORE功能恢复部件挂载改用专用 Keeper 重试预算#105449Arrow越界/空指针损坏偏移与 geo 列空指针#105464Dynamic 列崩溃ALTER 后压缩 Memory 表子列读取 SIGSEGV#105535JSON崩溃singleValueOrNull 反序列化 SEGFAULT#105579解析器崩溃TO INNER UUID 空 ENGINE 空指针#105582VALUES崩溃不同尺寸元组插入 String 列#105666Dynamic 列越界Native 反序列化 OOB#105776MongoDB崩溃空集合名/NUL 字节#106105权限功能system.dictionaries 返回 0 行#106349优化器崩溃optimize_using_constraints 关联子查询#106395Arrow IPC越界多类缓冲区校验缺失#106739Parquet/Avro越界/资源DataPageV2 长度、深嵌套、忽略内存上限#106741decodeHTMLComponent越界≫⃒/≪⃒ 扩展实体溢出#107097Access性能ZooKeeper 读取期间持有 mutex#107341多格式栈溢出深嵌套输入拒绝#107412windowFunnel越界越界事件类型状态最终化#107485PostgreSQL 协议下溢长度字段小于 4#107579ELF/DWARF越界缺失边界检查#107580ORC越界缺失边界检查#107606复制表安全部件获取路径遍历#107652BACKUP/RESTORE功能重复内容部件被静默去重#107764Arrow兼容Spark 空 String/Binary 列报 INCORRECT_DATA#107956Map/Dynamic崩溃has LowCardinality 查找崩溃#108386EXPLAIN安全隐藏密钥函数参数完整变更原文见 docs/changelogs/v25.8.25.37-lts.md本仓库 docs/changelogs 目录下还保留了全量版本历史可供横向对比。【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻