Freigeben über


Der COM-Erhöhungsmoniker

Der COM-Erhöhungsmoniker ermöglicht Anwendungen, die unter Benutzerkontensteuerung (User Account Control, UAC) ausgeführt werden, das Aktivieren von COM-Klassen mit erhöhten Rechten. Weitere Informationen finden Sie unter Fokus auf die geringsten Berechtigungen.

Verwendung des Höhenmonikers

Der Höhenmoniker wird verwendet, um eine COM-Klasse zu aktivieren, um eine bestimmte und eingeschränkte Funktion auszuführen, die erhöhte Berechtigungen erfordert, z. B. das Ändern des Systemdatums und der Systemzeit.

Die Erhöhung erfordert die Teilnahme sowohl von einer COM-Klasse als auch von ihrem Client. Die COM-Klasse muss für die Unterstützung von Erhöhungen konfiguriert werden, indem der Registrierungseintrag kommentiert wird, wie im Abschnitt "Anforderungen" beschrieben. Der COM-Client muss die Erhöhung mithilfe des Höhenmonikers anfordern.

Der Rechteerweiterungsmoniker ist nicht für Anwendungskompatibilität vorgesehen. Wenn Sie beispielsweise eine Legacy-COM-Anwendung wie WinWord als Server mit erhöhten Rechten ausführen möchten, sollten Sie die ausführbare COM-Clientdatei so konfigurieren, dass eine Erhöhung erforderlich ist, anstatt die Klasse der Legacyanwendung mit dem Höhenmoniker zu aktivieren. Wenn der COM-Client mit erhöhten Rechten CoCreateInstance mit der CLSID der Legacyanwendung aufruft, wird der Clientzustand mit erhöhten Rechten an den Serverprozess übertragen.

Nicht alle COM-Funktionen sind mit der Erhöhung kompatibel. Zu den Funktionen, die nicht funktionieren, gehören:

  • Die Rechteerweiterung wird nicht von einem Client zu einem COM-Remoteserver übertragen. Wenn ein Client einen COM-Remoteserver mit dem Höhenmoniker aktiviert, wird der Server nicht mit erhöhten Rechten versehen, auch wenn er die Rechteerweiterung unterstützt.
  • Wenn eine COM-Klasse mit erhöhten Rechten den Identitätswechsel während eines COM-Aufrufs verwendet, verlieren sie möglicherweise während des Identitätswechsels ihre erhöhten Berechtigungen.
  • Wenn ein COM-Server mit erhöhten Rechten eine Klasse in der ausgeführten Objekttabelle (ROT) registriert, ist die Klasse für Clients ohne rechte Rechte nicht verfügbar.
  • Ein Prozess mit erhöhten Rechten mithilfe des UAC-Mechanismus lädt während der COM-Aktivierungen keine Klassen pro Benutzer. Für COM-Anwendungen bedeutet dies, dass die COM-Klassen der Anwendung in der HKEY_LOCAL_MACHINE Registrierungsstruktur installiert werden müssen, wenn die Anwendung sowohl von nicht privilegierten als auch von privilegierten Konten verwendet werden soll. Die COM-Klassen der Anwendung müssen nur in der HKEY_USERS-Struktur installiert werden, wenn die Anwendung nie von privilegierten Konten verwendet wird.
  • Das Ziehen und Ablegen ist von Anwendungen mit nicht erhöhten Rechten in Anwendungen mit erhöhten Rechten nicht zulässig.

Anforderungen

Um den Höhenmoniker zum Aktivieren einer COM-Klasse zu verwenden, muss die Klasse so konfiguriert werden, dass sie als startender Benutzer oder als Anwendungsidentität "Activateor aktivieren" ausgeführt wird. Wenn die Klasse für die Ausführung unter einer anderen Identität konfiguriert ist, gibt die Aktivierung den Fehler CO_E_RUNAS_VALUE_MUST_BE_AAA zurück.

Die -Klasse muss auch mit einem anzeigefähigen Namen versehen werden, der mit mui-kompatibel (Multilingual User Interface) kompatibel ist. Hierfür ist der folgende Registrierungseintrag erforderlich:

HKEY_LOCAL_MACHINE\Software\Classes\CLSID
   {CLSID}
      LocalizedString = displayName

Wenn dieser Eintrag fehlt, gibt die Aktivierung den Fehler CO_E_MISSING_DISPLAYNAME zurück. Wenn die MUI-Datei fehlt, wird der Fehlercode der RegLoadMUIStringW-Funktion zurückgegeben.

Fügen Sie optional den folgenden Registrierungsschlüssel hinzu, um ein Anwendungssymbol anzugeben, das von der UAC-Benutzeroberfläche angezeigt werden soll:

HKEY_LOCAL_MACHINE\Software\Classes\CLSID
   {CLSID}
      Elevation
         IconReference = applicationIcon

IconReference verwendet das gleiche Format wie LocalizedString:

@ pathtobinary,-resourcenumber

Darüber hinaus muss die COM-Komponente signiert sein, damit das Symbol angezeigt wird.

Die COM-Klasse muss auch als LUA-fähig gekennzeichnet sein. Hierfür ist der folgende Registrierungseintrag erforderlich:

HKEY_LOCAL_MACHINE\Software\Classes\CLSID
   {CLSID}
      Elevation
         Enabled = 1

Wenn dieser Eintrag fehlt, gibt die Aktivierung den Fehler CO_E_ELEVATION_DISABLED zurück.

Beachten Sie, dass diese Einträge in der HKEY_LOCAL_MACHINE-Struktur vorhanden sein müssen, nicht in der HKEY_CURRENT_USER- oder HKEY_USERS-Struktur. Dadurch wird verhindert, dass Benutzer COM-Klassen erhöhen, die sie nicht auch über die Berechtigungen für die Registrierung verfügten.

Der Höhenmoniker und die Benutzeroberfläche für die Erhöhung

Wenn der Client bereits mit erhöhten Rechten versehen ist, führt die Verwendung des Höhenmonikers nicht dazu, dass die Benutzeroberfläche für die Erhöhung angezeigt wird.

Verwenden des Höhenmonikers

Der Höhenmoniker ist ein STANDARDMÄßIGER COM-Moniker, ähnlich dem Sitzungs-, Partitions- oder Warteschlangenmoniker. Sie leitet eine Aktivierungsanforderung an einen angegebenen Server mit der angegebenen Höhenstufe weiter. Die zu aktivierende CLSID wird in der Monikerzeichenfolge angezeigt.

Der Höhenmoniker unterstützt die folgenden Token auf Ausführungsebene:

  1. Administrator
  2. Maximal

Die Syntax hierfür sieht wie folgt aus:

Elevation:Administrator!new:{guid}
Elevation:Highest!new:{guid}

Die vorangehende Syntax verwendet den Moniker "new", um einen instance der com-Klasse zurückzugeben, die von guid angegeben wird. Beachten Sie, dass der Moniker "new" intern die IClassFactory-Schnittstelle verwendet, um ein Klassenobjekt abzurufen, und dann IClassFactory::CreateInstance dafür aufruft .

Der Höhenmoniker kann auch verwendet werden, um ein Klassenobjekt abzurufen, das IClassFactory implementiert. Der Aufrufer ruft dann CreateInstance auf, um ein Objekt instance abzurufen. Die Syntax hierfür sieht wie folgt aus:

Elevation:Administrator!clsid:{guid}

Beispielcode

Im folgenden Codebeispiel wird die Verwendung des Monikers zur Erhöhung veranschaulicht. Es wird davon ausgegangen, dass Sie COM bereits im aktuellen Thread initialisiert haben.

HRESULT CoCreateInstanceAsAdmin(HWND hwnd, REFCLSID rclsid, REFIID riid, __out void ** ppv)
{
    BIND_OPTS3 bo;
    WCHAR  wszCLSID[50];
    WCHAR  wszMonikerName[300];

    StringFromGUID2(rclsid, wszCLSID, sizeof(wszCLSID)/sizeof(wszCLSID[0])); 
    HRESULT hr = StringCchPrintf(wszMonikerName, sizeof(wszMonikerName)/sizeof(wszMonikerName[0]), L"Elevation:Administrator!new:%s", wszCLSID);
    if (FAILED(hr))
        return hr;
    memset(&bo, 0, sizeof(bo));
    bo.cbStruct = sizeof(bo);
    bo.hwnd = hwnd;
    bo.dwClassContext  = CLSCTX_LOCAL_SERVER;
    return CoGetObject(wszMonikerName, &bo, riid, ppv);
}

BIND_OPTS3 ist neu in Windows Vista. Sie wird von BIND_OPTS2 abgeleitet.

Der einzige Zusatz ist ein HWND-Feld , hwnd. Dieses Handle stellt ein Fenster dar, das ggf. besitzer der Benutzeroberfläche für Erhöhte Rechte wird.

Wenn hwndNULL ist, ruft COM GetActiveWindow auf, um ein Fensterhandle zu finden, das dem aktuellen Thread zugeordnet ist. Dieser Fall kann auftreten, wenn der Client ein Skript ist, das keine BIND_OPTS3 Struktur ausfüllen kann. In diesem Fall versucht COM, das Fenster zu verwenden, das dem Skriptthread zugeordnet ist.

Over-the-Shoulder (OTS) Erhöhung

Over-the-shoulder (OTS)-Erhöhung bezieht sich auf das Szenario, in dem ein Client einen COM-Server mit den Anmeldeinformationen eines Administrators anstelle seiner eigenen ausführt. (Der Begriff "über die Schulter" bedeutet, dass der Administrator über die Schulter des Clients überwacht, während der Client den Server ausführt.)

Dieses Szenario kann zu einem Problem für COM-Aufrufe an den Server führen, da der Server CoInitializeSecurity nicht explizit (d. a. programmgesteuert) oder implizit (d. a. deklarativ, mithilfe der Registrierung) aufruft. Für solche Server berechnet COM einen Sicherheitsdeskriptor, der es nur SELF, SYSTEM und Builtin\Administrators ermöglicht, COM-Aufrufe an den Server zu tätigen. Diese Anordnung funktioniert in OTS-Szenarien nicht. Stattdessen muss der Server CoInitializeSecurity explizit oder implizit aufrufen und eine ACL angeben, die die INTERACTIVE-Gruppen-SID und SYSTEM enthält.

Im folgenden Codebeispiel wird gezeigt, wie Sie einen Sicherheitsdeskriptor (SD) mit der INTERACTIVE-Gruppen-SID erstellen.

BOOL GetAccessPermissionsForLUAServer(SECURITY_DESCRIPTOR **ppSD)
{
// Local call permissions to IU, SY
    LPWSTR lpszSDDL = L"O:BAG:BAD:(A;;0x3;;;IU)(A;;0x3;;;SY)";
    SECURITY_DESCRIPTOR *pSD;
    *ppSD = NULL;

    if (ConvertStringSecurityDescriptorToSecurityDescriptorW(lpszSDDL, SDDL_REVISION_1, (PSECURITY_DESCRIPTOR *)&pSD, NULL))
    {
        *ppSD = pSD;
        return TRUE;
    }

    return FALSE;
}

Im folgenden Codebeispiel wird gezeigt, wie CoInitializeSecurity implizit mit dem SD aus dem vorherigen Codebeispiel aufgerufen wird:

// hKey is the HKCR\AppID\{GUID} key
BOOL SetAccessPermissions(HKEY hkey, PSECURITY_DESCRIPTOR pSD)
{
    BOOL bResult = FALSE;
    DWORD dwLen = GetSecurityDescriptorLength(pSD);
    LONG lResult;
    lResult = RegSetValueExA(hkey, 
        "AccessPermission",
        0,
        REG_BINARY,
        (BYTE*)pSD,
        dwLen);
    if (lResult != ERROR_SUCCESS) goto done;
    bResult = TRUE;
done:
    return bResult;
}

Im folgenden Codebeispiel wird gezeigt, wie CoInitializeSecurity explizit mit dem obigen SD aufgerufen wird:

// Absolute SD values
PSECURITY_DESCRIPTOR pAbsSD = NULL;
DWORD AbsSdSize = 0;
PACL  pAbsAcl = NULL;
DWORD AbsAclSize = 0;
PACL  pAbsSacl = NULL;
DWORD AbsSaclSize = 0;
PSID  pAbsOwner = NULL;
DWORD AbsOwnerSize = 0;
PSID  pAbsGroup = NULL;
DWORD AbsGroupSize = 0;

MakeAbsoluteSD (
    pSD,
    pAbsSD,
    &AbsSdSize,
    pAbsAcl,
    &AbsAclSize,
    pAbsSacl,
    &AbsSaclSize,
    pAbsOwner,
    &AbsOwnerSize,
    pAbsGroup,
    &AbsGroupSize
);

if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
{
    pAbsSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, AbsSdSize);
    pAbsAcl = (PACL)LocalAlloc(LMEM_FIXED, AbsAclSize);
    pAbsSacl = (PACL)LocalAlloc(LMEM_FIXED, AbsSaclSize);
    pAbsOwner = (PSID)LocalAlloc(LMEM_FIXED, AbsOwnerSize);
    pAbsGroup = (PSID)LocalAlloc(LMEM_FIXED, AbsGroupSize);

    if ( ! (pAbsSD && pAbsAcl && pAbsSacl && pAbsOwner && pAbsGroup))
    {
        hr = E_OUTOFMEMORY;
        goto Cleanup;
    }
    if ( ! MakeAbsoluteSD(
        pSD,
        pAbsSD,
        &AbsSdSize,
        pAbsAcl,
        &AbsAclSize,
        pAbsSacl,
        &AbsSaclSize,
        pAbsOwner,
        &AbsOwnerSize,
        pAbsGroup,
        &AbsGroupSize
        ))
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Cleanup;
    }
}
else
{
    hr = HRESULT_FROM_WIN32(GetLastError());
    goto Cleanup;
}

// Call CoInitializeSecurity .

COM-Berechtigungen und obligatorische Zugriffsbezeichnungen

Windows Vista führt das Konzept der obligatorischen Zugriffsbezeichnungen in Sicherheitsbeschreibungen ein. Die Bezeichnung bestimmt, ob Clients Ausführungszugriff auf ein COM-Objekt erhalten können. Die Bezeichnung wird im SACL-Teil (System Access Control List) des Sicherheitsdeskriptors angegeben. Unter Windows Vista unterstützt COM die bezeichnung "SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP". SACLs in den COM-Berechtigungen werden auf Betriebssystemen vor Windows Vista ignoriert.

Ab Windows Vista unterstützt dcomcnfg.exe das Ändern der Integritätsstufe (IL) in COM-Berechtigungen nicht. Sie muss programmgesteuert festgelegt werden.

Das folgende Codebeispiel zeigt, wie Sie einen COM-Sicherheitsdeskriptor mit einer Bezeichnung erstellen, die Start-/Aktivierungsanforderungen von allen LOW IL-Clients zulässt. Beachten Sie, dass die Bezeichnungen für Start-/Aktivierungs- und Anrufberechtigungen gültig sind. Daher ist es möglich, einen COM-Server zu schreiben, der den Start, die Aktivierung oder Aufrufe von Clients mit einer bestimmten IL nicht erlaubt. Weitere Informationen zu Integritätsstufen finden Sie im Abschnitt "Grundlegendes zum Integritätsmechanismus von Windows Vista" unter Verstehen und Arbeiten im internetgeschützten Modus Explorer.

BOOL GetLaunchActPermissionsWithIL (SECURITY_DESCRIPTOR **ppSD)
{
// Allow World Local Launch/Activation permissions. Label the SD for LOW IL Execute UP
    LPWSTR lpszSDDL = L"O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)";
    if (ConvertStringSecurityDescriptorToSecurityDescriptorW(lpszSDDL, SDDL_REVISION_1, (PSECURITY_DESCRIPTOR *)&pSD, NULL))
    {
        *ppSD = pSD;
        return TRUE;
    }
}

BOOL SetLaunchActPermissions(HKEY hkey, PSECURITY_DESCRIPTOR pSD)
{
    
    BOOL bResult = FALSE;
    DWORD dwLen = GetSecurityDescriptorLength(pSD);
    LONG lResult;
    lResult = RegSetValueExA(hkey, 
        "LaunchPermission",
        0,
        REG_BINARY,
        (BYTE*)pSD,
        dwLen);
    if (lResult != ERROR_SUCCESS) goto done;
    bResult = TRUE;
done:
    return bResult;
};

CoCreateInstance- und Integritätsebenen

Das Verhalten von CoCreateInstance hat sich in Windows Vista geändert, um zu verhindern, dass Clients mit niedriger IL standardmäßig an COM-Server gebunden werden. Der Server muss solche Bindungen explizit zulassen, indem er die SACL angibt. Die Änderungen an CoCreateInstance lauten wie folgt:

  1. Beim Starten eines COM-Serverprozesses wird die IL im Serverprozesstoken auf die Client- oder Servertoken-IL festgelegt, je nachdem, welcher Wert niedriger ist.
  2. Standardmäßig verhindert COM, dass Clients mit niedriger IL an ausgeführte Instanzen von COM-Servern gebunden werden. Um die Bindung zuzulassen, muss der Start-/Aktivierungs-Sicherheitsdeskriptor eines COM-Servers eine SACL enthalten, die die Bezeichnung "Niedrige IL" angibt (im vorherigen Abschnitt finden Sie den Beispielcode zum Erstellen eines solchen Sicherheitsdeskriptors).

Server mit erhöhten Rechten und ROT-Registrierungen

Wenn ein COM-Server sich in der laufenden Objekttabelle (Running Object Table, ROT) registrieren und jedem Client den Zugriff auf die Registrierung erlauben möchte, muss er das flag ROTFLAGS_ALLOWANYCLIENT verwenden. Ein COM-Server "Als Aktivator aktivieren" kann ROTFLAGS_ALLOWANYCLIENT nicht angeben, da der DCOM-Dienststeuerungs-Manager (DCOMSCM) eine Spoofprüfung für dieses Flag erzwingt. Daher fügt COM in Windows Vista Unterstützung für einen neuen Registrierungseintrag hinzu, mit dem der Server festlegen kann, dass seine ROT-Registrierungen für jeden Client verfügbar gemacht werden:

HKEY_LOCAL_MACHINE\Software\Classes\AppID
   {APPID}
      ROTFlags

Der einzige gültige Wert für diesen REG_DWORD Eintrag ist:

ROTREGFLAGS_ALLOWANYCLIENT 0x1

Der Eintrag muss in der HKEY_LOCAL_MACHINE Struktur vorhanden sein.

Dieser Eintrag stellt einen "Activateor"-Server mit der gleichen Funktionalität bereit, die ROTFLAGS_ALLOWANYCLIENT für einen RunAs-Server bereitstellt.

Sicherheit in COM

Das Verstehen des geschützten Modus des Internet Explorer und das Arbeiten damit