Gambar: PexelsDengan rilis pembaruan Januari untuk Windows, berita tentang kerentanan kritis yang berbahaya
CVE-2019-0547 di klien DHCP menggerakkan publik. Peringkat CVSS yang tinggi dan fakta bahwa Microsoft tidak segera mempublikasikan penilaian kinerja, yang menyulitkan pengguna untuk memutuskan pembaruan sistem yang mendesak, menghangatkan minat. Beberapa publikasi bahkan menyarankan bahwa kurangnya indeks dapat diartikan sebagai bukti bahwa eksploitasi kerja akan muncul dalam waktu dekat.
Solusi seperti
MaxPatrol 8 dapat mengidentifikasi komputer di jaringan yang rentan terhadap serangan spesifik. Solusi lain, seperti PT NAD, mendeteksi serangan itu sendiri. Untuk memungkinkan hal ini, perlu untuk menggambarkan aturan untuk mendeteksi kerentanan dalam produk dan aturan untuk mendeteksi serangan pada produk ini. Pada gilirannya, untuk memungkinkan hal ini, setiap kerentanan individu perlu mengetahui vektor, metode dan kondisi operasinya, yaitu, secara harfiah semua detail dan nuansa yang terkait dengan operasi. Pemahaman yang jauh lebih lengkap dan lebih dalam diperlukan daripada apa yang biasanya dapat dikompilasi dari deskripsi di situs vendor atau di CVE, seperti:
Kerentanan terwujud karena sistem operasi salah memproses objek dalam memori.
Jadi, untuk menambah produk perusahaan aturan untuk mendeteksi serangan pada kerentanan yang baru dibuat di DHCP, serta aturan untuk mengidentifikasi perangkat yang terkena dampaknya, Anda harus memahami detailnya. Dalam kasus kerentanan biner, patch-diff sering digunakan untuk mendapatkan wawasan tentang kesalahan yang mendasarinya, yaitu, perbandingan perubahan yang dibuat dengan kode biner aplikasi, pustaka atau kernel dari sistem operasi dengan patch tertentu, pembaruan yang memperbaiki kesalahan ini. Tapi tahap pertama selalu pengintaian.
Catatan :
Untuk langsung ke deskripsi kerentanan, melewati konsep DHCP yang mendasarinya, Anda dapat melewati beberapa halaman pertama dan langsung ke bagian "Fungsi DecodeDomainSearchListData".Pengintaian
Kami beralih ke mesin pencari dan melihat semua detail kerentanan yang dikenal saat ini. Kali ini ada detail minimum, dan semuanya adalah prosesi gratis dari informasi yang dikumpulkan dari
publikasi asli di situs web MSRC. Situasi ini cukup khas untuk kesalahan yang ditemukan oleh Microsoft selama audit internal.
Kami mengetahui dari publikasi bahwa kami dihadapkan dengan kerentanan kerusakan memori, yang terkandung dalam sistem klien dan server Windows 10 versi 1803 dan muncul saat penyerang mengirimkan respons yang dibuat khusus untuk klien DHCP. Setelah beberapa hari sejak saat itu di halaman, indeks kinerja juga akan muncul:

Seperti yang Anda lihat, MSRC memberi peringkat "2 - Eksploitasi Kurang Mungkin". Ini berarti bahwa kesalahan dengan probabilitas tinggi sama sekali tidak operasional sama sekali, atau operasi itu penuh dengan kesulitan seperti itu, mengatasi yang akan memerlukan biaya tenaga kerja terlalu tinggi. Memang, Microsoft tidak cenderung meremehkan perkiraan tersebut. Ini sebagian dipengaruhi oleh risiko kerugian reputasi, dan sebagian oleh beberapa independensi dari pusat respons dalam perusahaan. Oleh karena itu, anggaplah: karena ancaman eksploitasi ditunjukkan dalam laporan sebagai tidak mungkin, tentu saja demikian. Sebenarnya, ini bisa menyelesaikan analisis, tetapi tidak akan berlebihan untuk memeriksa ulang dan setidaknya mencari tahu apa kerentanannya. Pada akhirnya, terlepas dari semua kepribadian yang tidak dapat disangkal, kesalahan cenderung terulang dan muncul di tempat lain.
Dari halaman yang sama kami mengunduh patch (pembaruan keamanan) yang disediakan dalam bentuk arsip .msu, buka paketnya dan cari file yang kemungkinan besar terkait dengan pemrosesan respons DHCP di sisi klien. Baru-baru ini, telah menjadi jauh lebih sulit untuk melakukan ini, karena pembaruan mulai dikirimkan bukan dalam bentuk paket terpisah yang memperbaiki kesalahan spesifik, tetapi sebagai paket kumulatif tunggal yang mencakup semua koreksi bulanan. Ini sangat meningkatkan kelebihan noise, yaitu perubahan yang tidak terkait dengan tugas kami.
Di antara seluruh set file, pencarian menemukan beberapa pustaka yang cocok untuk filter, yang kami bandingkan dengan versinya pada sistem yang tidak ditambal. Pustaka dhcpcore.dll terlihat paling menjanjikan. Dalam hal ini,
BinDiff menghasilkan perubahan minimal:

Sebenarnya, selain perubahan kosmetik yang dilakukan pada satu fungsi - DecodeDomainSearchListData. Jika Anda terbiasa dengan protokol DHCP dan opsinya yang tidak terlalu sering digunakan, maka Anda sudah dapat mengasumsikan bahwa fungsi ini memproses daftar. Jika tidak, maka lanjutkan ke tahap kedua - studi tentang protokol.
DHCP dan opsinya
DHCP (
RFC 2131 |
wiki ) adalah protokol yang dapat diperluas yang kemampuan pengisian ulang disediakan oleh bidang opsi. Setiap opsi dijelaskan oleh tag unik (angka, pengidentifikasi), ukuran yang ditempati oleh data yang terkandung dalam opsi, dan data itu sendiri. Praktik ini merupakan tipikal protokol jaringan, dan salah satu opsi "ditanamkan" ke dalam protokol adalah Opsi Pencarian Domain yang dijelaskan dalam
RFC 3397 . Ini memungkinkan server DHCP untuk menetapkan akhiran nama domain standar pada klien, yang akan digunakan sebagai sufiks DNS untuk koneksi yang dikonfigurasi dengan cara ini.
Biarkan, misalnya, ujung nama berikut ditetapkan pada klien kami:
.microsoft.com .wikipedia.org

Kemudian, dalam upaya apa pun untuk menentukan alamat dengan nama domain, kueri DNS akan menggantikan sufiks dari daftar ini secara bergiliran hingga tampilan yang berhasil ditemukan. Misalnya, jika pengguna memasukkan ru di bilah alamat peramban, maka kueri DNS akan dihasilkan terlebih dahulu untuk ru.microsoft.com, lalu untuk ru.wikipedia.org:

Faktanya, browser modern terlalu cerdas, dan karenanya merespons pengalihan ke mesin pencari ke nama yang tidak mirip dengan FQDN. Oleh karena itu, di bawah ini kami sertakan kesimpulan dari utilitas yang kurang manja:

Tampaknya bagi pembaca bahwa ini adalah kerentanan, karena kemungkinan hanya mengganti sufiks DNS dengan server DHCP, yang dapat diidentifikasi oleh setiap perangkat di jaringan, menimbulkan ancaman bagi klien yang meminta parameter jaringan apa pun melalui DHCP . Tapi tidak: sebagai berikut dari RFC, ini dianggap perilaku yang cukup sah dan terdokumentasi. Sebenarnya, server DHCP secara inheren salah satu komponen tepercaya yang dapat berdampak kuat pada perangkat yang mengaksesnya.
Opsi Pencarian Domain
Opsi Pencarian Domain diberi nomor 0x77 (119). Seperti semua opsi, ini dikodekan dengan tag byte tunggal dengan nomor opsi. Seperti kebanyakan opsi lain, segera setelah tag adalah ukuran byte tunggal dari data yang mengikuti ukuran tersebut. Instance opsi dapat hadir dalam pesan DHCP lebih dari sekali. Dalam hal ini, data dari semua bagian tersebut disatukan dalam urutan di mana mereka muncul dalam pesan.

Dalam contoh yang disajikan, diambil dari
RFC 3397 , data dibagi menjadi tiga bagian, masing-masing 9 byte. Seperti yang dapat Anda lihat dari gambar, nama subdomain dalam nama domain yang memenuhi syarat dikodekan dengan panjang byte tunggal nama, segera diikuti oleh nama itu sendiri. Pengkodean nama domain yang sepenuhnya memenuhi syarat berakhir dengan byte nol (yaitu, nama subdomain berukuran nol).
Selain itu, opsi ini menggunakan metode kompresi data yang paling sederhana, atau lebih tepatnya, hanya beberapa poin. Alih-alih ukuran nama domain, bidang mungkin berisi nilai 0xc0. Kemudian byte berikutnya menetapkan offset relatif ke awal data opsi, yang harus digunakan untuk mencari akhir nama domain.
Jadi, dalam contoh ini, daftar dua sufiks domain dikodekan:
.eng.apple.com .marketing.apple.com
Fungsi DecodeDomainSearchListData
Jadi, nomor opsi DHCP 0x77 (119) memungkinkan server untuk mengkonfigurasi sufiks DNS pada klien. Tetapi tidak pada mesin dengan sistem operasi Windows. Sistem Microsoft secara tradisional mengabaikan opsi ini, jadi secara historis akhir nama DNS, jika perlu, digulirkan melalui kebijakan grup. Ini berlanjut hingga baru-baru ini, ketika rilis Windows 10 berikutnya, versi 1803, menambahkan pemrosesan untuk Opsi Pencarian Domain. Menilai dengan nama fungsi di dhcpcore.dll, di mana perubahan dilakukan, itu adalah dalam penangan tambahan bahwa kesalahan tersebut terletak.
Mulai bekerja. Kami menyisir sedikit kode dan mencari tahu yang berikut. Prosedur DecodeDomainSearchListData, sesuai sepenuhnya dengan namanya, menerjemahkan data dari Opsi Pencarian Domain dari pesan yang diterima dari server. Pada input, ia menerima array data yang dikemas dengan cara yang dijelaskan dalam paragraf sebelumnya, dan pada output, ia menghasilkan string yang diakhiri dengan nol yang berisi daftar ujung nama domain, dipisahkan dengan koma. Misalnya, fungsi ini mengubah data dari contoh di atas menjadi string:
eng.apple.com,marketing.apple.com
DecodeDomainSearchListData dipanggil dari prosedur UpdateDomainSearchOption, yang menetapkan daftar yang dikembalikan ke nilai kunci "DhcpDomainSearchListList":
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{INTERFACE_GUID}\
menyimpan parameter utama dari antarmuka jaringan tertentu.

Fungsi DecodeDomainSearchListData memenuhi dalam dua lintasan. Pada pass pertama, ia melakukan semua tindakan kecuali menulis ke buffer output. Dengan demikian, pass pertama dikhususkan untuk menghitung ukuran memori yang diperlukan untuk mengakomodasi data yang dikembalikan. Pada lintasan kedua, memori sudah dialokasikan untuk data ini dan memori yang dialokasikan diisi. Fungsinya agak kecil, sekitar 250 instruksi, dan tugas utamanya adalah memproses masing-masing dari tiga opsi yang mungkin untuk karakter yang diwakili dalam aliran input: 1) 0x00, 2) 0xc0, atau 3) semua nilai lainnya. Perbaikan hipotetis untuk kesalahan yang berhubungan dengan DHCP pada dasarnya turun ke menambahkan cek pada ukuran buffer yang dihasilkan pada awal pass kedua. Jika ukuran ini nol, maka memori tidak dialokasikan untuk buffer dan fungsi segera mengakhiri eksekusi dan mengembalikan kesalahan:

Ternyata kerentanan memanifestasikan dirinya dalam kasus di mana ukuran buffer target adalah nol. Pada saat yang sama, pada awal eksekusi, fungsi memeriksa data input, yang ukurannya tidak boleh kurang dari dua byte. Oleh karena itu, untuk pengoperasian, diperlukan untuk memilih opsi sufiks domain yang tidak kosong sedemikian rupa sehingga ukuran buffer output adalah nol.
Operasi
Hal pertama yang terlintas dalam pikiran adalah bahwa Anda dapat menggunakan titik reparasi yang dijelaskan sebelumnya sehingga data input non-kosong menghasilkan jalur output kosong:

Server yang dikonfigurasikan untuk mengirim opsi dengan konten seperti itu dalam respons sebenarnya akan menyebabkan pelanggaran akses pada klien yang tidak diperbarui. Ini terjadi karena alasan berikut. Pada setiap langkah, ketika fungsi mem-parsing bagian dari nama domain yang memenuhi syarat, itu menyalinnya ke buffer target dan meletakkan titik setelahnya. Dalam contoh yang diambil dari RFC, data akan disalin ke buffer dalam urutan berikut:
1). eng. 2). eng.apple. 3). eng.apple.com.
Kemudian, ketika domain berisi ukuran domain nol, fungsi tersebut menggantikan karakter buffer tujuan sebelumnya dengan koma:
4). eng.apple.com,
dan melanjutkan penguraian:
5). eng.apple.com,marketing. 6). eng.apple.com,marketing.apple. 7). eng.apple.com,marketing.apple.com. 8). eng.apple.com,marketing.apple.com,
Di akhir input, tetap hanya untuk mengganti koma terakhir dengan karakter nol dan Anda mendapatkan baris yang siap untuk ditulis ke registri:
9). eng.apple.com,marketing.apple.com
Apa yang terjadi ketika seorang penyerang mengirimkan buffer yang terbentuk dengan cara yang dijelaskan? Jika Anda melihat contoh, Anda dapat melihat bahwa daftar yang terkandung di dalamnya terdiri dari satu elemen - string kosong. Pada lintasan pertama, fungsi menghitung ukuran data keluaran. Karena data tidak mengandung satu nama domain bukan nol, ukurannya nol.
Pada lintasan kedua, blok memori dinamis dialokasikan untuk menempatkan data di dalamnya dan menyalin data itu sendiri. Tetapi fungsi parsing segera menemukan karakter nol, menandakan akhir nama domain, dan karena itu, seperti yang dikatakan, menggantikan karakter sebelumnya dari titik ke koma. Dan di sini kita dihadapkan dengan masalah. Iterator buffer target berada di posisi nol. Tidak ada karakter sebelumnya. Karakter sebelumnya milik header blok memori dinamis. Dan karakter yang sama ini akan diganti dengan 0x2c, yaitu dengan koma.
Namun, ini hanya terjadi pada sistem 32-bit. Menggunakan unsigned int untuk menyimpan posisi iterator buffer target saat ini memperkenalkan penyesuaian pada pemrosesan pada sistem x64. Mari kita memperhatikan potongan kode yang bertanggung jawab untuk menulis koma ke buffer:

Unit dikurangi dari posisi saat ini menggunakan register eax 32-bit, sementara ketika menangani buffer, kode mengakses register rax 64-bit penuh. Dalam arsitektur AMD64, operasi apa pun dengan register 32-bit membatalkan bagian atas register. Ini berarti bahwa dalam register rax, yang sebelumnya berisi nol, setelah dikurangi, bukan nilai –1, tetapi 0xffffffff akan disimpan. Oleh karena itu, pada sistem 64-bit, nilai 0x2c akan ditulis ke address buf [0xffffffff], yaitu, jauh melampaui batas memori yang dialokasikan untuk buffer.
Data yang diperoleh dalam perjanjian yang baik dengan penilaian kinerja Microsoft, karena untuk mengeksploitasi kerentanan ini, penyerang perlu belajar bagaimana melakukan penyemprotan tumpukan pada klien DHCP dan pada saat yang sama memiliki kontrol yang cukup atas alokasi memori dinamis untuk mencatat nilai yang telah ditentukan, yaitu koma. dan nol byte, diproduksi di alamat yang disiapkan dan menyebabkan konsekuensi negatif yang terkendali. Jika tidak, menulis data ke alamat yang tidak terverifikasi akan menyebabkan penurunan dalam proses svchost.exe, bersama dengan semua layanan yang saat ini di-host di dalamnya, dan restart lebih lanjut dari layanan ini oleh sistem operasi. Fakta bahwa penyerang dalam kondisi tertentu juga dapat menggunakan untuk keuntungan mereka sendiri.
Tampaknya hanya itulah yang bisa dikatakan tentang kesalahan yang sedang diselidiki. Hanya perasaan yang tersisa bahwa ini masih jauh dari akhir. Seolah kami tidak mempertimbangkan semua opsi. Pasti ada sesuatu yang lebih tersembunyi di baris ini.
CVE-2019-0726
Mungkin memang seperti itu. Jika Anda melihat dengan cermat pada tipe data yang menyebabkan kesalahan dan membandingkannya dengan bagaimana tepatnya kesalahan ini terjadi, Anda akan melihat bahwa daftar nama domain dapat diubah sedemikian rupa sehingga buffer yang dihasilkan adalah ukuran bukan nol, tetapi upaya untuk menulis di luarnya adalah hal yang sama akan dilakukan. Untuk melakukan ini, elemen pertama dalam daftar harus berupa string kosong, dan semua yang lain dapat berisi ujung domain normal. Sebagai contoh:

Opsi yang disajikan mencakup dua elemen. Akhiran domain pertama kosong, langsung berakhir dengan byte nol. Akhiran kedua adalah .ru. Ukuran garis terhitung pada output akan sama dengan tiga byte, yang akan memungkinkan untuk mengatasi cek yang diberlakukan oleh pembaruan Januari pada kekosongan buffer target. Pada saat yang sama, nol di bagian paling awal data akan memaksa fungsi untuk menulis koma dengan karakter sebelumnya dalam string yang dihasilkan, tetapi karena posisi iterator saat ini dalam string adalah nol, seperti dalam kasus yang dipertimbangkan di atas, rekaman akan kembali terjadi di luar buffer yang dialokasikan.
Sekarang perlu untuk mengkonfirmasi hasil teoritis yang diperoleh dalam praktek. Kami mensimulasikan situasi di mana server DHCP mengirim pesan dengan opsi yang disajikan sebagai tanggapan atas permintaan dari klien, dan segera menangkap pengecualian ketika mencoba menulis koma ke posisi 0xffffffff yang dialokasikan di bawah garis buffer yang dihasilkan:

Di sini, register r8 berisi pointer ke opsi yang masuk, rdi adalah alamat buffer target yang dipilih, dan rax adalah posisi dalam buffer ini di mana karakter harus ditulis. Kami mendapat hasil seperti itu pada sistem yang sepenuhnya diperbarui (per Januari 2019).
Kami menulis tentang masalah yang ditemukan di Microsoft dan ... mereka kehilangan surat itu. Ya, ini kadang terjadi bahkan dengan vendor terkemuka. Tidak ada sistem yang sempurna, dan dalam hal ini Anda harus mencari cara komunikasi lain. Oleh karena itu, seminggu kemudian, bahkan tanpa menerima tanggapan otomatis selama waktu ini, kami menghubungi manajer secara langsung melalui Twitter dan berdasarkan hasil beberapa hari menganalisis aplikasi, kami menemukan bahwa detail yang dikirim tidak ada hubungannya dengan CVE-2019-0547 dan merupakan kerentanan independen yang karenanya pengidentifikasi CVE baru. Sebulan kemudian, pada bulan Maret, koreksi yang sesuai keluar, dan kesalahan menerima nomor
CVE-2019-0726 .
Inilah cara Anda kadang-kadang mencoba mencari tahu detail kerentanan 1 hari untuk menemukan 0 hari tanpa sengaja hanya dengan memercayai intuisi Anda.
Diposting oleh Mikhail Tsvetkov, Spesialis Analisis Aplikasi Teknologi Positif.