Condividi tramite


Moniker di elevazione COM

Il moniker di elevazione com consente alle applicazioni in esecuzione nel controllo dell'account utente di attivare classi COM con privilegi elevati. Per altre informazioni, vedere Focus on Least Privilege.For more information, see Focus on Least Privilege.

Quando usare il moniker di elevazione

Il moniker di elevazione viene usato per attivare una classe COM per eseguire una funzione specifica e limitata che richiede privilegi elevati, ad esempio la modifica della data e dell'ora di sistema.

L'elevazione richiede la partecipazione sia da una classe COM che dal relativo client. La classe COM deve essere configurata per supportare l'elevazione dei privilegi annotando la voce del Registro di sistema, come descritto nella sezione Requisiti. Il client COM deve richiedere l'elevazione dei privilegi usando il moniker di elevazione.

Il moniker di elevazione non è progettato per garantire la compatibilità delle applicazioni. Ad esempio, se si vuole eseguire un'applicazione COM legacy, ad esempio WinWord come server con privilegi elevati, è necessario configurare l'eseguibile client COM per richiedere l'elevazione dei privilegi, anziché attivare la classe dell'applicazione legacy con il moniker di elevazione dei privilegi. Quando il client COM con privilegi elevati chiama CoCreateInstance usando il CLSID dell'applicazione legacy, lo stato con privilegi elevati del client passerà al processo server.

Non tutte le funzionalità COM sono compatibili con l'elevazione dei privilegi. La funzionalità che non funzionerà include:

  • L'elevazione non passa da un client a un server COM remoto. Se un client attiva un server COM remoto con il moniker di elevazione dei privilegi, il server non verrà elevato, anche se supporta l'elevazione dei privilegi.
  • Se una classe COM con privilegi elevati usa la rappresentazione durante una chiamata COM, potrebbe perdere i privilegi elevati durante la rappresentazione.
  • Se un server COM con privilegi elevati registra una classe nella tabella degli oggetti in esecuzione (ROT), la classe non sarà disponibile per i client non con privilegi elevati.
  • Un processo con privilegi elevati tramite il meccanismo di controllo dell'account utente non carica le classi per utente durante le attivazioni COM. Per le applicazioni COM, ciò significa che le classi COM dell'applicazione devono essere installate nell'hive del Registro di sistema HKEY_LOCAL_MACHINE se l'applicazione deve essere usata sia da account con privilegi che con privilegi. Le classi COM dell'applicazione devono essere installate solo nell'hive HKEY_Uedizione Standard RS se l'applicazione non viene mai usata dagli account con privilegi.
  • Il trascinamento della selezione non è consentito da applicazioni non elevate a applicazioni con privilegi elevati.

Requisiti

Per usare il moniker di elevazione per attivare una classe COM, la classe deve essere configurata per l'esecuzione come utente di avvio o l'identità dell'applicazione 'Activate as Activator'. Se la classe è configurata per l'esecuzione in qualsiasi altra identità, l'attivazione restituisce l'errore CO_E_RUNAS_VALUE_MUST_BE_AAA.

La classe deve anche essere annotata con un nome visualizzato "descrittivo" compatibile con l'interfaccia utente multilingue.The class must be annotated with a "friendly" display name that is multilingual user interface (MUI) compatible. Per questa operazione è necessaria la voce del Registro di sistema seguente:

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

Se questa voce non è presente, l'attivazione restituisce l'errore CO_E_MISSING_DISPLAYNAME. Se il file MUI non è presente, viene restituito il codice di errore della funzione RegLoadMUIStringW.

Facoltativamente, per specificare un'icona dell'applicazione da visualizzare dall'interfaccia utente di Controllo dell'account utente, aggiungere la chiave del Registro di sistema seguente:

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

IconReference usa lo stesso formato di LocalizedString:

@pathtobinary,-resourcenumber

Inoltre, il componente COM deve essere firmato per visualizzare l'icona.

La classe COM deve anche essere annotata come LUA-Enabled. Per questa operazione è necessaria la voce del Registro di sistema seguente:

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

Se questa voce non è presente, l'attivazione restituisce l'errore CO_E_ELEVATION_DISABLED.

Si noti che queste voci devono esistere nell'hive HKEY_LOCAL_MACHINE, non nell'hive HKEY_CURRENT_Uedizione Standard R o HKEY_Uedizione Standard RS. Ciò impedisce agli utenti di elevare le classi COM che non disponevano anche dei privilegi per la registrazione.

Moniker di elevazione e interfaccia utente di elevazione

Se il client è già elevato, l'uso del moniker di elevazione non causerà la visualizzazione dell'interfaccia utente di elevazione.

Come usare il moniker di elevazione

Il moniker di elevazione è un moniker COM standard, simile ai moniker di sessione, partizione o coda. Indirizza una richiesta di attivazione a un server specificato con il livello di elevazione specificato. Il CLSID da attivare viene visualizzato nella stringa del moniker.

Il moniker di elevazione supporta i token di livello di esecuzione seguenti:

  1. Amministratore
  2. Il più alto

La sintassi per questa operazione è la seguente:

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

La sintassi precedente usa il moniker "new" per restituire un'istanza della classe COM specificata da guid. Si noti che il moniker "new" usa internamente l'interfaccia IClassFactory per ottenere un oggetto classe e quindi chiama IClassFactory::CreateInstance su di esso.

Il moniker di elevazione può essere usato anche per ottenere un oggetto classe, che implementa IClassFactory. Il chiamante chiama quindi CreateInstance per ottenere un'istanza dell'oggetto. La sintassi per questa operazione è la seguente:

Elevation:Administrator!clsid:{guid}

Codice di esempio

Nell'esempio di codice seguente viene illustrato come usare il moniker di elevazione. Si presuppone che sia già stato inizializzato COM nel thread corrente.

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 è una novità di Windows Vista. Deriva da BIND_OPTS2.

L'unica aggiunta è un campo HWND , hwnd. Questo handle rappresenta una finestra che diventa il proprietario dell'interfaccia utente elevazione, se applicabile.

Se hwnd è NULL, COM chiamerà GetActiveWindow per trovare un handle di finestra associato al thread corrente. Questo caso può verificarsi se il client è uno script, che non può compilare una struttura BIND_OPTS3. In questo caso, COM tenterà di usare la finestra associata al thread di script.

Elevazione over-the-shoulder (OTS)

L'elevazione over-the-shoulder (OTS) si riferisce allo scenario in cui un client esegue un server COM con credenziali di un amministratore anziché con le proprie credenziali. Il termine "over the shoulder" indica che l'amministratore sta controllando la spalla del client mentre il client esegue il server.

Questo scenario potrebbe causare un problema per le chiamate COM nel server, perché il server potrebbe non chiamare CoInitializeSecurity in modo esplicito (ovvero a livello di codice) o in modo implicito (ovvero, in modo dichiarativo, usando il Registro di sistema). Per tali server, COM calcola un descrittore di sicurezza che consente solo edizione Standard LF, SYSTEM e Builtin\Amministrazione istrators per effettuare chiamate COM nel server. Questa disposizione non funzionerà negli scenari OTS. Al contrario, il server deve chiamare CoInitializeSecurity, in modo esplicito o implicito, e specificare un ACL che include il SID del gruppo INTERACTIVE e SYSTEM.

L'esempio di codice seguente illustra come creare un descrittore di sicurezza (SD) con il SID del gruppo 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;
}

L'esempio di codice seguente illustra come chiamare CoInitializeSecurity in modo implicito con sd nell'esempio di codice precedente:

// 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;
}

L'esempio di codice seguente illustra come chiamare CoInitializeSecurity in modo esplicito con la sd precedente:

// 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 .

Autorizzazioni COM ed etichette di accesso obbligatorie

Windows Vista introduce la nozione di etichette di accesso obbligatorie nei descrittori di sicurezza. L'etichetta determina se i client possono ottenere l'accesso a un oggetto COM. L'etichetta viene specificata nella parte SACL (System Access Control List) del descrittore di sicurezza. In Windows Vista COM supporta l'etichetta SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP. Le licenze SAC nelle autorizzazioni COM vengono ignorate nei sistemi operativi prima di Windows Vista.

A partire da Windows Vista, dcomcnfg.exe non supporta la modifica del livello di integrità (IL) nelle autorizzazioni COM. Deve essere impostato a livello di codice.

L'esempio di codice seguente illustra come creare un descrittore di sicurezza COM con un'etichetta che consente le richieste di avvio/attivazione da tutti i client LOW IL. Si noti che le etichette sono valide per le autorizzazioni di avvio/attivazione e chiamata. Pertanto, è possibile scrivere un server COM che non consente l'avvio, l'attivazione o le chiamate dai client con un determinato IL. Per altre informazioni sui livelli di integrità, vedere la sezione "Understanding Windows Vista's Integrity Mechanism" (Informazioni sul meccanismo di integrità di Windows Vista) in Understanding and Working in Protected Mode Internet Explorer (Informazioni sul meccanismo di integrità di Windows Vista) in Understanding and Working in Protected Mode Internet Explorer (Informazioni sul meccanismo di integrità di Windows Vista).

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

Livelli di integrità e CoCreateInstance

Il comportamento di CoCreateInstance è cambiato in Windows Vista per impedire ai client LOW IL di eseguire il binding ai server COM per impostazione predefinita. Il server deve consentire in modo esplicito tali associazioni specificando SACL. Le modifiche apportate a CoCreateInstance sono le seguenti:

  1. Quando si avvia un processo del server COM, il valore IL nel token di elaborazione del server viene impostato sul token IL del client o del server, a qualsiasi livello inferiore.
  2. Per impostazione predefinita, COM impedisce ai client IL bassi di eseguire l'associazione a istanze di qualsiasi server COM. Per consentire l'associazione, il descrittore di sicurezza Launch/Activation di un server COM deve contenere un sacl che specifica l'etichetta LOW IL (vedere la sezione precedente per il codice di esempio per creare un descrittore di sicurezza di questo tipo).

Server con privilegi elevati e registrazioni ROT

Se un server COM desidera eseguire la registrazione nella tabella degli oggetti in esecuzione (ROT) e consentire a qualsiasi client di accedere alla registrazione, deve usare il flag ROTFLAGS_ALLOWANYCLIENT. Un server COM "Activate As Activator" non può specificare ROTFLAGS_ALLOWANYCLIENT perché DCOM Service Control Manager (DCOMSCM) applica un controllo spoof su questo flag. Pertanto, in Windows Vista, COM aggiunge il supporto per una nuova voce del Registro di sistema che consente al server di stabilire che le registrazioni ROT devono essere rese disponibili a qualsiasi client:

HKEY_LOCAL_MACHINE\Software\Classes\AppID
   {APPID}
      ROTFlags

L'unico valore valido per questa voce di REG_DWORD è:

ROTREGFLAGS_ALLOWANYCLIENT 0x1

La voce deve esistere nell'hive HKEY_LOCAL_MACHINE .

Questa voce fornisce un server "Activate As Activator" con la stessa funzionalità che ROTFLAGS_ALLOWANYCLIENT fornisce per un server RunAs.

Sicurezza in COM

Understanding and Working in Protected Mode Internet Explorer (Informazioni e utilizzo della modalità protetta di Internet Explorer)