
CVE-2017-8291 CTF con docker y ejemplos
El módulo PIL (Pillow) para procesar imágenes en Python se ve afectado por la vulnerabilidad GhostButt (CVE-2017-8291) porque llama internamente a GhostScript, lo que resulta en una vulnerabilidad de ejecución remota de comandos.
PIL determina internamente el tipo de imagen basándose en el encabezado de la imagen (Magic Bytes). Si se determina que es un archivo EPS (el encabezado es %!PS), se envía a PIL/EpsImagePlugin.py para su procesamiento.
En este módulo, PIL llama al comando gs del sistema, que es GhostScript, para procesar archivos de imagen:
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)
Aunque se establece -dSAFER, es decir, el modo seguro, debido a una vulnerabilidad de omisión de sandbox en GhostScript (GhostButt CVE-2017-8291), este modo seguro se elude y se pueden ejecutar comandos arbitrarios.
Además, hasta ahora, la última versión oficial de GhostScript 9.21 todavía se ve afectada por esta vulnerabilidad, por lo que se puede decir que mientras GhostScript esté instalado en el sistema operativo, nuestro PIL tiene una vulnerabilidad de ejecución de comandos.
Entorno operativo:
docker-compose up -d
Después de ejecutar, visita http://your-ip:8000/ para ver una página de carga. La función normal es que subimos un archivo PNG, el backend llama a PIL para cargar la imagen y genera el largo y ancho. Pero podemos cambiar la extensión del archivo EPS de comando ejecutable a PNG para subirlo, porque el backend determina el tipo de imagen basándose en el encabezado del archivo, por lo que la verificación de la extensión se ignora.
Por ejemplo, si subimos poc.png, podemos ejecutar touch /tmp/youhavebeenpwned. Cambia el comando en el POC a un comando de rebote para obtener una shell: