Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Cuando una aplicación de usuario solicita datos de objetos en el sistema a través de un proveedor WMI, la suplantación significa que el proveedor presenta credenciales que representan el nivel de seguridad del cliente en lugar del proveedor. La suplantación impide que un cliente obtenga acceso no autorizado a la información del sistema.
En este tema se describen las secciones siguientes:
- Registrar un proveedor para representación
- Establecer niveles de suplantación dentro de un proveedor
- Mantenimiento de los niveles de seguridad en un proveedor
- Control de mensajes denegados de acceso en un proveedor
- Informes de instancias parciales
- Informe de enumeraciones parciales
- Depuración de su código de Acceso Denegado
- Temas relacionados
WMI normalmente se ejecuta como un servicio administrativo en un nivel de seguridad alto, mediante el contexto de seguridad LocalServer. El uso de un servicio administrativo proporciona a WMI los medios para acceder a la información con privilegios. Al llamar a un proveedor para obtener información, WMI pasa su identificador de seguridad (SID) al proveedor, lo que permite al proveedor acceder a la información en el mismo nivel de seguridad alto.
Durante el proceso de inicio de la aplicación WMI, el sistema operativo Windows proporciona a la aplicación WMI el contexto de seguridad del usuario que inició el proceso. El contexto de seguridad del usuario suele ser un nivel de seguridad inferior al de LocalServer, por lo que es posible que el usuario no tenga permiso para acceder a toda la información disponible para WMI. Cuando la aplicación de usuario solicita información dinámica, WMI pasa el SID del usuario al proveedor correspondiente. Si se escribe correctamente, el proveedor intenta acceder a la información con el SID de usuario, en lugar del SID del proveedor.
Para que el proveedor suplanta correctamente la aplicación cliente, la aplicación cliente y el proveedor deben cumplir los criterios siguientes:
- La aplicación cliente debe llamar a WMI con un nivel de seguridad de conexión COM de RPC_C_IMP_LEVEL_IMPERSONATE o RPC_C_IMP_LEVEL_DELEGATE. Para obtener más información, vea Mantener la seguridad de WMI.
- El proveedor debe registrarse con WMI como proveedor de suplantación. Para obtener más información, consulte Registro de un proveedor para suplantación.
- El proveedor debe cambiar al nivel de seguridad de la aplicación cliente antes de acceder a la información con privilegios. Para obtener más información, consulte Establecer niveles de suplantación dentro de un proveedor.
- El proveedor debe controlar correctamente las condiciones de error si se deniega el acceso a esta información. Para obtener más información, consulte Control de mensajes denegados de acceso en un proveedor.
Registro de un proveedor para suplantación
WMI solo pasa el SID de una aplicación cliente a proveedores que se han registrado como proveedores de suplantación. La habilitación de un proveedor para realizar la suplantación requiere que modifique el proceso de registro del proveedor.
En el procedimiento siguiente se describe cómo registrar un proveedor para la suplantación de identidad. El procedimiento supone que ya comprende el proceso de registro. Para obtener más información sobre el proceso de registro, consulte Registro de un proveedor.
Para registrar un proveedor para representación
Establezca la propiedad ImpersonationLevel de la clase __Win32Provider que representa al proveedor en 1.
La propiedad ImpersonationLevel indica si el proveedor admite la suplantación de identidad o no. Establecer ImpersonationLevel en 0 indica que el proveedor no suplanta al cliente y realiza todas las operaciones solicitadas en el mismo contexto de usuario que WMI. Al establecer ImpersonationLevel en 1, se indica que el proveedor usa llamadas de suplantación para comprobar las operaciones realizadas en nombre del cliente.
Establezca la propiedad PerUserInitialization de la misma clase __Win32Provider en TRUE.
Nota:
Si registra un proveedor con la propiedad __Win32ProviderInitializeAsAdminFirst establecido en TRUE, el proveedor usa el token de seguridad de subproceso de nivel de administración solo durante la fase de inicialización. Aunque no se produce un error en una llamada a CoImpersonateClient , el proveedor usa el contexto de seguridad de WMI y no del cliente.
En el ejemplo de código siguiente se muestra cómo registrar un proveedor para la suplantación.
instance of __Win32Provider
{
CLSID = "{FD4F53E0-65DC-11d1-AB64-00C04FD9159E}";
ImpersonationLevel = 1;
Name = "MS_NT_EVENTLOG_PROVIDER";
PerUserInitialization = TRUE;
};
Establecer niveles de suplantación dentro de un proveedor
Si usted registra un proveedor con la propiedad de clase __Win32ProviderImpersonationLevel establecida en 1, entonces WMI llama a su proveedor para hacerse pasar por varios clientes. Para controlar estas llamadas, use las funciones COM CoImpersonateClient y CoRevertToSelf en la implementación de la interfaz IWbemServices .
La función CoImpersonateClient permite a un servidor suplantar al cliente que realizó la llamada. Al realizar una llamada a CoImpersonateClient en la implementación de IWbemServices, se permite al proveedor establecer el token de subproceso del proveedor para que coincida con el token de subproceso del cliente y, por tanto, suplantar al cliente. Si no llama a CoImpersonateClient, el proveedor ejecuta código en un nivel de seguridad de administrador, lo que crea una posible vulnerabilidad de seguridad. Si el proveedor necesita actuar temporalmente como administrador o realizar la comprobación de acceso manualmente, llame a CoRevertToSelf.
A diferencia de CoImpersonateClient, CoRevertToSelf es una función COM que controla los niveles de suplantación de subprocesos. En este caso, CoRevertToSelf cambia el nivel de suplantación a la configuración de suplantación original. En general, el proveedor es inicialmente un administrador y alterna entre CoImpersonateClient y CoRevertToSelf en función de si realiza una llamada que representa al autor de la llamada o sus propias llamadas. Es responsabilidad del proveedor realizar estas llamadas correctamente para no exponer un agujero de seguridad al usuario final. Por ejemplo, el proveedor solo debe llamar a funciones nativas de Windows dentro de la secuencia de código suplantada.
Nota:
El propósito de CoImpersonateClient y CoRevertToSelf es establecer la seguridad de un proveedor. Si determina que se ha producido un error en la suplantación, debe devolver un código de finalización adecuado a WMI a través de IWbemObjectSink::SetStatus. Para obtener más información, consulte Control de mensajes denegados de acceso en un proveedor.
Mantenimiento de los niveles de seguridad en un proveedor
Los proveedores no pueden llamar a CoImpersonateClient una vez en una implementación de IWbemServices y suponer que las credenciales de suplantación permanecen en vigor durante la duración del proveedor. En su lugar, llame a CoImpersonateClient varias veces durante el transcurso de una implementación para evitar que WMI cambie las credenciales.
La principal preocupación por establecer la suplantación para un proveedor es la reentrada. En este contexto, la reentrada es cuando un proveedor realiza una llamada a WMI para obtener información y espera hasta que WMI vuelva a llamar al proveedor. En esencia, el subproceso de ejecución deja el código de proveedor, solo para volver a escribir el código en una fecha posterior. Reentry es parte del diseño de COM, y generalmente no es un problema. Sin embargo, cuando el subproceso de ejecución entra en WMI, el subproceso toma los niveles de suplantación de WMI. Cuando el subproceso vuelve al proveedor, debe restablecer los niveles de suplantación con otra llamada a CoImpersonateClient.
Para protegerse de los agujeros de seguridad en su proveedor, debe realizar llamadas reentrantes a WMI solo mientras suplanta al cliente. Es decir, las llamadas a WMI deben realizarse después de llamar a CoImpersonateClient y antes de llamar a CoRevertToSelf. Dado que CoRevertToSelf hace que la suplantación se establezca en el nivel de usuario WMI se está ejecutando, generalmente LocalSystem, las llamadas reentrantes a WMI después de llamar a CoRevertToSelf podrían proporcionar al usuario y a cualquier proveedor llamado, muchas más funcionalidades de las que deberían tener.
Nota:
Si llama a una función del sistema u otro método de interfaz, no se garantiza que se mantenga el contexto de llamada.
Gestión de mensajes de acceso denegado en un proveedor
La mayoría de los mensajes de error de Acceso denegado aparecen cuando un cliente solicita una clase o información a la que no tiene acceso. Si el proveedor devuelve un mensaje de error de Acceso denegado a WMI y WMI lo pasa al cliente, el cliente puede deducir que existe la información. En algunas situaciones, esto puede ser una infracción de seguridad. Por lo tanto, el proveedor no debe propagar el mensaje al cliente. En su lugar, el conjunto de clases que el proveedor habría proporcionado no debe exponerse. Del mismo modo, un proveedor de instancias dinámicas debe llamar al origen de datos subyacente para determinar cómo tratar los mensajes denegados de Access. Es responsabilidad del proveedor replicar esa filosofía en el entorno de WMI. Para obtener más información, consulte Informe de instancias parciales e Informe de enumeraciones parciales.
Debe escribir y depurar su código cuando determine cómo debe manejar su proveedor los mensajes de Acceso Denegado. Durante la depuración, a menudo es conveniente distinguir entre una denegación debido a un nivel de suplantación bajo y una denegación debido a un error en tu código. Puede usar una prueba sencilla en el código para determinar la diferencia. Para obtener más información, consulte Depuración del código de acceso denegado.
Informes sobre instancias parciales
Una aparición común de un mensaje de acceso denegado es cuando WMI no puede proporcionar toda la información para rellenar una instancia. Por ejemplo, un cliente puede tener la autoridad para ver un objeto de unidad de disco duro, pero puede que no tenga autoridad para ver cuánto espacio está disponible en la propia unidad de disco duro. El proveedor debe determinar cómo controlar cualquier situación cuando el proveedor no puede rellenar completamente una instancia con propiedades debido a una infracción de acceso.
WMI no requiere una única respuesta a los clientes que tienen acceso parcial a una instancia. En su lugar, WMI versión 1.x permite al proveedor una de las siguientes opciones:
Produzca un error en toda la operación con WBEM_E_ACCESS_DENIED y no devuelva ninguna instancia.
Devuelve un objeto de error junto con WBEM_E_ACCESS_DENIED para describir el motivo de la denegación.
Devuelve todas las propiedades disponibles y rellena las propiedades no disponibles con NULL.
Nota:
Asegúrese de que el retorno de WBEM_E_ACCESS_DENIED no cree un agujero de seguridad en su entorno empresarial.
Informes de enumeraciones parciales
Otra aparición común de una infracción de acceso es cuando WMI no puede devolver toda una enumeración. Por ejemplo, un cliente puede tener acceso para ver todos los objetos de equipo de red local, pero puede que no tenga acceso para ver objetos de equipo fuera de su dominio. El proveedor debe determinar cómo controlar cualquier situación cuando no se puede completar una enumeración debido a una infracción de acceso.
Al igual que con un proveedor de instancias, WMI no requiere una única respuesta a una enumeración parcial. En su lugar, WMI versión 1.x permite a un proveedor una de las siguientes opciones:
Devuelve WBEM_S_NO_ERROR para todas las instancias a las que el proveedor puede tener acceso.
Si usa esta opción, el usuario no sabe que algunas instancias no estaban disponibles. Varios proveedores, como los que usan lenguaje de consulta estructurado (SQL) con seguridad de nivel de fila, devuelven resultados parciales correctos mediante el nivel de seguridad del autor de la llamada para definir el conjunto de resultados.
Produzca un error en toda la operación con WBEM_E_ACCESS_DENIED y no devuelva ninguna instancia.
El proveedor puede incluir opcionalmente un objeto de error que describa la situación para el cliente. Tenga en cuenta que algunos proveedores puedan acceder a las fuentes de datos de forma secuencial y es posible que no encuentren denegaciones a mitad del proceso de enumeración.
Devuelve todas las instancias a las que se puede acceder, pero también devuelve el código de estado sin error WBEM_S_ACCESS_DENIED.
El proveedor debe tener en cuenta la denegación durante la enumeración y puede continuar proporcionando instancias, terminando con el código de estado sin errores. El proveedor también puede optar por finalizar la enumeración en la primera denegación. La justificación de esta opción es que los distintos proveedores tienen distintos paradigmas de recuperación. Es posible que un proveedor ya haya entregado instancias antes de detectar una infracción de acceso. Algunos proveedores pueden optar por seguir proporcionando otras instancias y otras pueden querer finalizar.
Debido a la estructura de COM, no se puede encapsular ninguna información durante un error excepto un objeto de error. Por lo tanto, no puede devolver tanto la información como un código de error. Si decide devolver información, debe usar un código de estado sin error en su lugar.
Depuración del código de acceso denegado
Algunas aplicaciones pueden usar niveles de suplantación de identidad inferiores a RPC_C_IMP_LEVEL_IMPERSONATE. En este caso, la mayoría de las llamadas de suplantación realizadas por el proveedor para la aplicación cliente fallarán. Para diseñar e implementar correctamente un proveedor, debe tener en cuenta esta idea.
De manera predeterminada, el único otro nivel de suplantación que puede acceder a un proveedor es RPC_C_IMP_LEVEL_IDENTIFY. En los casos en los que una aplicación cliente usa RPC_C_IMP_LEVEL_IDENTIFY, CoImpersonateClient no devuelve un código de error. En su lugar, el proveedor suplanta al cliente solo con fines de identificación. Por lo tanto, la mayoría de los métodos de Windows a los que llama el proveedor devolverán un mensaje de acceso denegado. Esto es inofensivo en la práctica, ya que los usuarios no podrán hacer nada inapropiado. Sin embargo, puede ser útil durante el desarrollo del proveedor saber si el cliente realmente se ha suplantado o no.
El código requiere las siguientes referencias e instrucciones #include para compilarse correctamente.
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <wbemidl.h>
En el ejemplo de código siguiente se muestra cómo determinar si un proveedor ha suplantado correctamente una aplicación cliente.
DWORD dwImp = 0;
HANDLE hThreadTok;
DWORD dwBytesReturned;
BOOL bRes;
// You must call this before trying to open a thread token!
CoImpersonateClient();
bRes = OpenThreadToken(
GetCurrentThread(),
TOKEN_QUERY,
TRUE,
&hThreadTok
);
if (bRes == FALSE)
{
printf("Unable to read thread token (%d)\n", GetLastError());
return 0;
}
bRes = GetTokenInformation(
hThreadTok,
TokenImpersonationLevel,
&dwImp,
sizeof(DWORD),
&dwBytesReturned
);
if (!bRes)
{
printf("Unable to read impersonation level\n");
CloseHandle(hThreadTok);
return 0;
}
switch (dwImp)
{
case SecurityAnonymous:
printf("SecurityAnonymous\n");
break;
case SecurityIdentification:
printf("SecurityIdentification\n");
break;
case SecurityImpersonation:
printf("SecurityImpersonation\n");
break;
case SecurityDelegation:
printf("SecurityDelegation\n");
break;
default:
printf("Error. Unable to determine impersonation level\n");
break;
}
CloseHandle(hThreadTok);
Temas relacionados