Bagikan melalui


Meniru Klien

Ketika aplikasi pengguna meminta data dari objek pada sistem melalui penyedia WMI, peniruan berarti penyedia menyajikan kredensial yang mewakili tingkat keamanan klien daripada penyedia. Peniruan identitas mencegah klien mendapatkan akses tidak sah ke informasi pada sistem.

Bagian berikut dibahas dalam topik ini:

WMI biasanya berjalan sebagai layanan administratif pada tingkat keamanan tinggi, menggunakan konteks keamanan LocalServer. Menggunakan layanan administratif memberi WMI sarana untuk mengakses informasi istimewa. Saat memanggil penyedia untuk informasi, WMI meneruskan pengidentifikasi keamanan (SID) ke penyedia, memungkinkan penyedia untuk mengakses informasi pada tingkat keamanan tinggi yang sama.

Selama proses peluncuran aplikasi WMI, sistem operasi Windows memberi aplikasi WMI konteks keamanan pengguna yang memulai proses. Konteks keamanan pengguna biasanya merupakan tingkat keamanan yang lebih rendah daripada LocalServer, sehingga pengguna mungkin tidak memiliki izin untuk mengakses semua informasi yang tersedia untuk WMI. Ketika aplikasi pengguna meminta informasi dinamis, WMI meneruskan SID pengguna ke penyedia yang sesuai. Jika ditulis dengan tepat, penyedia mencoba mengakses informasi dengan SID pengguna, bukan SID penyedia.

Agar penyedia berhasil meniru aplikasi klien, aplikasi klien dan penyedia harus memenuhi kriteria berikut:

Mendaftarkan Penyedia untuk Peniruan Identitas

WMI hanya meneruskan SID aplikasi klien kepada penyedia yang telah terdaftar sebagai penyedia peniruan identitas. Mengaktifkan penyedia untuk melakukan peniruan mengharuskan Anda mengubah proses pendaftaran penyedia.

Prosedur berikut menjelaskan cara mendaftarkan penyedia untuk peniruan identitas. Prosedur ini mengasumsikan bahwa Anda sudah memahami proses pendaftaran. Untuk informasi selengkapnya tentang proses pendaftaran, lihat Mendaftarkan Penyedia.

Untuk mendaftarkan penyedia untuk peniruan identitas

  1. Atur properti ImpersonationLevel dari kelas __Win32Provider yang mewakili penyedia Anda ke 1.

    Dokumen properti ImpersonationLevel apakah penyedia mendukung peniruan identitas atau tidak. Mengatur ImpersonationLevel ke 0 menunjukkan bahwa penyedia tidak meniru klien dan melakukan semua operasi yang diminta dalam konteks pengguna yang sama dengan WMI. Mengatur ImpersonationLevel ke 1 menunjukkan bahwa penyedia menggunakan panggilan peniruan identitas untuk memeriksa operasi yang dilakukan atas nama klien.

  2. Atur properti PerUserInitialization dari kelas __Win32Provider yang sama ke TRUE.

Catatan

Jika Anda mendaftarkan penyedia dengan properti __Win32ProviderInitializeAsAdminFirst diatur ke TRUE, maka penyedia menggunakan token keamanan utas tingkat administrasi hanya selama fase inisialisasi. Meskipun panggilan ke CoImpersonateClient tidak gagal, penyedia menggunakan konteks keamanan WMI dan bukan klien.

 

Contoh kode berikut menunjukkan cara mendaftarkan penyedia untuk peniruan identitas.

instance of __Win32Provider
{
    CLSID = "{FD4F53E0-65DC-11d1-AB64-00C04FD9159E}";
    ImpersonationLevel = 1;
    Name = "MS_NT_EVENTLOG_PROVIDER";
    PerUserInitialization = TRUE;
};

Mengatur Tingkat Peniruan Dalam Penyedia

Jika Anda mendaftarkan penyedia dengan properti kelas __Win32ProviderImpersonationLevel diatur ke 1, maka WMI memanggil penyedia Anda untuk meniru berbagai klien. Untuk menangani panggilan ini, gunakan fungsi CoImpersonateClient dan CoRevertToSelf COM dalam implementasi antarmuka IWbemServices Anda.

Fungsi CoImpersonateClient memungkinkan server untuk meniru klien yang melakukan panggilan. Dengan melakukan panggilan ke CoImpersonateClient ke dalam implementasi IWbemServices Anda, Anda mengizinkan penyedia untuk mengatur token utas penyedia agar sesuai dengan token utas klien, dan dengan demikian meniru klien. Jika Anda tidak memanggil CoImpersonateClient, penyedia Anda menjalankan kode pada tingkat keamanan administrator, sehingga menciptakan potensi kerentanan keamanan. Jika penyedia Anda untuk sementara waktu perlu bertindak sebagai administrator atau melakukan pemeriksaan akses secara manual, hubungi CoRevertToSelf.

Berbeda dengan CoImpersonateClient, CoRevertToSelf adalah fungsi COM yang menangani tingkat peniruan utas. Dalam hal ini, CoRevertToSelf mengubah tingkat peniruan kembali ke pengaturan peniruan asli. Secara umum, penyedia awalnya adalah administrator dan bergantian antara CoImpersonateClient dan CoRevertToSelf tergantung pada apakah itu melakukan panggilan yang mewakili pemanggil atau panggilannya sendiri. Penyedia bertanggung jawab untuk melakukan panggilan ini dengan benar agar tidak mengekspos lubang keamanan kepada pengguna akhir. Misalnya, penyedia hanya boleh memanggil fungsi Windows asli dalam urutan kode yang ditiru.

Catatan

Tujuan dari CoImpersonateClient dan CoRevertToSelf adalah untuk mengatur keamanan bagi penyedia. Jika Anda menentukan bahwa peniruan Anda telah gagal, Anda harus mengembalikan kode penyelesaian yang sesuai ke WMI melalui IWbemObjectSink::SetStatus. Untuk informasi selengkapnya, lihat Menangani Pesan Akses Ditolak di Penyedia.

 

Mempertahankan Tingkat Keamanan di Penyedia

Penyedia tidak dapat memanggil CoImpersonateClient satu kali dalam implementasi IWbemServices dan mengasumsikan bahwa kredensial peniruan tetap diberlakukan selama durasi penyedia. Sebagai gantinya, panggil CoImpersonateClient beberapa kali selama implementasi untuk mencegah WMI mengubah kredensial.

Kekhawatiran utama untuk menetapkan peniruan identitas untuk penyedia adalah reentrancy. Dalam konteks ini, reentrancy adalah ketika penyedia melakukan panggilan ke WMI untuk informasi dan menunggu sampai WMI memanggil kembali ke penyedia. Intinya, utas eksekusi meninggalkan kode penyedia, hanya untuk memasukkan kembali kode di kemudian hari. Masuk kembali adalah bagian dari desain COM, dan umumnya tidak menjadi perhatian. Namun, ketika utas eksekusi memasuki WMI, utas mengambil tingkat peniruan WMI. Saat utas kembali ke penyedia, Anda harus mengatur ulang tingkat peniruan dengan panggilan lain ke CoImpersonateClient.

Untuk melindungi diri Anda dari lubang keamanan di penyedia Anda, Anda harus melakukan panggilan masuk kembali ke WMI hanya saat meniru klien. Artinya, panggilan ke WMI harus dilakukan setelah Anda memanggil CoImpersonateClient dan sebelum Anda memanggil CoRevertToSelf. Karena CoRevertToSelf menyebabkan peniruan identitas diatur ke tingkat pengguna WMI berjalan, umumnya LocalSystem, panggilan masuk kembali ke WMI setelah memanggil CoRevertToSelf dapat memberi pengguna, dan penyedia apa pun yang dipanggil, lebih banyak kemampuan daripada yang seharusnya mereka miliki.

Catatan

Jika Anda memanggil fungsi sistem atau metode antarmuka lain, konteks panggilan tidak dijamin akan dipertahankan.

 

Menangani Pesan Akses Ditolak di Penyedia

Sebagian besar pesan kesalahan Akses Ditolak muncul ketika klien meminta kelas atau informasi yang tidak mereka miliki aksesnya. Jika penyedia mengembalikan pesan kesalahan Akses Ditolak ke WMI dan WMI meneruskan ini ke klien, klien dapat menyimpulkan bahwa informasi tersebut ada. Dalam beberapa situasi, ini bisa menjadi pelanggaran keamanan. Oleh karena itu, penyedia Anda tidak boleh menyebarluaskan pesan ke klien. Sebaliknya, set kelas yang akan disediakan penyedia tidak boleh diekspos. Demikian pula, penyedia instans dinamis harus memanggil ke sumber data yang mendasar untuk menentukan cara menangani pesan Akses Ditolak. Penyedia bertanggung jawab untuk mereplikasi filosofi tersebut ke lingkungan WMI. Untuk informasi selengkapnya, lihat Melaporkan Instans Parsial dan Melaporkan Enumerasi Parsial.

Ketika Anda menentukan bagaimana penyedia Anda harus menangani pesan Akses Ditolak, Anda harus menulis dan men-debug kode Anda. Saat penelusuran kesalahan, seringkali lebih mudah untuk membedakan antara penolakan karena peniruan yang rendah, dan penolakan karena kesalahan dalam kode Anda. Anda dapat menggunakan pengujian sederhana dalam kode Anda untuk menentukan perbedaannya. Untuk informasi selengkapnya, lihat Men-debug Kode Akses Ditolak.

Melaporkan Instans Parsial

Salah satu kemunculan umum pesan Akses Ditolak adalah ketika WMI tidak dapat memberikan semua informasi untuk mengisi instans. Misalnya, klien mungkin memiliki otoritas untuk melihat objek hard disk drive, tetapi mungkin tidak memiliki otoritas untuk melihat berapa banyak ruang yang tersedia pada hard disk drive itu sendiri. Penyedia Anda harus menentukan cara menangani situasi apa pun ketika penyedia tidak dapat sepenuhnya mengisi instans dengan properti karena pelanggaran akses.

WMI tidak memerlukan satu respons terhadap klien yang memiliki akses parsial ke instans. Sebagai gantinya, WMI versi 1.x memungkinkan penyedia salah satu opsi berikut:

  • Gagalkan seluruh operasi dengan WBEM_E_ACCESS_DENIED dan tidak mengembalikan instans.

    Kembalikan objek kesalahan bersama dengan WBEM_E_ACCESS_DENIED, untuk menjelaskan alasan penolakan.

  • Mengembalikan semua properti yang tersedia, dan mengisi properti yang tidak tersedia dengan NULL.

Catatan

Pastikan bahwa mengembalikan WBEM_E_ACCESS_DENIED tidak membuat lubang keamanan di perusahaan Anda.

 

Melaporkan Enumerasi Parsial

Kejadian umum lain dari pelanggaran akses adalah ketika WMI tidak dapat mengembalikan semua enumerasi. Misalnya, klien mungkin memiliki akses untuk melihat semua objek komputer jaringan lokal, tetapi mungkin tidak memiliki akses untuk melihat objek komputer di luar domainnya. Penyedia Anda harus menentukan cara menangani situasi apa pun ketika enumerasi tidak dapat diselesaikan karena pelanggaran akses.

Seperti halnya penyedia instans, WMI tidak memerlukan satu respons terhadap enumerasi parsial. Sebagai gantinya, WMI versi 1.x memungkinkan penyedia salah satu opsi berikut:

  • Mengembalikan WBEM_S_NO_ERROR untuk semua instans yang dapat diakses penyedia.

    Jika Anda menggunakan opsi ini, pengguna tidak menyadari bahwa beberapa instans tidak tersedia. Sejumlah penyedia, seperti yang menggunakan Bahasa Permintaan Terstruktur (SQL) dengan keamanan tingkat baris, mengembalikan hasil parsial yang berhasil menggunakan tingkat keamanan pemanggil untuk menentukan tataan hasil.

  • Gagalkan seluruh operasi dengan WBEM_E_ACCESS_DENIED dan tidak mengembalikan instans.

    Penyedia dapat secara opsional menyertakan objek kesalahan yang menjelaskan situasinya kepada klien. Perhatikan bahwa beberapa penyedia dapat mengakses sumber data secara serial dan mungkin tidak mengalami penolakan hingga sebagian melalui enumerasi.

  • Mengembalikan semua instans yang dapat diakses tetapi juga mengembalikan kode status non-kesalahan WBEM_S_ACCESS_DENIED.

    Penyedia harus mencatat penolakan selama enumerasi dan dapat terus menyediakan instans, menyelesaikan dengan kode status non-kesalahan. Penyedia juga dapat memilih untuk mengakhiri enumerasi pada penolakan pertama. Pembenaran untuk opsi ini adalah bahwa penyedia yang berbeda memiliki paradigma pengambilan yang berbeda. Penyedia mungkin telah mengirimkan instans sebelum menemukan pelanggaran akses. Beberapa penyedia dapat memilih untuk terus menyediakan instans lain dan yang lain mungkin ingin mengakhiri.

Karena struktur COM, Anda tidak dapat melakukan marshal kembali informasi apa pun selama kesalahan kecuali untuk objek kesalahan. Oleh karena itu, Anda tidak dapat mengembalikan informasi dan kode kesalahan. Jika Anda memilih untuk mengembalikan informasi, Anda harus menggunakan kode status non-gangguan sebagai gantinya.

Men-debug kode Akses Anda Ditolak

Beberapa aplikasi mungkin menggunakan tingkat peniruan lebih rendah dari RPC_C_IMP_LEVEL_IMPERSONATE. Dalam hal ini, sebagian besar panggilan peniruan yang dilakukan oleh penyedia untuk aplikasi klien akan gagal. Agar berhasil merancang dan mengimplementasikan penyedia, Anda harus mengingat ide ini.

Secara default, satu-satunya tingkat peniruan identitas lain yang dapat mengakses penyedia adalah RPC_C_IMP_LEVEL_IDENTIFY. Dalam kasus di mana aplikasi klien menggunakan RPC_C_IMP_LEVEL_IDENTIFY, CoImpersonateClient tidak mengembalikan kode kesalahan. Sebaliknya, penyedia meniru klien hanya untuk tujuan identifikasi. Oleh karena itu, sebagian besar metode Windows yang dipanggil oleh penyedia akan mengembalikan pesan akses ditolak. Ini tidak berbahaya dalam praktiknya, karena pengguna tidak akan diizinkan untuk melakukan sesuatu yang tidak pantas. Namun, mungkin berguna selama pengembangan penyedia untuk mengetahui apakah klien benar-benar ditiru atau tidak.

Kode memerlukan referensi berikut dan pernyataan #include untuk dikompilasi dengan benar.

#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <wbemidl.h>

Contoh kode berikut menunjukkan cara menentukan apakah penyedia telah berhasil meniru aplikasi klien.

DWORD dwImp = 0;
HANDLE hThreadTok;
DWORD dwBytesReturned;
BOOL bRes;

// You must call this before trying to open a thread token!
CoImpersonateClient();

bRes = OpenThreadToken(
    GetCurrentThread(),
    TOKEN_QUERY,
    TRUE,
    &hThreadTok
);

if (bRes == FALSE)
{
    printf("Unable to read thread token (%d)\n", GetLastError());
    return 0;
}

bRes = GetTokenInformation(
    hThreadTok,
    TokenImpersonationLevel, 
    &dwImp,
    sizeof(DWORD),
    &dwBytesReturned
);

if (!bRes)
{
    printf("Unable to read impersonation level\n");
    CloseHandle(hThreadTok);
    return 0;
}

switch (dwImp)
{
case SecurityAnonymous:
    printf("SecurityAnonymous\n");
    break;

case SecurityIdentification:
    printf("SecurityIdentification\n");
    break;

case SecurityImpersonation:
    printf("SecurityImpersonation\n");
    break;

case SecurityDelegation:
    printf("SecurityDelegation\n");
    break;

default:
    printf("Error. Unable to determine impersonation level\n");
    break;
}

CloseHandle(hThreadTok);

Mengembangkan Penyedia WMI

Mengatur Deskriptor Keamanan Namepace

Mengamankan Penyedia Anda