
CVE-2017-8291 CTF с Docker и примерами
Модуль PIL (Pillow) для обработки изображений в Python подвержен уязвимости GhostButt (CVE-2017-8291), поскольку он внутренне вызывает GhostScript, что приводит к уязвимости удаленного выполнения команд.
PIL внутренне определяет тип изображения на основе заголовка изображения (Magic Bytes). Если обнаружено, что это файл EPS (заголовок — %!PS), он передается для обработки в PIL/EpsImagePlugin.py.
В этом модуле PIL вызывает системную команду gs, которая является GhostScript, для обработки файлов изображений:
command = ["gs",
"-q", # quiet mode
"-g%dx%d" % size, # set output geometry (pixels)
"-r%fx%f" % res, # set input DPI (dots per inch)
"-dBATCH", # exit after processing
"-dNOPAUSE", # don't pause between pages,
"-dSAFER", # safe mode
"-sDEVICE=ppmraw", # ppm driver
"-sOutputFile=%s" % outfile, # output file
"-c", "%d %d translate" % (-bbox[0], -bbox[1]),
# adjust for image origin
"-f", infile, # input file
]
# Omit the code to determine whether GhostScript is installed
try:
with open(os.devnull, 'w+b') as devnull:
subprocess.check_call(command, stdin=devnull, stdout=devnull)
im = Image.open(outfile)
Хотя установлен -dSAFER, то есть безопасный режим, из-за уязвимости обхода песочницы в GhostScript (GhostButt CVE-2017-8291) этот безопасный режим обходится, и могут быть выполнены произвольные команды.
Кроме того, на данный момент последняя официальная версия GhostScript 9.21 все еще подвержена этой уязвимости, поэтому можно сказать, что пока GhostScript установлен в операционной системе, наш PIL имеет уязвимость выполнения команд.
Рабочая среда:
docker-compose up -d
После запуска перейдите по адресу http://your-ip:8000/, чтобы увидеть страницу загрузки. Обычная функция заключается в том, что мы загружаем PNG-файл, бэкенд вызывает PIL для загрузки изображения и выводит длину и ширину. Но мы можем изменить суффикс выполняющего команды EPS-файла на PNG для загрузки, поскольку бэкенд определяет тип изображения по заголовку файла, поэтому проверка суффикса игнорируется.
Например, если мы загрузим poc.png, мы сможем выполнить touch /tmp/youhavebeenpwned. Измените команду в POC на обратную команду, чтобы получить оболочку: