Encontraron una vulnerabilidad en Python que permite ejecutar comandos desde scripts de espacio aislado
Hace pocos dias se dio a conocer un método para eludir los sistemas de ejecución de código aislado de Python, basado en el uso de un error conocido desde hace mucho tiempo que apareció en Python 2.7, identificado en 2012 y aún no solucionado en Python 3.
Se menciona que el error permite usar código de Python especialmente vinculado para iniciar una llamada a la memoria ya liberada (Use-After-Free) en Python. Inicialmente, se asumió que el error no representa una amenaza para la seguridad y solo en casos muy raros, generalmente creados artificialmente, puede provocar una terminación anormal del script.
Un investigador de seguridad bajo el seudónimo kn32 se interesó en el problema y logró preparar un exploit funcional que hace posible llamar a cualquier comando del sistema sin tener acceso directo a métodos como os.system.
El exploit se implementa en Python puro y funciona sin importar bibliotecas externas y sin instalar el controlador «code.__new__». De los ganchos, solo se usa «builtin.__id__», que generalmente no está prohibido. En el aspecto práctico, el código propuesto se puede utilizar para eludir los mecanismos de aislamiento en varios servicios y entornos (por ejemplo, en entornos de aprendizaje, shells en línea, controladores integrados, etc.) que permiten la ejecución del código Python, pero limitan las llamadas disponibles y no permita métodos de acceso como os.system.
El código propuesto es un análogo de la llamada os.system, que funciona mediante la explotación de una vulnerabilidad en CPython. El exploit funciona con todas las versiones de Python 3 en sistemas x86-64 y es estable en Ubuntu 22.04 incluso con los modos de seguridad PIE, RELRO y CET habilitados.
El trabajo se reduce a obtener del código Python información sobre la dirección de una de las funciones en el código ejecutable CPython.
En función de esta dirección, se calculan la dirección base de CPython en la memoria y la dirección de la función system() en la instancia de libc cargada. Al final, se inicia una transición directa a un determinado sistema de direcciones con la sustitución del puntero del primer argumento por la cadena «/bin/sh».
El enfoque más fácil para la explotación es crear una lista con una longitud igual a la longitud del búfer liberado, que muy probablemente tendrá su búfer de elementos (ob_item) asignado en el mismo lugar que el búfer liberado.
Esto significará que obtendremos dos «vistas» diferentes en la misma pieza de memoria. Una vista, la memoryview, piensa que la memoria es solo una matriz de bytes, en la que podemos escribir o leer arbitrariamente. La segunda vista es la lista que creamos, que piensa que la memoria es una lista de PyObjectpunteros. Esto significa que podemos crear correos electrónicos falsos PyObjecten algún lugar de la memoria, escribir sus direcciones en la lista escribiendo en el memoryviewy luego acceder a ellos indexando la lista.
En el caso del PoC, escriben 0en el búfer (línea 16) y luego acceden con print(L[0]). L[0]obtiene el primero PyObject*que es 0y luego printintenta acceder a algunos campos en él, lo que resulta en una desreferencia de puntero nulo.
Se menciona que este error está presente en todas las versiones de Python desde al menos Python 2.7 y aunque el exploit fue diseñado para funcionar sobre casi cualquier versión de Python 3, esto no quiere decir que no sea reproducible en Python 2 (a palabras del autor).
El objetivo del exploit es llamar a system(«/bin/sh») cuyos pasos son los siguientes:
- Puntero de función binaria de fuga CPython
- Calcular la dirección base de CPython
- Calcular la dirección de systemo su PLT stub
- Salta a esta dirección con el primer argumento apuntando a/bin/sh
- Ganar
Por último, se menciona que el exploit no será útil en la mayoría de las configuraciones. Sin embargo, ser puede ser útil en los intérpretes de Python que intentan aislar el código, restringiendo las importaciones o el uso de Audit Hooks.
Finalmente si estás interesado en poder conocer más al respecto sobre la nota, puedes consultar la publicación original en el siguiente enlace.