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

Reply via email to