Selamat siang, mungkin banyak yang telah mendengar tentang kerentanan terkini di router Mikrotik, yang memungkinkan Anda untuk mengekstrak kata sandi semua pengguna. Dalam artikel ini, saya ingin menunjukkan dan menganalisis secara rinci esensi dari kerentanan ini.
Semua materi disediakan hanya untuk tujuan informasi, sehingga kode yang mengeksploitasi kerentanan tidak akan ada di sini. Jika Anda tidak tertarik mempelajari penyebab dan struktur internal kerentanan tertentu, Anda dapat membaca.
Mari kita mulai
Hal pertama yang harus dimulai adalah analisis lalu lintas antara klien Winbox dan perangkat
Winbox adalah aplikasi untuk OS WIndows, yang persis mengulangi antarmuka web dan dirancang untuk mengelola dan mengkonfigurasi perangkat dengan OS Router on board. 2 mode operasi yang didukung, TCP dan UDP
Sebelum Anda mulai, Anda harus menonaktifkan enkripsi lalu lintas di Winbox. Ini dilakukan sebagai berikut: Anda perlu mengaktifkan kotak centang
Tools ->
Advanced Mode . Setelah itu, antarmuka akan berubah sebagai berikut:
Hapus centang pada
Mode Aman . Luncurkan Wireshark dan coba masuk ke perangkat:
Seperti yang dapat Anda lihat di bawah, setelah otorisasi, file
daftar diminta dan kemudian isinya ditransfer sepenuhnya kepada kami, sepertinya semuanya baik-baik saja, tetapi mari kita lihat di awal sesi ini:
Pada awalnya, Winbox mengirimkan paket yang sama persis meminta file
daftar :
Pertimbangkan strukturnya:
- 37010035 - ukuran paket
- M2 adalah konstanta yang mengindikasikan awal suatu paket
- 0500ff01 - variabel 0xff0005 pada nilai True
- 0600ff09 01 - variabel 0xff0006 pada nilai 1 (Jumlah paket yang dikirimkan)
- 0700ff09 07 - variabel 0xff0007 pada nilai 7 (Buka file dalam mode baca)
- 01000021 04 6967374 - daftar string variabel 0x01000001 4 byte (Biasanya variabel ini bertanggung jawab untuk nama file)
- 0200ff88 02 ... 00 - array 0xff0002 dengan ukuran 2 elemen
- 0100ff88 02 ... 00 - array 0xff0001 dengan ukuran 2 elemen
Sebagai hasil dari protokol terbalik, dan file-file biner yang sesuai pada sisi klien dan server, dimungkinkan untuk memulihkan dan memahami struktur protokol di mana Winbox berkomunikasi dengan perangkat.
Uraian Protokol NvMessageJenis Bidang (Nama: Penunjukan Digital)
- u32: 0x08000000
- u32_array: 0x88000000
- string: 0x20000000
- string_array: 0xA0000000
- addr6: 0x18000000
- addr6_array: 0x98000000
- u64: 0x10000000
- u64_array: 0x90000000
- true: 0x0000000000
- false: 0x01000000
- bool_array: 0x80000000
- pesan: 0x28000000
- message_array: 0xA8000000
- mentah: 0x30000000
- raw_array: 0xB0000000
- u8: 0x09000000
- be32_array: 0x88000000
Jenis kesalahan (Nama: Penunjukan digital)
- SYS_TO: 0xFF0001
- STD_UNDOID: 0xFE0006
- STD_DESCR: 0xFE0009
- STD_FINISHED: 0xFE000B
- STD_DYNAMIC: 0xFE0007
- STD_INACTIVE: 0xFE0008
- STD_GETALLID: 0xFE0003
- STD_GETALLNO: 0xFE0004
- STD_NEXTID: 0xFE0005
- STD_ID: 0xFE0001
- STD_OBJS: 0xFE0002
- SYS_ERRNO: 0xFF0008
- SYS_POLICY: 0xFF000B
- SYS_CTRL_ARG: 0xFF000F
- SYS_RADDR6: 0xFF0013
- SYS_CTRL: 0xFF000D
- SYS_ERRSTR: 0xFF0009
- SYS_USER: 0xFF000A
- SYS_STATUS: 0xFF0004
- SYS_FROM: 0xFF0002
- SYS_TYPE: 0xFF0003
- SYS_REQID: 0xFF0006
Nilai Kesalahan (Nama: Penunjukan Digital)
- ERROR_FAILED: 0xFE0006
- ERROR_TOOBIG: 0xFE000A
- ERROR_EXISTS: 0xFE0007
- ERROR_NOTALLOWED: 0xFE0009
- ERROR_BUSY: 0xFE000C
- ERROR_UNKNOWN: 0xFE0001
- ERROR_BRKPATH: 0xFE0002
- ERROR_UNKNOWNID: 0xFE0004
- ERROR_UNKNOWNNEXTID: 0xFE000B
- ERROR_TIMEOUT: 0xFE000D
- ERROR_TOOMUCH: 0xFE000E
- ERROR_NOTIMP: 0xFE0003
- ERROR_MISSING: 0xFE0005
- STATUS_OK: 0x01
- STATUS_ERROR: 0x02
Struktur bidang dalam suatu paket
Pada awal bidang apa pun adalah jenisnya - 4 byte (3 byte - tujuan variabel, lebih lanjut tentang itu nanti, 1 byte - langsung tipe variabel ini) maka panjangnya 1-2 byte dan nilainya sendiri.
Array
Secara kiasan, array dapat dijelaskan oleh struktur berikut:
struct Array { uint32 type; uint8 count; uint32 item1; uint32 item2; ... uint8 zero; }
Ketik (4 byte) / Jumlah elemen (1 byte) / Elemen (4 byte) / Di akhir byte \ x00
Garis
String tidak diakhiri null, tetapi memiliki panjang yang jelas:
struct String { uint32 type; uint8 length; char text[length]; }
Angka-angka
Jenis paling sederhana dalam paket, dapat direpresentasikan sebagai tipe nilai:
struct u* { uint32 type; uint8/32/64 value; }
Bergantung pada jenisnya, nilainya memiliki dimensi bit yang sesuai.
Tipe Boolean
Ukuran bidang adalah 4 byte, byte tinggi bertanggung jawab atas nilai (True \ False), 3 byte lebih rendah untuk menetapkan variabel
Selain itu, setiap paket berisi:
- spidol khusus untuk menunjukkan awal paket
- ukuran paket
- pasar kontrol paket besar
Konstanta yang ditemukan
- 0xfe0001 - Berisi pengidentifikasi sesi (1 byte)
- 0xff0006 - Jumlah paket yang dikirim (1 byte)
- 0xff0007 - Mode Akses File (1 byte)
Mode Akses File
- 7 - terbuka untuk membaca
- 1 - terbuka untuk perekaman
- 6 - buat direktori
- 4 - baca
- 5 - hapus
Sekarang, mengetahui cara kerja protokol, kita dapat secara acak menghasilkan paket yang kita butuhkan dan melihat bagaimana perangkat meresponsnya.
Di sisi perangkat, executable
/ nova / bin / mproxy bertanggung jawab untuk memproses paket. Karena nama-nama fungsi tidak disimpan, saya memanggil fungsi yang memproses paket dan membuat keputusan tentang apa yang harus dilakukan dengan file
file_handler () . Lihatlah fungsi itu sendiri:
PS Kode yang akan menarik bagi kita ditandai dengan panah.
Langkah 1
Saat menerima paket untuk membuka file untuk dibaca, itu mulai diproses dari blok ini:
Pada awalnya, nama file diekstraksi dari paket menggunakan fungsi
nv :: message :: get <nv :: string_id> () .
Selanjutnya, fungsi
tokenize () membagi string yang dihasilkan menjadi bagian yang terpisah, menggunakan karakter "
/ " sebagai pembatas.
Array string yang dihasilkan dilewatkan ke fungsi
path_filter () , yang memeriksa array string yang diterima untuk keberadaan "
.. ", dan jika ada kesalahan mengembalikan kesalahan
ERROR_NOTALLOWED (0xFE0009)PS ERROR_NOTALLOWED juga akan diterima dalam respons jika tidak ada izin file
Jika semuanya baik-baik saja, maka path ke direktori
webfig atau
pckg disatukan dengan awal nama file
Langkah 2
Jika semuanya berjalan dengan baik, file terbuka dan pegangannya disimpan ke objek global.
Jika file tidak dapat dibuka, maka dalam respons kami mendapatkan kesalahan:
tidak dapat membuka file sumber .
Jadi, untuk menerima konten file, 3 syarat harus dipenuhi:
- Jalur file tidak mengandung " .. ";
- Ada hak untuk mengakses file;
- File ada dan dapat dibuka dengan sukses.
Sekarang mari kita coba mengirim beberapa paket untuk menguji fungsionalitas fungsi ini:
$ ./untitled.py -t 192.168.88.1 -f /etc/passwd Error: SYS_ERRNO => ERROR_FAILED Error: SYS_ERRSTR => cannot open source file $ ./untitled.py -t 192.168.88.1 -f /../../../etc/passwd Error: SYS_ERRNO => ERROR_NOTALLOWED $ ./untitled.py -t 192.168.88.1 -f //./././././../etc/passwd Error: SYS_ERRNO => ERROR_FAILED Error: SYS_ERRSTR => cannot open source file
Jadi! Tapi ini sudah aneh ... Kita ingat bahwa
ERROR_NOTALLOWED muncul jika check in
path_filter () tidak lulus, kalau tidak kita masih akan menerima pesan tentang kurangnya hak akses, tetapi dalam kasus terakhir, ternyata file tersebut dicari di direktori tingkat atas?
Mari kita coba cara ini:
$ ./untitled.py -t 192.168.88.1 -f //./.././.././../etc/passwd xvM2 1Enobody:*:99:99:nobody:/tmp:/bin/sh root::0:0:root:/home/root:/bin/sh
Dan itu berhasil. Tapi mengapa? Mari kita lihat kode fungsi
path_filter ():Kode dengan jelas menunjukkan bahwa pencarian untuk terjadinya "
.. " di array string yang dihasilkan benar-benar terjadi. Tetapi bagian yang paling menarik, saya menyoroti bagian ini dengan warna merah.
Inti dari kode ini adalah:
Jika item sebelumnya juga " .. ", maka cek dianggap gagal. Kalau tidak, pertimbangkan bahwa semuanya baik-baik saja.
Yaitu Agar semuanya berfungsi, Anda hanya perlu mengganti "
/./ " dan "
/../ " untuk berhasil menavigasi direktori mana pun dan turun ke tingkat FS apa pun.
Mari kita lihat bagaimana pengembang Mikrotik memperbaikinya:
Perbandingan kode pseudo-C Sekarang jalan keluar dari siklus verifikasi terjadi pada deteksi pertama "
.. ". Benar, tidak sepenuhnya jelas bagi saya mengapa mereka menambahkan cek untuk terjadinya satu poin. Dan karena perubahan dalam mekanisme aktivasi pengguna
devel , sayangnya, tidak ada cara untuk melihat ini dalam dinamika.
Untuk meringkas
- Router OS memproses paket yang masuk tanpa masalah bahkan sebelum otorisasi pengguna
- Karena filter yang salah, kami mendapatkan akses ke file apa pun
Dengan paragraf sebelumnya, kita dapat dengan mudah: membuat, menghapus, membaca, dan menulis file, serta membuat direktori arbitrer
Jadi tidak mengherankan bahwa memiliki akses untuk membaca file tanpa otorisasi, hal pertama yang dilakukan adalah membaca file dengan kata sandi pengguna. Untungnya, jaringan memiliki banyak informasi tentang di mana ia berada dan bagaimana cara mengekstrak data darinya.
Selain itu, kerentanan ini dapat menjadi pengganti yang sangat baik untuk kemungkinan yang sebelumnya diketahui mengaktifkan mode pengembang, karena Anda tidak perlu me-restart perangkat, lakukan
backup \
restore file konfigurasi sekarang.