Megosztás a következőn keresztül:


Ügyfél megszemélyesítése

Amikor egy felhasználói alkalmazás WMI-szolgáltatón keresztül kér adatokat a rendszer objektumaitól, a megszemélyesítés azt jelenti, hogy a szolgáltató a szolgáltató helyett az ügyfél biztonsági szintjét képviselő hitelesítő adatokat jelenít meg. A megszemélyesítés megakadályozza, hogy az ügyfél jogosulatlan hozzáférést kapjon a rendszer információihoz.

A következő szakaszokat tárgyaljuk ebben a témakörben:

A WMI általában magas biztonsági szintű rendszergazdai szolgáltatásként fut a LocalServer biztonsági környezet használatával. A rendszergazdai szolgáltatás használata lehetővé teszi a WMI számára a jogosultsági adatok elérését. Amikor egy szolgáltatót információkért hív meg, a WMI átadja a biztonsági azonosítóját (SID) a szolgáltatónak, lehetővé téve, hogy a szolgáltató azonos magas biztonsági szinten férhessen hozzá az információkhoz.

A WMI-alkalmazás indítása során a Windows operációs rendszer megadja a WMI-alkalmazásnak a folyamatot kezdő felhasználó biztonsági környezetét. A felhasználó biztonsági környezete általában alacsonyabb biztonsági szint, mint a LocalServer, ezért előfordulhat, hogy a felhasználó nem rendelkezik engedéllyel a WMI számára elérhető összes információ eléréséhez. Amikor a felhasználói alkalmazás dinamikus információkat kér, a WMI átadja a felhasználó SID-ét a megfelelő szolgáltatónak. Ha megfelelően meg van írva, a szolgáltató a szolgáltató SID-je helyett a felhasználói SID-vel próbál hozzáférni az adatokhoz.

Ahhoz, hogy a szolgáltató sikeresen megszemélyesítse az ügyfélalkalmazást, az ügyfélalkalmazásnak és a szolgáltatónak meg kell felelnie a következő feltételeknek:

Szolgáltató regisztrálása megszemélyesítésre

A WMI csak az ügyfélalkalmazás SID-címét továbbítja a megszemélyesítési szolgáltatóként regisztrált szolgáltatóknak. Ahhoz, hogy egy szolgáltató megszemélyesítést hajtson végre, módosítania kell a szolgáltató regisztrációs folyamatát.

Az alábbi eljárás bemutatja, hogyan regisztrálhat szolgáltatót megszemélyesítésre. Az eljárás feltételezi, hogy már ismeri a regisztrációs folyamatot. További információ a regisztrációs folyamatról: Egy szolgáltató regisztrációja.

Megszemélyesítéshez szolgáltató regisztrálása

  1. Állítsa be a Megszemélyesítési szint tulajdonságát a __Win32Provider osztályban, amely a szolgáltatóját jelöli, 1 értékre.

    A Megszemélyesítési szint tulajdonság dokumentálja, hogy a szolgáltató támogatja-e a megszemélyesítést. A Megszemélyesítési szint 0 értékre állítása azt jelzi, hogy a szolgáltató nem személyesíti meg az ügyfelet, és az összes kért műveletet ugyanabban a felhasználói környezetben hajtja végre, mint a WMI. A Megszemélyesítési szint 1 értékre állítása azt jelzi, hogy a szolgáltató megszemélyesítési hívásokkal ellenőrzi az ügyfél nevében végrehajtott műveleteket.

  2. Állítsa be a PerUserInitialization tulajdonságot ugyanannak a __Win32Provider osztálynak TRUEértékre.

Jegyzet

Ha egy szolgáltatót a __Win32Provider tulajdonsággal regisztrál, a InitializeAsAdminFirst értékét TRUEállítva, akkor a szolgáltató csak az inicializálási fázisban használja az adminisztrációs szintű szálbiztonsági jogkivonatot. Bár a CoImpersonateClient hívása nem hiúsul meg, a szolgáltató a WMI biztonsági környezetét használja, nem pedig az ügyfélét.

 

Az alábbi példakód bemutatja, hogyan regisztrálhat szolgáltatót a megszemélyesítéshez.

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

Megszemélyesítési szintek beállítása egy szolgáltatón belül

Ha egy szolgáltatót regisztrál az __Win32Provider osztály tulajdonsággal, ahol a Megszemélyesítési szint 1-re van állítva, akkor a WMI meghívja a szolgáltatót, hogy különböző ügyfeleket megszemélyesítsen. A hívások kezeléséhez használja a CoImpersonateClient és CoRevertToSelf COM-függvényeket az IWbemServices felület megvalósításában.

A CoImpersonateClient függvény lehetővé teszi, hogy a kiszolgáló megszemélyesítse a hívást kezdeményező ügyfelet. Ha meghívja CoImpersonateClient a IWbemServicesimplementációjába, lehetővé teszi a szolgáltató számára, hogy a szolgáltató száljogkivonatát az ügyfél száljogkivonatának megfelelően állítsa be, és így megszemélyesítse az ügyfelet. Ha nem hívja meg CoImpersonateClient, a szolgáltató rendszergazdai szinten hajtja végre a kódot, ami potenciális biztonsági rést okoz. Ha a szolgáltatónak ideiglenesen rendszergazdaként kell működnie, vagy manuálisan kell elvégeznie a hozzáférés-ellenőrzést, hívja meg CoRevertToSelf.

Ellentétben CoImpersonateClientfunkcióval, CoRevertToSelf egy olyan COM függvény, amely a szálak megszemélyesítési szintjeit kezeli. Ebben az esetben CoRevertToSelf visszaállítja a megszemélyesítési szintet az eredeti megszemélyesítési beállításra. Általában a szolgáltató kezdetben rendszergazda, és a CoImpersonateClient és a CoRevertToSelf között váltakozik attól függően, hogy a hívót vagy a saját hívásait képviselő hívást kezdeményez. A szolgáltató felelőssége, hogy ezeket a hívásokat helyesen helyezze el, hogy ne tegye elérhetővé a végfelhasználó számára a biztonsági rést. A szolgáltatónak például csak natív Windows-függvényeket kell meghívnia a megszemélyesített kódütemezésen belül.

Jegyzet

A CoImpersonateClient és CoRevertToSelf célja a szolgáltató biztonságának beállítása. Ha megállapítja, hogy a megszemélyesítés sikertelen volt, megfelelő befejezési kódot kell visszaadnia a WMI-nek a következőn keresztül: IWbemObjectSink::SetStatus. További információért lásd: Hozzáférés megtagadva üzenetek kezelése a szolgáltatónál.

 

Biztonsági szintek fenntartása egy szolgáltatóban

A szolgáltatók nem hívhatják meg a CoImpersonateClient függvényt egyszer a IWbemServices implementáció során, és nem feltételezhetik, hogy a megszemélyesítési hitelesítő adatok érvényben maradnak a szolgáltató teljes működése alatt. Ehelyett egy implementáció során többször hívja meg CoImpersonateClient, hogy a WMI ne módosítsa a hitelesítő adatokat.

A szolgáltató megszemélyesítésének beállításával kapcsolatos fő szempont az újra beléphetőség. Ebben az összefüggésben a reentrancia az, amikor egy szolgáltató meghívja a WMI-t információkért, és megvárja, amíg a WMI visszahívja a szolgáltatót. Lényegében a végrehajtás szála elhagyja a szolgáltató kódját, hogy később visszatérjen oda. Az újrapróbálkozás a COM kialakításának része, és általában nem jelent problémát. Amikor azonban a végrehajtási szál a WMI-be kerül, a szál felveszi a WMI megszemélyesítési szintjeit. Amikor a szál visszatér a szolgáltatóhoz, szükséges a megszemélyesítési szinteket visszaállítani egy másik CoImpersonateClienthívással.

Ha meg szeretné védeni magát a szolgáltató biztonsági réseitől, csak az ügyfél megszemélyesítése közben kell újrahívásokat kezdeményeznie a WMI-be. Vagyis a CoImpersonateClient hívása után és CoRevertToSelfhívása előtt kell hívni a WMI-t. Mivel a CoRevertToSelf a megszemélyesítést arra a felhasználói szintre állítja be, amelyen a WMI fut, ami általában a LocalSystem, az ismétlődő WMI-hívások a CoRevertToSelf meghívása után sokkal több képességet biztosíthatnak a felhasználónak és a hívott szolgáltatóknak, mint amennyit kellene.

Jegyzet

Ha rendszerfüggvényt vagy más interfészmetódust hív meg, a hívási környezet nem garantáltan megmarad.

 

Hozzáférés-megtagadott üzenetek kezelése egy szolgáltatóban

A hozzáférés megtagadva hibaüzenetek többsége akkor jelenik meg, ha egy ügyfél olyan osztályt vagy információt kér, amelyhez nincs hozzáférése. Ha a szolgáltató hozzáférést megtagadó hibaüzenetet ad vissza a WMI-nek, és a WMI átadja ezt az ügyfélnek, az ügyfél arra következtethet, hogy az információ létezik. Bizonyos helyzetekben ez a biztonság megsértését okozhatja. Ezért a szolgáltató nem propagálja az üzenetet az ügyfélnek. Ehelyett a szolgáltató által megadott osztályok nem lesznek közzétéve. Hasonlóképpen, a dinamikus példányszolgáltatónak meg kell hívnia a mögöttes adatforrást annak megállapításához, hogyan kell kezelni a hozzáférés-megtagadott üzeneteket. A szolgáltató feladata, hogy replikálja ezt a filozófiát a WMI-környezetbe. További információ: Részleges példányok jelentése és Részleges enumerációk jelentése.

Ha megállapítja, hogy a szolgáltató hogyan kezelje a hozzáférés-megtagadott üzeneteket, meg kell írnia és hibakeresést kell végeznie a kódban. A hibakeresés során gyakran célszerű különbséget tenni az alacsony megszemélyesítés miatti megtagadás és a kód hibája miatti megtagadás között. A különbség meghatározásához használhat egy egyszerű tesztet a kódban. További információ: Hozzáférés-megtagadott kód hibakeresése.

Részleges példányok jelentése

A hozzáférés megtagadására vonatkozó üzenet egyik gyakori oka, hogy a WMI nem tudja megadni az összes szükséges információt a példány kitöltéséhez. Előfordulhat például, hogy az ügyfél rendelkezik a merevlemez-objektum megtekintésére vonatkozó jogosultsággal, de nem biztos, hogy rendelkezik jogosultsággal arra, hogy lássa, mennyi hely áll rendelkezésre magáról a merevlemez-meghajtóról. A szolgáltatónak meg kell határoznia, hogyan kezelje azokat a helyzeteket, amikor a szolgáltató nem tudja egy példányt tulajdonságokkal kitölteni a hozzáférési jog megsértése miatt.

A WMI nem igényel egyetlen választ azoknak az ügyfeleknek, amelyek részleges hozzáféréssel rendelkeznek egy példányhoz. Ehelyett a WMI 1.x-es verziója az alábbi lehetőségek egyikét teszi lehetővé a szolgáltató számára:

  • Sikertelen a teljes művelet a WBEM_E_ACCESS_DENIED hiba miatt, és nem ad vissza példányokat.

    A megtagadás okának leírásához adjon vissza egy hibaobjektumot a WBEM_E_ACCESS_DENIEDegyütt.

  • Adja vissza az összes elérhető tulajdonságot, és töltse ki a nem elérhető tulajdonságokat NULL.

Jegyzet

Győződjön meg arról, hogy a visszaküldött WBEM_E_ACCESS_DENIED nem hoz létre biztonsági rést a vállalatnál.

 

Részleges számbavételek jelentése

A hozzáférés megsértése egy másik gyakori előfordulása, amikor a WMI nem tudja visszaadni az összes enumerálást. Előfordulhat például, hogy egy ügyfélnek hozzáférése van az összes helyi hálózati számítógép-objektum megtekintéséhez, de nem rendelkezik hozzáféréssel a tartományán kívüli számítógép-objektumok megtekintéséhez. A szolgáltatónak meg kell határoznia, hogyan kezelheti azokat a helyzeteket, amikor egy enumerálás nem hajtható végre hozzáférés-megsértés miatt.

A példányszolgáltatóhoz hasonlóan a WMI sem igényel egyetlen választ a részleges számbavételre. Ehelyett a WMI 1.x-es verziója az alábbi lehetőségek egyikét teszi lehetővé a szolgáltató számára:

  • Adja vissza WBEM_S_NO_ERROR minden példány esetében, amelyhez a szolgáltató hozzáférhet.

    Ha ezt a lehetőséget használja, a felhasználó nem tudja, hogy egyes példányok nem voltak elérhetők. Számos szolgáltató, például a sorszintű biztonsággal rendelkező strukturált lekérdezési nyelvet (SQL) használó szolgáltatók sikeres részleges eredményeket adnak vissza a hívó biztonsági szintjének használatával az eredményhalmaz meghatározásához.

  • Szakítsa meg a teljes műveletet WBEM_E_ACCESS_DENIED, és ne adjon vissza példányokat.

    A szolgáltató opcionálisan tartalmazhat egy hibaobjektumot, amely leírja az ügyfél helyzetét. Vegye figyelembe, hogy egyes szolgáltatók sorozatosan férhetnek hozzá az adatforrásokhoz, és előfordulhat, hogy csak az enumerálás során tapasztalnak megtagadásokat.

  • Adja vissza az összes elérhető példányt, de a nem érvénytelen állapotkódot is visszaadja WBEM_S_ACCESS_DENIED.

    A szolgáltatónak fel kell jegyeznie a megtagadás eseményét az enumerálás során, és továbbra is biztosíthatja a példányokat. Végül hibamentes állapotkóddal zárhatja le. A szolgáltató dönthet úgy is, hogy az első megtagadáskor leállítja az enumerálást. Ennek a lehetőségnek az az oka, hogy a különböző szolgáltatók különböző lekérési paradigmával rendelkeznek. Előfordulhat, hogy a szolgáltató már kézbesített példányokat, mielőtt észlelte a hozzáférés megsértését. Egyes szolgáltatók dönthetnek úgy, hogy továbbra is más példányokat biztosítanak, míg mások megszüntethetik azokat.

A COM struktúrája miatt a hibaobjektumok kivételével a rendszer nem tud visszavenni semmilyen információt a hiba során. Ezért nem adhat vissza információt és hibakódot sem. Ha úgy dönt, hogy információt küld vissza, ehelyett egy nem-hibás állapotkódot kell használnia.

Hozzáférés-megtagadott kód hibakeresése

Egyes alkalmazások a RPC_C_IMP_LEVEL_IMPERSONATE-nál alacsonyabb megszemélyesítési szinteket használhatnak. Ebben az esetben az ügyfélalkalmazás szolgáltatója által kezdeményezett legtöbb megszemélyesítési hívás sikertelen lesz. A szolgáltató sikeres tervezéséhez és implementálásához szem előtt kell tartania ezt az ötletet.

Alapértelmezés szerint a szolgáltatóhoz csak a RPC_C_IMP_LEVEL_IDENTIFYmellett más megszemélyesítési szint férhet hozzá. Ha egy ügyfélalkalmazás RPC_C_IMP_LEVEL_IDENTIFYhasznál, CoImpersonateClient nem ad vissza hibakódot. Ehelyett a szolgáltató csak azonosítás céljából megszemélyesíti az ügyfelet. Ezért a szolgáltató által meghívott Windows-metódusok többsége egy hozzáférés-megtagadási üzenetet ad vissza. Ez a gyakorlatban ártalmatlan, mivel a felhasználók nem tehetnek semmi helytelent. A szolgáltató fejlesztése során azonban hasznos lehet tudni, hogy az ügyfél valóban megszemélyesítve volt-e.

A kód helyes fordításához a következő hivatkozásokra és #include utasításokra van szükség.

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

Az alábbi példakód bemutatja, hogyan állapítható meg, hogy egy szolgáltató sikeresen megszemélyesített-e egy ügyfélalkalmazást.

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);

WMI-szolgáltatói fejlesztése

Namepace biztonsági leírók beállítása

szolgáltatói biztonságossá tétele