Der COM-Erhöhungsmoniker
Der COM-Erhöhungsmoniker ermöglicht Anwendungen, die unter Benutzerkontensteuerung (User Account Control, UAC) ausgeführt werden, COM-Klassen mit erhöhten Rechten zu aktivieren. Weitere Informationen finden Sie unter Fokus auf geringste Rechte.
Wann sollte der Erhöhungsmoniker verwendet werden?
Der Erhöhungsmoniker wird verwendet, um eine COM-Klasse zu aktivieren, um eine bestimmte und eingeschränkte Funktion zu erreichen, die erhöhte Berechtigungen erfordert, z. B. das Ändern des Systemdatums und der Systemzeit.
Eine Erhöhung erfordert die Teilnahme sowohl von einer COM-Klasse als auch von ihrem Client. Die COM-Klasse muss so konfiguriert werden, dass erhöhte Rechte unterstützt werden, indem der zugehörige Registrierungseintrag kommentiert wird, wie im Abschnitt Anforderungen beschrieben. Der COM-Client muss erhöhte Rechte mithilfe des Erhöhungsmonikers anfordern.
Der Erhöhungsmoniker soll keine Anwendungskompatibilität bereitstellen. Wenn Sie beispielsweise eine ältere 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 Erhöhungsmoniker zu aktivieren. Wenn der COM-Client mit erhöhten Rechten CoCreateInstance mithilfe der CLSID der Legacyanwendung aufruft, wird der Clientstatus mit erhöhten Rechten an den Serverprozess übertragen.
Nicht alle COM-Funktionen sind mit der Erhöhung kompatibel. Die Funktionen, die nicht funktionieren, umfassen Folgendes:
- Die Rechteerweiterung wird nicht von einem Client zu einem COM-Remoteserver übertragen. Wenn ein Client einen COM-Remoteserver mit dem Erhöhungsmoniker aktiviert, wird der Server nicht erhöht, auch wenn er erhöhte Rechte unterstützt.
- Wenn eine COM-Klasse mit erhöhten Rechten während eines COM-Aufrufs den Identitätswechsel verwendet, verlieren sie möglicherweise ihre erhöhten Berechtigungen während des Identitätswechsels.
- Wenn ein COM-Server mit erhöhten Rechten eine Klasse in der ausgeführten Objekttabelle (ROT) registriert, ist die Klasse für Clients ohne erhöhte Rechte nicht verfügbar.
- Ein Prozess mit erhöhten Rechten mithilfe des UAC-Mechanismus lädt während COM-Aktivierungen keine Benutzerklassen. Für COM-Anwendungen bedeutet dies, dass die COM-Klassen der Anwendung in der Registrierungsstruktur HKEY _ LOCAL _ MACHINE 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.
- Drag & Drop ist von Anwendungen ohne erhöhte Rechte nicht zulässig.
Requirements (Anforderungen)
Um den Erhöhungsmoniker zum Aktivieren einer COM-Klasse zu verwenden, muss die -Klasse so konfiguriert werden, dass sie als startende Benutzer oder die Anwendungsidentität "Activate as Activator" 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 außerdem mit einem "anzeigefreundlichen" Anzeigenamen versehen werden, der mit der mehrsprachigen Benutzeroberfläche 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 CSV-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-Aktiviert kommentiert werden. 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 Struktur HKEY LOCAL MACHINE vorhanden sein müssen, nicht in _ _ der Struktur HKEY CURRENT USER _ oder _ HKEY _ USERS. Dadurch wird verhindert, dass Benutzer COM-Klassen erhöhen, die sie nicht auch registrieren konnten.
Der Erhöhungsmoniker und die Benutzeroberfläche für erhöhte Rechte
Wenn der Client bereits über erhöhte Rechte verfügt, führt die Verwendung des Erhöhungsmonikers nicht dazu, dass die Benutzeroberfläche für erhöhte Rechte angezeigt wird.
Verwenden des Monikers für erhöhte Rechte
Der Erhöhungsmoniker ist ein COM-Standardmoniker, der den Sitzungs-, Partitions- oder Warteschlangenmonikern ähnelt. Sie leitet eine Aktivierungsanforderung an einen angegebenen Server mit der angegebenen Höhe weiter. Die zu aktivierende CLSID wird in der Monikerzeichenfolge angezeigt.
Der Erhöhungsmoniker unterstützt die folgenden Token auf Ausführungsebene:
- Administrator
- 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 eine Instanz der COM-Klasse zurückzugeben, die durch guid angegeben wird. Beachten Sie, dass der "neue" Moniker intern die IClassFactory-Schnittstelle verwendet, um ein Klassenobjekt abzurufen, und dann IClassFactory::CreateInstance dafür aufruft.
Der Erhöhungsmoniker kann auch verwendet werden, um ein Klassenobjekt abzurufen, das IClassFactoryimplementiert. Der Aufrufer ruft dann CreateInstance auf, um eine Objektinstanz abzurufen. Die Syntax hierfür sieht wie folgt aus:
Elevation:Administrator!clsid:{guid}
Beispielcode
Im folgenden Codebeispiel wird die Verwendung des Monikers für erhöhte Rechte veranschaulicht. Es wird davon ausgegangen, dass Sie COM bereits für den 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 _ OPTS2abgeleitet.
Die einzige Hinzufügung ist ein HWND-Feld, hwnd. Dieses Handle stellt ein Fenster dar, das ggf. besitzer der Benutzeroberfläche für erhöhte Rechte wird.
Wenn hwnd NULL ist, ruft COM GetActiveWindow auf, um ein Fensterhandle zu suchen, 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 dem Skriptthread zugeordnete Fenster zu verwenden.
Über-die-Shoulder-Erhöhung (OVER THE SHOULDER, OTS)
"Over-the-Shoulder"-Rechteerweiterung (Over-the-Shoulder, OTS) bezieht sich auf das Szenario, in dem ein Client einen COM-Server mit den Anmeldeinformationen eines Administrators und nicht mit seinem eigenen Server ausführt. (Der Begriff "über die Uhr" bedeutet, dass der Administrator während der Ausführung des Servers durch den Client über die Client sollte.)
Dieses Szenario kann ein Problem für COM-Aufrufe an den Server verursachen, da der Server CoInitializeSecurity entweder explizit (programmgesteuert) oder implizit (d. b. deklarativ, mithilfe der Registrierung) nicht aufruft. Für solche Server berechnet COM einen Sicherheitsdeskriptor, mit dem nur SELF-, SYSTEM- und Integrierte \ Administratoren COM-Aufrufe an den Server senden können. Diese Anordnung funktioniert in OTS-Szenarien nicht. Stattdessen muss der Server CoInitializeSecurity entweder explizit oder implizit aufrufen und eine ACL angeben, die die INTERAKTIVE Gruppen-SID und SYSTEM enthält.
Das folgende Codebeispiel zeigt, wie Sie einen Sicherheitsdeskriptor (SD) mit der INTERAKTIVEn 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;
}
Das folgende Codebeispiel zeigt, wie CoInitializeSecurity implizit mit der 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;
}
Das folgende Codebeispiel zeigt, wie CoInitializeSecurity explizit mit der 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 CoinitilizeSecurity.
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) der Sicherheitsbeschreibung angegeben. In 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 keine Änderung der Integritätsstufe (IL) in COM-Berechtigungen. 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 die Berechtigungen Start/Aktivierung und Aufruf gültig sind. Daher ist es möglich, einen COM-Server zu schreiben, der das Starten, Aktivieren oder Aufrufen von Clients mit einer bestimmten IL nicht zu lässt. Weitere Informationen zu Integritätsebenen finden Sie im Abschnitt "Understanding Windows Vista es Integrity Mechanism" unter Understanding and Working in Protected Mode Internet 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 Low IL-Clients 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:
- Beim Starten eines COM-Serverprozesses wird die IL im Serverprozesstoken auf die Client- oder Servertoken-IL festgelegt, je nachdem, welcher Wert niedriger ist.
- Com verhindert standardmäßig, dass Low IL-Clients an ausgeführte Instanzen von COM-Servern gebunden werden. Um die Bindung zuzulassen, muss der Sicherheitsdeskriptor zum Starten/Aktivieren eines COM-Servers eine SACL enthalten, die die Bezeichnung Low IL angibt (im vorherigen Abschnitt finden Sie den Beispielcode zum Erstellen eines solchen Sicherheitsdeskriptors).
Server mit erhöhten Rechten und ROT-Registrierungen
Wenn sich ein COM-Server in der laufenden Objekttabelle (ROT) registrieren und jedem Client den Zugriff auf die Registrierung erlauben möchte, muss er das ROTFLAGS _ ALLOWANYCLIENT-Flag verwenden. Ein COM-Server vom Typ "Activate As Activator" kann ROTFLAGS _ ALLOWANYCLIENT nicht angeben, da der DCOMSCM (Service Control Manager) eine Spoofüberprüfung für dieses Flag erzwingt. Aus diesem Grund fügt COM in Windows Vista Unterstützung für einen neuen Registrierungseintrag hinzu, mit dem der Server festlegen kann, dass seine ROT-Registrierungen jedem Client zur Verfügung gestellt 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 Struktur HKEY _ LOCAL _ MACHINE vorhanden sein.
Dieser Eintrag stellt einen Server "Aktivieren als Activator" mit der gleichen Funktionalität wie ROTFLAGS _ ALLOWANYCLIENT für einen RunAs-Server zur Verfügung.