Hi all, I'd like to share a bug fix introduced by the following PR:
- master: https://github.com/apache/iotdb/pull/18573 Previously, COPY ... TO accepted any client-supplied target path, including absolute paths and relative paths containing a parent component. A user holding only the privilege to run COPY TO could therefore export a TsFile into directories that the server watches and automatically loads from — such as the active-load listening and pipe directories. Because those directories are ingested by the server with SUPER_USER privileges, this let an unprivileged user escalate privileges by planting a crafted TsFile. The same flexibility also allowed writes to arbitrary locations outside the managed export directories. The root cause is that the relational analyzer only performed a global system-privilege check for COPY TO and never validated the client-supplied target path against the locations the server is willing to export to. The fix restricts client-supplied export paths: - A target path that contains a parent component (absolute, or relative with directories) is now rejected unless it is strictly inside one of the directories configured in the new copy_to_allowed_export_dirs setting. - copy_to_allowed_export_dirs is empty by default, so such paths are rejected out of the box. - Validation is done on canonical paths, so .. and symlink tricks cannot escape the allowlist; a target equal to an allowed directory is also rejected. - Bare file names are still accepted and continue to land in the managed copyto folder. Main changes include: - Added FileUtils.isFilePathAllowed() to check, after canonicalization, that a target path is strictly under one of the allowed directories. - StatementAnalyzer.visitCopyTo now validates the target path and fails with COPY_TO_WRITE_ERROR when it is outside the allowed export directories. - Added the copy_to_allowed_export_dirs config (hot-reloadable, SECURITY privilege) to IoTDBConfig, IoTDBDescriptor, and iotdb-system.properties.template. - Added the English/Chinese message COPY_TO_TARGET_PATH_NOT_ALLOWED and unit/integration tests (FileUtilsTest, PropertiesTest, IoTDBCopyToTsFileIT). Feedback and suggestions are welcome. 大家好, 我想分享以下 PR 中修复的一个问题: - master:https://github.com/apache/iotdb/pull/18573 此前,COPY ... TO 会接受客户端传入的任意目标路径,包括绝对路径以及带父目录的相对路径。这样一来,只有执行 COPY TO 权限的用户,就可以把 TsFile 导出到服务端会监控并自动加载的目录中,例如 active-load 监听目录和 pipe 目录。由于服务端会以 SUPER_USER 权限加载这些目录中的数据,攻击者只需放入一个精心构造的 TsFile,就能借机提权。同时,这种不受限的路径也允许写入受管导出目录之外的任意位置。 根本原因是:关系模型分析器对 COPY TO 只做了全局系统权限检查,从未校验客户端传入的目标路径是否落在服务端允许导出的目录内。 本次修复对客户端传入的导出路径做了限制: - 目标路径只要包含父目录(绝对路径,或带目录的相对路径),就必须严格位于新增配置 copy_to_allowed_export_dirs 所配置的目录之内,否则一律拒绝。 - copy_to_allowed_export_dirs 默认为空,因此这类路径开箱即被拒绝。 - 校验基于规范化(canonical)路径,.. 和软链接等手段无法绕过白名单;目标路径恰好等于某个允许目录时也会被拒绝。 - 仅含文件名的路径仍然允许,继续落到受管的 copyto 目录。 主要修改包括: - 新增 FileUtils.isFilePathAllowed(),在规范化之后校验目标路径是否严格位于某个允许目录之下。 - StatementAnalyzer.visitCopyTo 增加目标路径校验,不在允许导出目录内时以 COPY_TO_WRITE_ERROR 报错。 - 在 IoTDBConfig、IoTDBDescriptor 和 iotdb-system.properties.template 中新增 copy_to_allowed_export_dirs 配置(支持热加载,SECURITY 权限)。 - 新增中英文提示 COPY_TO_TARGET_PATH_NOT_ALLOWED,并补充单元/集成测试(FileUtilsTest、 PropertiesTest、IoTDBCopyToTsFileIT)。 欢迎大家提出反馈和建议。 Best regards, Wenwei Shu
