Freigeben über


Vortäuschung eines Kunden

Wenn eine Benutzeranwendung Daten von Objekten im System über einen WMI-Anbieter anfordert, bedeutet Impersonation, dass der Anbieter Anmeldeinformationen verwendet, die die Sicherheitsstufe des Clients und nicht die des Anbieters repräsentieren. Der Identitätswechsel verhindert, dass ein Client nicht autorisierten Zugriff auf Informationen im System erhält.

Die folgenden Abschnitte werden in diesem Thema behandelt:

WMI wird in der Regel als Administratordienst auf hoher Sicherheitsebene ausgeführt, wobei der LocalServer-Sicherheitskontext verwendet wird. Die Verwendung eines Verwaltungsdiensts ermöglicht WMI den Zugriff auf privilegierte Informationen. Beim Aufrufen eines Anbieters für Informationen übergibt WMI seine Sicherheits-ID (SID) an den Anbieter, sodass der Anbieter auf Informationen auf derselben hohen Sicherheitsstufe zugreifen kann.

Während des Startvorgangs der WMI-Anwendung gibt das Windows-Betriebssystem der WMI-Anwendung den Sicherheitskontext des Benutzers, der den Prozess begonnen hat. Der Sicherheitskontext des Benutzers ist in der Regel eine niedrigere Sicherheitsstufe als LocalServer, sodass der Benutzer möglicherweise nicht über die Berechtigung verfügt, auf alle informationen zuzugreifen, die für WMI verfügbar sind. Wenn die Benutzeranwendung nach dynamischen Informationen fragt, übergibt WMI die SID des Benutzers an den entsprechenden Anbieter. Falls zutreffend geschrieben, versucht der Anbieter, auf Informationen mit der Benutzer-SID und nicht auf die Anbieter-SID zuzugreifen.

Damit der Anbieter die Identität der Clientanwendung erfolgreich imitieren kann, muss die Clientanwendung und der Anbieter die folgenden Kriterien erfüllen:

Registrieren eines Anbieters für Nachahmung

WMI übergibt die SID einer Clientanwendung nur an Anbieter, die sich als Impersonationsanbieter registriert haben. Das Aktivieren eines Anbieters zum Ausführen eines Identitätswechsels erfordert, dass Sie den Registrierungsprozess des Anbieters ändern.

Das folgende Verfahren beschreibt, wie ein Anbieter zur Stellvertretung registriert wird. Bei diesem Verfahren wird davon ausgegangen, dass Sie den Registrierungsprozess bereits verstehen. Weitere Informationen zum Registrierungsprozess finden Sie unter Registrieren eines Anbieters.

So registrieren Sie einen Anbieter für Impersonation

  1. Legen Sie die ImpersonationLevel-Eigenschaft der __Win32Provider-Klasse fest, die Ihren Anbieter auf 1 darstellt.

    Die ImpersonationLevel-Eigenschaft dokumentiert, ob der Anbieter identitätswechsel unterstützt oder nicht. Das Festlegen des Identitätswechsellevels auf 0 gibt an, dass der Anbieter den Client nicht imitiert und alle angeforderten Vorgänge im selben Benutzerkontext wie WMI ausführt. Das Festlegen des Identitätswechsellevels auf 1 gibt an, dass der Anbieter Identitätswechselaufrufe verwendet, um Vorgänge zu überprüfen, die im Auftrag des Clients ausgeführt werden.

  2. Legen Sie die PerUserInitialization-Eigenschaft der gleichen __Win32Provider Klasse auf TRUE fest.

Hinweis

Wenn Sie einen Anbieter mit der Eigenschaft __Win32Provider registrieren und InitializeAsAdminFirst auf TRUE setzen, verwendet der Anbieter das Threadsicherheitstoken auf Verwaltungsebene nur während der Initialisierungsphase. Während ein Aufruf von CoImpersonateClient nicht fehlschlägt, verwendet der Anbieter den Sicherheitskontext von WMI und nicht des Clients.

 

Das folgende Codebeispiel zeigt, wie ein Anbieter für Identitätswechsel registriert wird.

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

Festlegen von Impersonation-Stufen innerhalb eines Providers

Wenn Sie einen Anbieter bei der auf 1 festgelegten __Win32Provider Klasseneigenschaft "ImpersonationLevel " registrieren, ruft WMI Ihren Anbieter auf, um die Identität verschiedener Clients zu imitieren. Verwenden Sie zum Behandeln dieser Aufrufe die CoImpersonateClient - und CoRevertToSelf-COM-Funktionen in Ihrer Implementierung der IWbemServices-Schnittstelle .

Mit der CoImpersonateClient-Funktion kann ein Server den Client annehmen, der den Aufruf ausgeführt hat. Indem Sie einen Aufruf von CoImpersonateClient in Ihre Implementierung von IWbemServices einfügen, können Sie dem Anbieter das Threadtoken des Anbieters so festlegen, dass es dem Threadtoken des Clients entspricht, und somit den Client imitieren. Wenn Sie "CoImpersonateClient" nicht aufrufen, führt Ihr Anbieter Code auf Administratorebene der Sicherheit aus, wodurch ein potenzieller Sicherheitsrisiko entsteht. Wenn Ihr Anbieter vorübergehend als Administrator fungieren oder die Zugriffsüberprüfung manuell durchführen muss, rufen Sie CoRevertToSelf auf.

Im Gegensatz zu CoImpersonateClient ist CoRevertToSelf eine COM-Funktion, die Threadwechselebenen behandelt. In diesem Fall ändert CoRevertToSelf die Identitätswechselebene wieder in die ursprüngliche Identitätswechseleinstellung. Im Allgemeinen ist der Anbieter zunächst ein Administrator und wechselt zwischen CoImpersonateClient und CoRevertToSelf , je nachdem, ob er einen Aufruf vornimmt, der den Anrufer oder seine eigenen Anrufe darstellt. Es liegt in der Verantwortung des Anbieters, diese Aufrufe korrekt zu platzieren, damit dem Endbenutzer kein Sicherheitsloch offen steht. Beispielsweise sollte der Anbieter nur systemeigene Windows-Funktionen innerhalb der imitierten Codesequenz aufrufen.

Hinweis

Der Zweck von CoImpersonateClient und CoRevertToSelf besteht darin, die Sicherheit für einen Anbieter festzulegen. Wenn Sie feststellen, dass der Identitätswechsel fehlgeschlagen ist, sollten Sie einen geeigneten Abschlusscode über IWbemObjectSink::SetStatus an WMI zurückgeben. Weitere Informationen finden Sie unter Behandeln von "Zugriff verweigerten Nachrichten" in einem Anbieter.

 

Verwalten von Sicherheitsstufen in einem Anbieter

Anbieter können CoImpersonateClient nicht einmal in einer Implementierung von IWbemServices aufrufen und davon ausgehen, dass die Identitätswechselanmeldeinformationen für die Dauer des Anbieters vorhanden bleiben. Rufen Sie stattdessen während einer Implementierung mehrmals CoImpersonateClient auf, um zu behalten, dass WMI die Anmeldeinformationen ändert.

Die Hauptbedenken bei der Einrichtung der Identitätswechselung für einen Anbieter sind Reentrancy. In diesem Zusammenhang bezeichnet Reentrancy den Fall, wenn ein Anbieter WMI kontaktiert, um Informationen zu erhalten, und darauf wartet, dass WMI den Anbieter erneut aufruft. Im Wesentlichen verlässt der Ausführungsthread den Anbietercode, nur um zu einem späteren Zeitpunkt erneut in den Code einzutreten. Der Wiedereintritt ist Teil des Entwurfs von COM und ist im Allgemeinen kein Anlass zur Sorge. Wenn jedoch der Ausführungsthread WMI betritt, übernimmt der Thread die Identitätswechselstufen von WMI. Wenn der Thread zum Anbieter zurückkehrt, müssen Sie die Imitationsstufen mit einem weiteren Aufruf von CoImpersonateClient zurücksetzen.

Um sich vor Sicherheitslücken in Ihrem Anbieter zu schützen, sollten Sie nur dann erneut WMI-Aufrufe durchführen, wenn Sie die Identität des Clients übernehmen. Das heißt, Anrufe an WMI sollten nach dem Aufrufen von CoImpersonateClient und vor dem Aufrufen von CoRevertToSelf erfolgen. Da CoRevertToSelf bewirkt, dass der Identitätswechsel auf die Benutzerebene festgelegt wird, auf der WMI im Allgemeinen im LocalSystem-Kontext ausgeführt wird, könnten reentrante Aufrufe an WMI nach dem Aufruf von CoRevertToSelf dem Benutzer und allen aufgerufenen Anbietern wesentlich mehr Fähigkeiten geben, als sie haben sollten.

Hinweis

Wenn Sie eine Systemfunktion oder eine andere Schnittstellenmethode aufrufen, wird der Aufrufkontext nicht garantiert verwaltet.

 

Umgang mit Zugriffsverweigerungs-Fehlermeldungen bei einem Anbieter

Die meisten Fehlermeldungen "Zugriff verweigert" werden angezeigt, wenn ein Client eine Klasse oder Informationen anfordert, auf die er keinen Zugriff hat. Wenn der Anbieter eine Fehlermeldung "Zugriff verweigert" an WMI zurückgibt und WMI dies an den Client weitergibt, kann der Client ableiten, dass die Informationen vorhanden sind. In einigen Fällen kann dies eine Sicherheitsverletzung sein. Daher sollte Ihr Anbieter die Nachricht nicht an den Client weitergeben. Stattdessen sollte die Menge der Klassen, die vom Anbieter bereitgestellt worden wäre, nicht offengelegt werden. Ebenso sollte ein Dynamischer Instanzanbieter die zugrunde liegende Datenquelle aufrufen, um zu bestimmen, wie mit Zugriffsverweigerungsnachrichten umgegangen werden soll. Es liegt in der Verantwortung des Anbieters, diese Philosophie in die WMI-Umgebung zu replizieren. Weitere Informationen finden Sie unter Berichterstattung über teilweise Instanzen und Berichterstattung über teilweise Aufzählungen.

Wenn Sie bestimmen, wie Ihr Anbieter Zugriffsverweigerungsnachrichten behandeln soll, müssen Sie Ihren Code schreiben und debuggen. Beim Debuggen ist es häufig praktisch, zwischen einem Denial aufgrund eines niedrigen Identitätswechsels und einer Ablehnung aufgrund eines Fehlers in Ihrem Code zu unterscheiden. Sie können einen einfachen Test in Ihrem Code verwenden, um den Unterschied zu ermitteln. Weitere Informationen finden Sie unter Debuggen von "Access Denied"-Codes.

Melden teilweise Vorgänge

Ein häufiges Vorkommen einer Nachricht "Zugriff verweigert" ist, wenn WMI nicht alle Informationen zum Ausfüllen einer Instanz bereitstellen kann. Beispielsweise kann ein Client über die Berechtigung verfügen, ein Festplattenlaufwerkobjekt anzuzeigen, aber möglicherweise nicht über die Autorität verfügen, um zu sehen, wie viel Speicherplatz auf der Festplatte selbst verfügbar ist. Ihr Anbieter muss bestimmen, wie eine Situation behandelt werden kann, wenn der Anbieter eine Instanz aufgrund einer Zugriffsverletzung nicht vollständig mit Eigenschaften füllen kann.

WMI erfordert keine einzige Antwort auf Clients, die teilweisen Zugriff auf eine Instanz haben. Stattdessen ermöglicht WMI Version 1.x dem Anbieter eine der folgenden Optionen:

  • Schlägt den gesamten Vorgang mit WBEM_E_ACCESS_DENIED fehl und gibt keine Instanzen zurück.

    Gibt ein Fehlerobjekt zusammen mit WBEM_E_ACCESS_DENIED zurück, um den Grund für die Ablehnung zu beschreiben.

  • Gibt alle verfügbaren Eigenschaften zurück und füllt nicht verfügbare Eigenschaften mit NULL.

Hinweis

Stellen Sie sicher, dass durch die Rückgabe von WBEM_E_ACCESS_DENIED kein Sicherheitsloch in Ihrem Unternehmen entsteht.

 

Berichterstattung über partielle Auflistungen

Ein weiteres häufiges Vorkommen einer Zugriffsverletzung ist, wenn WMI nicht alle Enumerationen zurückgeben kann. Beispielsweise kann ein Client Zugriff auf alle Objekte des lokalen Netzwerkcomputers haben, aber keinen Zugriff auf Computerobjekte außerhalb seiner Domäne haben. Ihr Anbieter muss bestimmen, wie eine Situation behandelt werden kann, wenn eine Aufzählung aufgrund einer Zugriffsverletzung nicht abgeschlossen werden kann.

Wie bei einem Instanzanbieter erfordert WMI keine einzige Antwort auf eine partielle Aufzählung. Stattdessen ermöglicht WMI Version 1.x einem Anbieter eine der folgenden Optionen:

  • Gibt WBEM_S_NO_ERROR für alle Instanzen zurück, auf die der Anbieter zugreifen kann.

    Wenn Sie diese Option verwenden, ist dem Benutzer nicht bewusst, dass einige Instanzen nicht verfügbar waren. Eine Reihe von Anbietern, z. B. solche, die die Structured Query Language (SQL) mit Sicherheit auf Zeilenebene verwenden, geben erfolgreiche Teilergebnisse mithilfe der Sicherheitsstufe des Aufrufers zurück, um das Resultset zu definieren.

  • Schlägt den gesamten Vorgang mit WBEM_E_ACCESS_DENIED fehl und gibt keine Instanzen zurück.

    Der Anbieter kann optional ein Fehlerobjekt enthalten, das die Situation für den Client beschreibt. Beachten Sie, dass einige Anbieter serial auf Datenquellen zugreifen können und möglicherweise erst dann auf Denials stoßen, wenn sie durch die Enumeration weitergeleitet werden.

  • Gibt alle Instanzen zurück, auf die zugegriffen werden kann, und gibt den Nichtfehlerstatuscode WBEM_S_ACCESS_DENIED zurück.

    Der Anbieter sollte die Ablehnung während der Enumeration notieren und kann weiterhin Instanzen bereitstellen, wobei er mit dem Statuscode "Nicht-Fehler" abschließt. Der Anbieter kann auch entscheiden, die Aufzählung beim ersten Denial zu beenden. Die Begründung für diese Option besteht darin, dass unterschiedliche Anbieter unterschiedliche Abrufparadigma aufweisen. Möglicherweise hat ein Anbieter bereits Instanzen übermittelt, bevor eine Zugriffsverletzung erkannt wird. Einige Anbieter können sich entscheiden, weiterhin andere Instanzen zu versorgen, während andere möglicherweise deren Bereitstellung beenden möchten.

Aufgrund der Struktur von COM können Sie im Fehlerfall keine Informationen zurückübertragen, mit Ausnahme eines Fehlerobjekts. Daher können Sie sowohl Informationen als auch einen Fehlercode nicht zurückgeben. Wenn Sie Informationen zurückgeben möchten, müssen Sie stattdessen einen Nichtfehlerstatuscode verwenden.

Debuggen des Zugriffs verweigerten Codes

Einige Anwendungen nutzen möglicherweise Identitätswechselebenen unterhalb von RPC_C_IMP_LEVEL_IMPERSONATE. In diesem Fall schlagen die meisten Identitätswechselaufrufe des Anbieters für die Clientanwendung fehl. Um einen Anbieter erfolgreich zu entwerfen und zu implementieren, müssen Sie diese Idee berücksichtigen.

Standardmäßig ist die einzige andere Impersonierungsebene, die auf einen Anbieter zugreifen kann, RPC_C_IMP_LEVEL_IDENTIFY. In Fällen, in denen eine Clientanwendung RPC_C_IMP_LEVEL_IDENTIFY verwendet, gibt CoImpersonateClient keinen Fehlercode zurück. Stattdessen stellt der Anbieter den Identitätswechsel des Clients nur zu Identifikationszwecken bereit. Daher geben die meisten vom Anbieter aufgerufenen Windows-Methoden eine Nachricht mit Zugriff verweigert zurück. Dies ist in der Praxis harmlos, da die Benutzer nichts unangemessenes tun dürfen. Es kann jedoch hilfreich sein, während der Anbieterentwicklung zu wissen, ob der Client wirklich imitiert wurde oder nicht.

Der Code erfordert die folgenden Verweise und #include Anweisungen, um ordnungsgemäß zu kompilieren.

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

Das folgende Codebeispiel zeigt, wie Sie ermitteln können, ob ein Anbieter die Identität einer Clientanwendung erfolgreich angenommen hat.

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

Entwickeln eines WMI-Anbieters

Festlegen von Namespacesicherheitsdeskriptoren

Sichern Ihres Anbieters