
CVE-2020-1362 분석 문서
WalletService는 지난 패치 화요일에 권한 상승 버그를 수정했으며, 그 중 하나가 CVE-2020-1362로 지정되었습니다. 이 버그는 서비스의 경계를 벗어난(out-of-bound) 버그를 이용합니다. 여기에서 이를 악용하는 기법을 공유합니다.
walletservice.dll에서 다음 함수들의 바이너리 분석을 수행했습니다:
SetGroup 함수는 사용자가 제어하는 오프셋의 메모리에 사용자가 제어하는 데이터를 썼습니다.
signed __int64 __fastcall Wallet::WalletCustomProperty::SetGroup(__int64 this, int a2, int a3, int a4)
{
signed __int64 result; // rax
result = 0i64;
if ( a2 == 1 )
{
if ( a3 & 0xFFFFFFDF )
return 0x80070057i64;
}
else if ( a3 == 0x20 )
{
return 0x80070057i64;
}
if ( a4 == -1 )
{
*(_DWORD *)(this + 8i64 * a2 + 0x74) = 0;
*(_DWORD *)(this + 8i64 * a2 + 0x78) = 0x7FFFFFFF;
}
else
{
*(_DWORD *)(this + 8i64 * a2 + 0x74) = a3;
*(_DWORD *)(this + 8i64 * a2 + 0x78) = a4;
}
return result;
}
함수가 사용자가 제어할 수 있는 오프셋의 범위를 확인하지 않음을 알 수 있습니다. 이것이 바로 취약점이 발생하는 지점입니다.
이제 경계를 벗어나 메모리에 쓸 수 있습니다. 관찰을 통해 동일한 클래스에 BSTR을 설정하고 가져오는 함수가 있음을 알 수 있습니다:
따라서 oobw를 통해 BSTR에 대한 포인터를 쉽게 수정하여 임의 주소를 읽고 쓸 수 있는 능력을 얻을 수 있습니다.
WWW(write-what-where)를 확보하면, 힙에 있는 Wallet::WalletCustomProperty 객체의 vtable을 덮어써서 RIP를 제어할 수 있습니다. 처음에는 oobw로 직접 수정하려고 했지만, oobw가 8바이트 정렬되어 있지 않음을 발견했습니다. 따라서 경쟁 조건(race condition)을 사용하여 vtable 하이재킹을 달성하려면 두 번의 쓰기가 필요합니다. 하지만 이는 익스플로잇을 불안정하게 만들 수 있습니다. 이를 우회하는 다른 방법도 있습니다. 하지만 저희 POC에서는 다른 정보 유출 취약점(CVE-2020-1361)을 사용하여 힙 주소를 유출하고 www를 사용하여 vtable을 직접 썼습니다. 참고로, CVE-2020-1361은 정보 유출 취약점으로 표시되어 있지만, 실제로는 EOP(권한 상승)를 달성하는 데 사용될 수 있습니다. 이에 대한 writeup은 추후 작성할 예정입니다.
dxgi.dll에서 ATL::CComObject<CDXGIAdapter>::`vector deleting destructor 함수를 찾았으며, 이 함수는 임의 함수 실행에서 임의 코드 실행으로 전환하는 데 도움을 줍니다. 이 함수는 loadlibraryEx 함수를 호출하며, 전역 포인터를 loadlibraryEx의 첫 번째 매개변수로 사용합니다. 그런 다음 사용자 지정 dll을 로드하여 임의 코드 실행을 달성할 수 있습니다.
예제 POC는 POC 디렉토리에 제공됩니다.
이 취약점을 통해 중간 권한에서 NT AUTHORITY\system까지 권한 상승을 달성할 수 있습니다.
Test in Windows 10.0.18363.815, x64

Haoran Qin
Zhiniang Peng (@edwardzpeng) of Qihoo 360
2020년 4월 10일: 취약점 보고
2020년 4월 21일: MSRC 조사 및 버그 확인
2020년 7월 14일: 패치 릴리스
2020년 7월 17일: Writeup 게시