Festlegen der Sicherheit für einen asynchronen Aufruf

Asynchrone Aufrufe stellen schwerwiegende Sicherheitsrisiken dar, da ein Rückruf an die Senke möglicherweise nicht das Ergebnis des asynchronen Aufrufs durch die ursprüngliche Anwendung oder das ursprüngliche Skript ist. Die Sicherheit bei Remoteverbindungen basiert auf der Verschlüsselung der Kommunikation zwischen dem Client und dem Anbieter auf dem Remotecomputer. In C++ können Sie die Verschlüsselung über den Parameter auf Authentifizierungsebene im Aufruf von CoInitializeSecurityfestlegen. Legen Sie bei der Skripterstellung authenticationLevel in der Monikerverbindung oder in einem SWbemSecurity-Objekt fest. Weitere Informationen finden Sie unter Festlegen der Standardprozesssicherheitsstufe mit VBScript.

Die Sicherheitsrisiken für asynchrone Aufrufe bestehen, da WMI die Authentifizierungsebene für einen Rückruf verringert, bis der Rückruf erfolgreich ist. Bei einem ausgehenden asynchronen Aufruf kann der Client die Authentifizierungsebene für die Verbindung auf WMI festlegen. WMI ruft die Sicherheitseinstellungen für den Clientaufruf ab und versucht, einen Rückruf mit der gleichen Authentifizierungsebene durchzuführen. Der Rückruf wird immer auf der _ _ _ _ PKT _ PRIVACY-Ebene von RPC C AUTHN LEVEL initiiert. Wenn der Rückruf fehlschlägt, verringert WMI die Authentifizierungsebene auf eine Ebene, auf der der Rückruf ggf. erfolgreich ausgeführt werden kann, auf RPC _ C _ AUTHN _ LEVEL _ NONE. Im Kontext von Aufrufen innerhalb des lokalen Systems, in dem der Authentifizierungsdienst nicht Kerberos ist, wird der Rückruf immer bei RPC _ C _ AUTHN _ LEVEL _ NONE zurückgegeben.

Die Mindestauthentifizierungsebene ist RPC _ C _ AUTHN _ LEVEL _ PKT (wbemAuthenticationLevelPkt für Skripterstellung). Sie können jedoch eine höhere Ebene angeben, z. B. RPC _ C _ AUTHN _ LEVEL _ PKT _ PRIVACY (wbemAuthenticationLevelPktPrivacy). Es wird empfohlen, dass Clientanwendungen oder Skripts die Authentifizierungsebene auf RPC _ C _ AUTHN _ LEVEL _ DEFAULT (wbemAuthenticationLevelDefault) festlegen, wodurch die Authentifizierungsebene auf die vom Server angegebene Ebene ausgehandelt werden kann.

Der Registrierungswert HKEY _ LOCAL _ MACHINE \ Software \ Microsoft \ WBEM \ CIMOM \ UnsecAppAccessControlDefault steuert, ob WMI in Rückrufen auf eine akzeptable Authentifizierungsebene prüft. Dies ist der einzige Mechanismus zum Schutz der Senkensicherheit für asynchrone Aufrufe, die in Skripts oder Visual Basic erfolgen. Standardmäßig ist dieser Registrierungsschlüssel auf 0 (null) festgelegt. Wenn der Registrierungsschlüssel 0 (null) ist, überprüft WMI die Authentifizierungsebenen nicht. Legen Sie den Registrierungsschlüssel auf 1 fest, um asynchrone Aufrufe in der Skripterstellung zu schützen. C++-Clients können IWbemUnsecuredApartment::CreateSinkStub aufrufen, um den Zugriff auf die Senke zu steuern. Der Wert wird standardmäßig an einer beliebigen Stelle erstellt.

Die folgenden Themen enthalten Beispiele für das Festlegen der asynchronen Aufrufsicherheit:

Festlegen der asynchronen Aufrufsicherheit in C++

Die IWbemUnsecuredApartment::CreateSinkStub-Methode ähnelt der IUnsecuredApartment::CreateObjectStub-Methode und erstellt eine Senke in einem separaten Prozess, Unsecapp.exe, um Rückrufe zu empfangen. Die CreateSinkStub-Methode verfügt jedoch über einen dwFlag-Parameter, der angibt, wie der separate Prozess die Zugriffssteuerung behandelt.

Der dwFlag-Parameter gibt eine der folgenden Aktionen für Unsecapp.exe an:

  • Verwenden Sie die Einstellung des Registrierungsschlüssels, um zu bestimmen, ob der Zugriff überprüft werden soll.
  • Ignorieren Sie den Registrierungsschlüssel, und überprüfen Sie immer den Zugriff.
  • Ignorieren Sie den Registrierungsschlüssel, und überprüfen Sie nie den Zugriff.

Das Codebeispiel in diesem Thema erfordert die folgende # include-Anweisung, um ordnungsgemäß zu kompilieren.

#include <wbemidl.h>

Im folgenden Verfahren wird beschrieben, wie ein asynchroner Aufruf mit IWbemUnsecuredApartmentausgeführt wird.

So führen Sie einen asynchronen Aufruf mit IWbemUnsecuredApartment aus

  1. Erstellen Sie einen dedizierten Prozess mit einem Aufruf von CoCreateInstance.

    Das folgende Codebeispiel ruft CoCreateInstance auf, um einen dedizierten Prozess zu erstellen.

    CLSID                    CLSID_WbemUnsecuredApartment;
    IWbemUnsecuredApartment* pUnsecApp = NULL;
    
    CoCreateInstance(CLSID_WbemUnsecuredApartment, 
                     NULL, 
                     CLSCTX_LOCAL_SERVER, 
                     IID_IWbemUnsecuredApartment, 
                     (void**)&pUnsecApp);
    
  2. Instanziieren Sie das Senkenobjekt.

    Im folgenden Codebeispiel wird ein neues Senkenobjekt erstellt.

    CMySink* pSink = new CMySink;
    pSink->AddRef();
    
  3. Erstellen Sie einen Stub für die Senke.

    Ein Stub ist eine Wrapperfunktion, die aus der Senke erzeugt wird.

    Im folgenden Codebeispiel wird ein Stub für die Senke erstellt.

    LPCWSTR          wszReserved = NULL;           
    IWbemObjectSink* pStubSink   = NULL;
    IUnknown*        pStubUnk    = NULL; 
    
    pUnsecApp->CreateSinkStub(pSink,
                              WBEM_FLAG_UNSECAPP_CHECK_ACCESS,  //Authenticate callbacks regardless of registry key
                              wszReserved,
                              &pStubSink);
    
  4. Geben Sie den Senkenobjektzeiger frei.

    Sie können den Objektzeiger freigeben, da der Stub jetzt den Zeiger besitzt.

    Im folgenden Codebeispiel wird der Objektzeiger veröffentlicht.

    pSink->Release();
    
  5. Verwenden Sie den Stub in jedem asynchronen Aufruf.

    Geben Sie nach Abschluss des Aufrufs den lokalen Verweiszähler frei.

    Im folgenden Codebeispiel wird der Stub in einem asynchronen Aufruf verwendet.

    // pServices is an IWbemServices* object
    pServices->CreateInstanceEnumAsync(strClassName, 0, NULL, pStubSink);
    

    Manchmal müssen Sie möglicherweise einen asynchronen Aufruf abbrechen, nachdem Sie den Aufruf tätigen. Wenn Sie den Aufruf abbrechen müssen, brechen Sie den Aufruf mit dem gleichen Zeiger ab, der den Aufruf ursprünglich durchgeführt hat.

    Im folgenden Codebeispiel wird beschrieben, wie ein asynchroner Aufruf abgebrochen wird.

    pServices->CancelAsyncCall(pStubSink);
    
  6. Geben Sie den lokalen Verweiszähler frei, wenn Sie mit dem asynchronen Aufruf fertig sind.

    Stellen Sie sicher, dass Sie den pStubSink-Zeiger erst freigeben, nachdem Sie bestätigt haben, dass der asynchrone Aufruf nicht abgebrochen werden muss. Geben Sie außerdem pStubSink nicht mehr frei, nachdem WMI den PSink-Senkenzeiger veröffentlicht hat. Das Freigeben von pStubSink nach pSink erstellt einen zirkulären Verweiszähler, bei dem sowohl die Senke als auch der Stub dauerhaft im Arbeitsspeicher verbleiben. Stattdessen befindet sich ein möglicher Speicherort zum Freigeben des Zeigers im Aufruf IWbemObjectSink::SetStatus, der von WMI ausgeführt wird, um zu melden, dass der ursprüngliche asynchrone Aufruf abgeschlossen ist.

  7. Wenn Sie fertig sind, sollten Sie COM mit einem Aufruf von Release()nicht initialisieren.

    Das folgende Codebeispiel zeigt, wie Release() für den pUnsecApp-Zeiger aufgerufen wird.

    pUnsecApp->Release();
    

Weitere Informationen zur CoInitializeSecurity-Funktion und den Parametern finden Sie in der COM-Dokumentation.