ProFTPD 1.3.9d - 高危 - 远程 - 权限残留 / 文件写入 - SITE COPY 目标跟随符号链接
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · proftpd-site-copy-dest-follow
类别: 权限残留 / 文件写入 可达性: 远程
ProFTPD 1.3.9d (f59f248) - proftpd.org
Contrib mod_copy 的 SITE COPY 使用 dir_canonical_vpath(未解析)对目标进行 Limit 检查。随后 pr_fs_copy_file2 在 open 目标时未使用 O_NOFOLLOW,因此会跟随目标符号链接。FTP STOR 对已解析路径(dir_realpath / dir_best_path)进行 Limit 检查。SITE COPY 的目标则不会。
已认证的 FTP 用户通过将目标符号链接指向一个 WRITE 被拒绝的文件并发出 SITE COPY,即可覆盖该文件。 直接 STOR 和 SITE COPY 到受害文件仍返回 550。对链接的 STOR / SITE RMDIR / RMD 仍返回 550。DELE 仅删除链接节点。无 shell。Unix DAC 仍然生效。
这是公开 Issue 2095(SITE COPY 源 READ 跳过)的反向问题。它与公开 Issue 2256(RNTO EXDEV 符号链接跟随)不同。此残留问题在每次复制时都影响 SITE COPY 目标,而不仅限于 EXDEV。
| ID | 暂无 CVE |
| 类别 | 权限残留 / 文件写入 |
| 可达性 | 远程(已认证 FTP) |
| CWE | CWE-59, CWE-863 |
| CVSS | 高危:7.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N |
| 产品 | ProFTPD |
| 受影响版本 | 1.3.9d 标签 v1.3.9d (f59f248e26bdfa514443e42bf72a145641df635d) contrib mod_copy |
| 认证 | 已认证 FTP(加载 mod_copy,CopyEngine 默认开启)。SITE SYMLINK 植入还需要 contrib mod_site_misc,除非链接已存在 |
| 许可证 | GNU Affero GPL v3.0 |
| 实验环境 | 仅 127.0.0.1 |
谁:已认证的 FTP 用户。已加载 mod_copy。在 WRITE 允许的目录中存在一个目标符号链接(通过 SITE SYMLINK,或预先存在的链接)。SITE SYMLINK 源使用 dir_check_canon G_READ,因此植入一个指向受害文件的链接需要对该文件具有 READ 权限。这种分离是 READ 允许、WRITE 拒绝。会话 UID 仍必须能够以 Unix 方式写入目标。
| 方法 | 汇聚点 | 权限 |
|---|---|---|
| 在 WRITE 允许的目录中 SITE SYMLINK(或已存在的链接),其目标为 WRITE 被拒绝但 UID 能以 Unix 方式写入的文件;SITE COPY 可读源到该链接 | pr_fsio_open 目标跟随 | 完整性(实验证明): 以会话 UID 截断/覆盖 Limit 拒绝的文件。实验:/secret/victim 从 ORIGINAL 变为见证内容,执行 SITE COPY /readable/src.txt /upload/link 后。直接 SITE COPY 到 /secret/victim 仍返回 550。 |
| 对同一链接执行 SITE RMDIR | dir_check_canon -> dir_best_path | 已关闭(实验证明): 550 RMDIR /upload/link: Operation not permitted。受害文件完好。 |
| 对同一链接执行核心 RMD | dir_best_path + WRITE | 已关闭(实验证明): 550 Permission denied。受害文件完好。 |
| 对目标链接执行 STOR | dir_best_path + WRITE | 已关闭(实验证明): STOR /upload/link -> 550。受害文件完好。 |
| 对目标链接执行 DELE | unlink 链接节点 | 对受害文件已关闭(实验证明): DELE 仅删除了链接;受害文件仍持有见证内容。 |
DefaultRoot 囚禁到主机 /etc | chroot | 已关闭。Unix DAC 仍然生效。无未认证。无 shell。 |
实验证明与推断: 通过未解析目标符号链接覆盖、STOR/RMDIR/RMD 被拒绝、以及 DELE 仅删除链接均为实验证明。未认证和 Unix DAC 仍从认证/chroot 模型推断。
我固定了 proftpd/proftpd v1.3.9d (f59f248)。默认核心 FTP 配合示例 basic.conf 没有未公开的严重/高危问题。接下来是 contrib mod_copy。
copy_copy(contrib/mod_copy.c)使用 dir_canonical_vpath 构建目标,然后对该未解析字符串执行 dir_check(..., G_WRITE, to)。pr_fs_copy_file2(src/fsio.c)注释说明 stat/open 会跟随目标符号链接,然后 pr_fsio_open(dst, O_WRONLY|O_CREAT|O_NONBLOCK) 未使用 O_NOFOLLOW。
公开 Issue 2095 是 SITE COPY 的源 READ 跳过。跳过那个确切的 bug。公开 Issue 2256 是 RNTO EXDEV 跟随。此残留问题在每次复制时都影响 SITE COPY 目标。
SITE RMDIR 递归跟随是一个父级遗漏:SITE RMDIR 使用 dir_check_canon / dir_best_path,在 Limit 之前解析符号链接。实验确认 SITE RMDIR 和核心 RMD 对目标链接仍被拒绝。
已记录的弯路:因为 STOR 是已解析的就将目标 Limit 视为已解析;将 Issue 2256 视为此残留问题;声称 SITE RMDIR 会遍历受害文件。表演:反向 shell。判定标准是 /secret/victim 在通过 /upload/link 执行 SITE COPY 后持有见证内容,而对链接的 STOR 仍返回 550。
python3 proftpd-site-copy-dest-follow-Abraxas-Labs.py
或:
cd lab
./run.sh
回环 FTP 127.0.0.1:18720,被动模式 18721-18730。Compose 项目 proftpd-site-copy-dest-follow。见证内容 PROFTPD-SITE-COPY-DEST-FOLLOW-WITNESS。最后一行:
SUCCESS PROFTPD-SITE-COPY-DEST-FOLLOW victim-has-witness=yes stor-secret=denied stor-link=denied site-rmdir-walk=no rmd-walk=no dele-victim=intact PROFTPD-SITE-COPY-DEST-FOLLOW-WITNESS
对已解析的目标进行 Limit 检查(dir_realpath / dir_best_path),或使用 O_NOFOLLOW 打开目标。STOR 已经对已解析路径进行 Limit 检查。
供应商接收邮箱为 [email protected]。请勿在 proftpd/proftpd 上开启公开 GitHub issue。
f59f248e26bdfa514443e42bf72a145641df635d)contrib/mod_copy.c copy_copysrc/fsio.c pr_fs_copy_file2<Limit READ>GNU Affero GPL v3.0。参见 LICENSE。仅限回环实验环境。无担保。