Moniker podnoszenia uprawnień COM
Nazwa podniesienia uprawnień COM umożliwia aplikacjom działającym w ramach kontroli konta użytkownika (UAC) aktywowanie klas COM z podwyższonymi uprawnieniami. Aby uzyskać więcej informacji, zobacz Focus on Least Privilege.
Kiedy używać moniker podniesienia uprawnień
Moniker zwiększenia uprawnień służy do aktywowania klasy COM, aby wykonać określoną i ograniczoną funkcję wymagającą podwyższonych uprawnień, takich jak zmiana daty i godziny systemu.
Podniesienie wymaga udziału zarówno klasy COM, jak i jej klienta. Klasa COM musi być skonfigurowana do obsługi podniesienia uprawnień przez dodawanie adnotacji do wpisu rejestru zgodnie z opisem w sekcji Wymagania. Klient COM musi zażądać podniesienia uprawnień przy użyciu moniker podniesienia uprawnień.
Nazwa "elevacja" nie jest przeznaczona do zapewnienia kompatybilności aplikacji. Jeśli na przykład chcesz uruchomić starszą aplikację COM, taką jak WinWord jako serwer z podwyższonym poziomem uprawnień, należy skonfigurować plik wykonywalny klienta COM, aby wymagać podniesienia uprawnień, zamiast aktywować starszą klasę aplikacji z monikerem podniesienia uprawnień. Gdy klient COM z podwyższonym poziomem uprawnień wywołuje CoCreateInstance korzystając z identyfikatora CLSID starszej aplikacji, podwyższony poziom uprawnień klienta zostanie przeniesiony do procesu serwera.
Nie wszystkie funkcje COM są zgodne z podnoszeniem uprawnień. Funkcje, które nie będą działać, obejmują:
- Podniesienie poziomu nie jest przenoszone z klienta do zdalnego serwera COM. Jeśli klient aktywuje zdalny serwer COM z nazwą poziomu uprawnień, serwer nie zostanie podniesiony do wyższego poziomu uprawnień, nawet jeśli obsługuje podniesienie uprawnień.
- Jeśli klasa COM z podwyższonym poziomem uprawnień używa impersonacji podczas wywołania COM, może utracić te uprawnienia podczas impersonacji.
- Jeśli serwer COM z podwyższonym poziomem uprawnień rejestruje klasę w uruchomionej tabeli obiektów (ROT), klasa nie będzie dostępna dla klientów bez podwyższonego poziomu uprawnień.
- Proces z podwyższonym poziomem uprawnień przy użyciu mechanizmu UAC nie ładuje klas dla poszczególnych użytkowników podczas aktywacji COM. W przypadku aplikacji COM oznacza to, że klasy COM aplikacji muszą być zainstalowane w gałęzi rejestru HKEY_LOCAL_MACHINE, jeśli aplikacja ma być używana zarówno przez konta nieuprzywilejowane, jak i uprzywilejowane. Klasy COM aplikacji muszą być zainstalowane tylko w HKEY_USERS hive, jeśli aplikacja nigdy nie jest używana przez uprzywilejowane konta.
- Przeciąganie i upuszczanie nie jest dozwolone z aplikacji bez podwyższonych uprawnień do aplikacji z podwyższonymi uprawnieniami.
Wymagania
Aby użyć monikera podwyższenia uprawnień do aktywacji klasy COM, klasa musi być skonfigurowana do uruchamiania jako aktualny użytkownik lub z tożsamością aplikacji 'Aktywuj jako aktywator'. Jeśli klasa jest skonfigurowana do działania pod inną tożsamością, aktywacja zwraca błąd CO_E_RUNAS_VALUE_MUST_BE_AAA.
Klasa musi być również oznakowana przyjazną dla użytkownika nazwą wyświetlaną zgodną z wielojęzycznym interfejsem użytkownika (MUI). Wymaga to następującego wpisu rejestru:
HKEY_LOCAL_MACHINE\Software\Classes\CLSID
{CLSID}
LocalizedString = displayName
Jeśli brakuje tego wpisu, aktywacja zwróci błąd CO_E_MISSING_DISPLAYNAME. Jeśli brakuje pliku MUI, zwracany jest kod błędu funkcji RegLoadMUIStringW.
Opcjonalnie, aby określić ikonę aplikacji, która ma być wyświetlana przez interfejs UAC, dodaj następujący klucz rejestru:
HKEY_LOCAL_MACHINE\Software\Classes\CLSID
{CLSID}
Elevation
IconReference = applicationIcon
IconReference używa tego samego formatu co LocalizedString:
@ pathtobinary-resourcenumber
Ponadto składnik COM musi być podpisany, aby można było wyświetlić ikonę.
Klasa COM musi być również oznaczona jako kompatybilna z LUA. Wymaga to następującego wpisu rejestru:
HKEY_LOCAL_MACHINE\Software\Classes\CLSID
{CLSID}
Elevation
Enabled = 1
Jeśli brakuje tego wpisu, aktywacja zwraca błąd CO_E_ELEVATION_DISABLED.
Należy pamiętać, że te wpisy muszą istnieć w gałęzi HKEY_LOCAL_MACHINE, a nie w HKEY_CURRENT_USER lub HKEY_USERS hive. Uniemożliwia to użytkownikom podniesienie klas COM, do których zarejestrowania nie mieli również uprawnień.
Moniker Elevation i interfejs użytkownika Elevation
Jeśli klient jest już podwyższony, użycie znacznika podwyższenia nie spowoduje wyświetlenia UI podwyższenia.
Jak używać moniker podniesienia uprawnień
Moniker podniesienia uprawnień jest standardowym monikerem COM, podobnym do sesji, partycji lub monikerów kolejki. Kieruje żądanie aktywacji do określonego serwera z określonym poziomem podniesienia uprawnień. Identyfikator CLSID, który ma zostać aktywowany, pojawia się w ciągu identyfikacyjnym (moniker).
Moniker podniesienia uprawnień obsługuje następujące tokeny poziomu uruchamiania:
- Administrator
- Najwyższy
Składnia dla tego elementu jest następująca:
Elevation:Administrator!new:{guid}
Elevation:Highest!new:{guid}
Poprzednia składnia używa monikera "new", aby zwrócić wystąpienie klasy COM określonej przez identyfikator GUID . Należy pamiętać, że "nowy" moniker wewnętrznie używa interfejsu IClassFactory w celu uzyskania obiektu klasy, a następnie wywołuje IClassFactory::CreateInstance.
Moniker elewacji może również być użyty do uzyskania obiektu klasy, który implementuje IClassFactory. Następnie obiekt wywołujący wykonuje CreateInstance, aby uzyskać instancję obiektu. Składnia dla tego elementu jest następująca:
Elevation:Administrator!clsid:{guid}
Przykładowy kod
W poniższym przykładzie kodu pokazano, jak używać identyfikatora podniesienia uprawnień. Przyjęto założenie, że w bieżącym wątku zainicjowano już COM.
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 jest nowy w systemie Windows Vista. Pochodzi on z BIND_OPTS2.
Jedynym dodatkiem jest pole HWND, hwnd. Ten wskaźnik reprezentuje okno, które staje się właścicielem interfejsu podniesienia uprawnień, w stosownych przypadkach.
Jeśli ma wartość NULL, wywoła GetActiveWindow, aby znaleźć uchwyt okna skojarzony z bieżącym wątkiem. Ten przypadek może mieć miejsce, gdy klientem jest skrypt, który nie jest w stanie wypełnić struktury BIND_OPTS3. W takim przypadku com spróbuje użyć okna skojarzonego z wątkiem skryptu.
Nadmierna wysokośćThe-Shoulder (OTS)
Elewacja over-the-shoulder (OTS) odnosi się do sytuacji, w której klient uruchamia serwer COM z poświadczeniami administratora, a nie swoimi własnymi. (Termin "przez ramię" oznacza, że administrator obserwuje pracę klienta, gdy klient uruchamia serwer).
Ten scenariusz może spowodować problem z wywołaniami COM na serwerze, ponieważ serwer może nie wywoływać CoInitializeSecurity jawnie (czyli programowo) lub niejawnie (czyli deklaratywnie przy użyciu rejestru). ** W przypadku takich serwerów COM oblicza deskryptor zabezpieczeń, który umożliwia tylko SELF, SYSTEM i Builtin\Administrators wykonywanie wywołań COM do serwera. Ten układ nie będzie działać w scenariuszach OTS. Zamiast tego serwer musi wywołać CoInitializeSecurity, jawnie lub niejawnie, i określić listę ACL zawierającą identyfikator SID grupy INTERAKTYWNEJ i SYSTEM.
Poniższy przykład kodu przedstawia sposób tworzenia deskryptora zabezpieczeń (SD) przy użyciu identyfikatora SID grupy INTERACTIVE.
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;
}
W poniższym przykładzie kodu pokazano, jak wywołać funkcję CoInitializeSecurity niejawnie z użyciem SD z poprzedniego przykładu kodu.
// 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;
}
W poniższym przykładzie kodu pokazano, jak wywołać metodę CoInitializeSecurity jawnie przy użyciu powyższego standardu SD:
// 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 .
Uprawnienia COM i obowiązkowe etykiety dostępu
System Windows Vista wprowadza pojęcie obowiązkowych etykiet dostępu w deskryptorach zabezpieczeń. Etykieta określa, czy klienci mogą uzyskać dostęp do obiektu COM. Etykieta jest określona w części listy kontroli dostępu systemu (SACL) w deskryptorze zabezpieczeń. W systemie Windows Vista COM obsługuje etykietę SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP. SacLs w uprawnieniach COM są ignorowane w systemach operacyjnych przed Windows Vista.
W systemie Windows Vista dcomcnfg.exe nie obsługuje zmiany poziomu integralności (IL) w uprawnieniach COM. Należy ją ustawić programowo.
W poniższym przykładzie kodu pokazano, jak utworzyć deskryptor zabezpieczeń COM z etykietą, która umożliwia uruchamianie i aktywowanie żądań od wszystkich klientów o niskim poziomie integralności (Low Integrity Level). Należy pamiętać, że oznaczenia są prawidłowe dla uprawnień dotyczących uruchamiania, aktywacji oraz wywołania. W związku z tym można napisać serwer COM, który nie zezwala na uruchamianie, aktywację ani wywołania od klientów z określonym IL. Aby uzyskać więcej informacji na temat poziomów integralności, zobacz sekcję "Understanding Windows Vista's Integrity Mechanism" (Opis mechanizmu integralności systemu Windows Vista) w Understanding and Working in Protected Mode (Omówienie i praca w trybie chronionym) w programie 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;
};
Metoda CoCreateInstance i poziomy integralności
Zachowanie CoCreateInstance uległo zmianie w systemie Windows Vista, aby domyślnie zapobiec wiązaniu się klientów z niskim poziomem integralności z serwerami COM. Serwer musi jawnie zezwalać na takie powiązania, określając SACL. Zmiany CoCreateInstance są następujące:
- Podczas uruchamiania procesu serwera COM, poziom integralności (IL) w tokenie procesu serwera jest ustawiany na poziom integralności tokena klienta lub serwera, w zależności od tego, który jest niższy.
- Domyślnie COM uniemożliwia klientom z niskim IL wiązanie z działającymi instancjami dowolnych serwerów COM. Aby zezwolić na powiązanie, deskryptor zabezpieczeń uruchamiania/aktywacji serwera COM musi zawierać SACL, który określa etykietę Low IL (zobacz poprzednią sekcję, aby uzyskać przykładowy kod do stworzenia takiego deskryptora zabezpieczeń).
Serwery z podwyższonym poziomem uprawnień i rejestracje ROT
Jeśli serwer COM chce zarejestrować się w uruchomionej tabeli obiektów (ROT) i zezwolić dowolnemu klientowi na dostęp do rejestracji, musi użyć flagi ROTFLAGS_ALLOWANYCLIENT. Serwer COM "Aktywuj jako aktywator" nie może określić ROTFLAGS_ALLOWANYCLIENT, ponieważ menedżer kontroli usługi DCOM (DCOMSCM) wymusza sprawdzanie fałszu względem tej flagi. W związku z tym w systemie Windows Vista COM dodaje obsługę nowego wpisu rejestru, który umożliwia serwerowi określenie, że jego rejestracje ROT mają być udostępniane dla dowolnego klienta.
HKEY_LOCAL_MACHINE\Software\Classes\AppID
{APPID}
ROTFlags
Jedyną prawidłową wartością dla tego wpisu REG_DWORD jest:
ROTREGFLAGS_ALLOWANYCLIENT 0x1
Wpis musi istnieć w gałęzi HKEY_LOCAL_MACHINE.
Ten wpis zawiera serwer "Aktywuj jako aktywator" o tej samej funkcjonalności, którą ROTFLAGS_ALLOWANYCLIENT udostępnia serwer Uruchom jako.
Tematy pokrewne
-
zabezpieczenia w COM
-
Zrozumienie i praca w trybie chronionym w programie Internet Explorer