Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Untuk diskusi umum tentang menulis driver yang aman, lihat Membuat Driver Andal Kernel-Mode.
Selain mengikuti praktik pengkodean yang aman dan panduan driver perangkat umum, driver jaringan harus melakukan hal berikut untuk meningkatkan keamanan:
- Semua driver jaringan harus memvalidasi nilai yang dibaca dari registri. Secara khusus, pemanggil NdisReadConfiguration atau NdisReadNetworkAddress tidak boleh membuat asumsi tentang nilai yang dibaca dari registri dan harus memvalidasi setiap nilai registri yang dibacanya. Jika pemanggil NdisReadConfiguration menentukan bahwa nilai berada di luar batas, nilai tersebut harus menggunakan nilai default sebagai gantinya. Jika pemanggil NdisReadNetworkAddress menentukan bahwa nilai berada di luar batas, itu harus menggunakan alamat kontrol akses menengah (MAC) permanen atau alamat default sebagai gantinya.
Masalah khusus OID
Driver miniport, dalam fungsi MiniportOidRequest atau MiniportCoOidRequest, harus memvalidasi apa pun nilai pengidentifikasi objek (OID) yang diminta untuk ditetapkan oleh driver. Jika driver menentukan bahwa nilai yang akan ditetapkan berada di luar batas, harus menggagalkan permintaan pengaturan tersebut. Untuk informasi selengkapnya tentang pengidentifikasi objek, lihat Mendapatkan dan Mengatur Informasi Driver Miniport dan Dukungan NDIS untuk WMI.
Jika fungsi MiniportOidRequest driver perantara tidak meneruskan operasi yang ditetapkan ke driver miniport yang mendasar, fungsi harus memvalidasi nilai OID. Untuk informasi selengkapnya, lihat Kueri Driver Menengah dan Atur Operasi.
Pedoman Keamanan untuk Kueri OID
Sebagian besar OID Kueri dapat dikeluarkan oleh aplikasi usermode apa pun pada sistem. Ikuti panduan khusus berikut untuk Kueri OID.
Selalu validasi ukuran buffer yang cukup besar untuk output. Setiap handler OID kueri yang tidak memiliki pemeriksaan ukuran buffer output memiliki bug keamanan.
if (oid->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG)) { oid->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG); return NDIS_STATUS_INVALID_LENGTH; }Selalu tulis nilai yang benar dan minimal ke BytesWritten. Ini adalah tanda bahaya untuk menugaskan
oid->BytesWritten = oid->InformationBufferLengthseperti yang dilakukan contoh berikut.// ALWAYS WRONG oid->DATA.QUERY_INFORMATION.BytesWritten = DATA.QUERY_INFORMATION.InformationBufferLength;OS akan menyalin byte BytesWritten kembali ke aplikasi usermode. Jika BytesWritten lebih besar dari jumlah byte yang benar-benar ditulis driver, maka OS mungkin akhirnya menyalin kembali memori kernel yang tidak diinisialisasi ke usermode, yang akan menjadi kerentanan pengungkapan informasi. Sebagai gantinya, gunakan kode yang mirip dengan ini:
oid->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG);Jangan pernah membaca kembali nilai dari buffer. Dalam beberapa kasus, buffer output OID langsung dipetakan ke dalam proses mode pengguna yang berbahaya. Proses jahat dapat mengubah buffer output Anda setelah Anda menulis ke buffer tersebut. Misalnya, kode di bawah ini dapat diserang, karena penyerang dapat mengubah NumElements setelah ditulis:
output->NumElements = 4; for (i = 0 ; i < output->NumElements ; i++) { output->Element[i] = . . .; }Untuk menghindari pembacaan kembali dari buffer, simpan salinan lokal. Misalnya, untuk memperbaiki contoh di atas, perkenalkan variabel tumpukan baru:
ULONG num = 4; output->NumElements = num; for (i = 0 ; i < num; i++) { output->Element[i] = . . .; }Dengan pendekatan ini, for loop membaca ulang dari variabel
numtumpukan driver dan tidak dari buffer keluarannya. Driver juga harus menandai buffer output denganvolatilekata kunci, untuk mencegah pengkompilasi membatalkan perbaikan ini secara diam-diam.
Menetapkan pedoman keamanan OID
Sebagian besar OID Set dapat dikeluarkan oleh aplikasi usermode yang berjalan di Administrator atau Grup keamanan sistem. Meskipun ini umumnya adalah aplikasi tepercaya, driver miniport masih tidak boleh mengizinkan kerusakan memori atau injeksi kode kernel. Ikuti aturan khusus ini untuk Mengatur OID:
Selalu pastikan input cukup besar. Setiap handler set OID tanpa pemeriksaan ukuran buffer input memiliki kerentanan keamanan.
if (oid->DATA.SET_INFORMATION.InformationBufferLength < sizeof(ULONG)) { return NDIS_STATUS_INVALID_LENGTH; }Setiap kali memvalidasi OID dengan offset yang disematkan, Anda harus memvalidasi bahwa buffer yang disematkan berada dalam payload OID. Ini membutuhkan beberapa pemeriksaan. Misalnya, OID_PM_ADD_WOL_PATTERN dapat memberikan pola yang disematkan, yang perlu diperiksa. Validasi yang benar memerlukan pemeriksaan:
InformationBufferSize >= sizeof(NDIS_PM_PACKET_PATTERN)
PmPattern = (PNDIS_PM_PACKET_PATTERN) InformationBuffer; if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN)) { Status = NDIS_STATUS_BUFFER_TOO_SHORT; *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN); break; }Pattern->PatternOffset + Pattern->PatternSize tidak melampaui batas
ULONG TotalSize = 0; if (!NT_SUCCESS(RtlUlongAdd(Pattern->PatternOffset, Pattern->PatternSize, &TotalSize) || TotalSize > InformationBufferLength) { return NDIS_STATUS_INVALID_LENGTH; }Kedua pemeriksaan ini dapat digabungkan menggunakan kode seperti contoh berikut:
ULONG TotalSize = 0; if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN) || !NT_SUCCESS(RtlUlongAdd(Pattern->PatternSize, Pattern->PatternOffset, &TotalSize) || TotalSize > InformationBufferLength) { return NDIS_STATUS_INVALID_LENGTH; }InformationBuffer + Pattern>-PatternOffset + Pattern>-PatternLength tidak meluap
ULONG TotalSize = 0; if (!NT_SUCCESS(RtlUlongAdd(Pattern->PatternOffset, Pattern->PatternLength, &TotalSize) || (!NT_SUCCESS(RtlUlongAdd(TotalSize, InformationBuffer, &TotalSize) || TotalSize > InformationBufferLength) { return NDIS_STATUS_INVALID_LENGTH; }Pattern->PatternOffset + Pattern->PatternLength< = InformationBufferSize
ULONG TotalSize = 0; if(!NT_SUCCESS(RtlUlongAdd(Pattern->PatternOffset, Pattern->PatternLength, &TotalSize) || TotalSize > InformationBufferLength)) { return NDIS_STATUS_INVALID_LENGTH; }
Panduan keamanan metode OID
OID metode dapat dikeluarkan oleh aplikasi moda pengguna yang berjalan di kelompok Administrator atau kelompok keamanan sistem. Mereka adalah kombinasi dari Set dan Kueri, maka kedua daftar panduan yang disebutkan sebelumnya juga berlaku untuk Metode OID.
Masalah keamanan driver jaringan lainnya
Banyak driver miniport NDIS mengekspos perangkat kontrol dengan menggunakan NdisRegisterDeviceEx. Mereka yang melakukan ini harus mengaudit handler IOCTL mereka, dengan semua aturan keamanan yang sama dengan driver WDM. Untuk informasi selengkapnya, lihat Masalah Keamanan untuk Kode Kontrol I/O.
Driver miniport NDIS yang dirancang dengan baik tidak boleh tergantung pada pemanggilan dalam konteks proses tertentu, atau berinteraksi terlalu dekat dengan mode pengguna (dengan IOCTL dan OID yang menjadi pengecualian). Ini akan menjadi tanda peringatan untuk melihat miniport yang membuka handle mode pengguna, menunggu di mode pengguna, atau mengalokasikan memori terhadap kuota mode pengguna. Kode itu harus diselidiki.
Sebagian besar driver miniport NDIS seharusnya tidak terlibat dalam memilah payload paket. Namun, dalam beberapa kasus, mungkin perlu. Jika demikian, kode ini harus diaudit dengan sangat hati-hati, karena driver mengurai data dari sumber yang tidak tepercaya.
Seperti standar saat mengalokasikan memori mode kernel, driver NDIS harus menggunakan mekanisme NX Pool Opt-In yang sesuai. Di WDK 8 dan yang lebih baru, keluarga fungsi
NdisAllocate*diaktifkan dengan benar.