Windows CSRSS message box double free

CVE-2006-6696

Public disclosure: Dec 15, 2006
Vendor patch: MS07-021

Systems affected

  • Windows 2000
  • Windows XP
  • Windows 2003
  • Windows Vista

Not affected

  • Windows NT

Overview

There is a vulnerability in the way the Windows CSRSS service processes messages sent with the NtRaiseHardError syscall. This vulnerability allows a logged on user or .NET control running in Internet Explorer to execute arbitrary code in the CSRSS.EXE process and gain SYSTEM privileges. The vulnerable code is present in Windows 2000, XP, 2003 and Vista.

The crash caused by this vulnerability was first reported by Tim Garnett, one of my coworkers at Determina. I investigated the bug and discovered that it was an exploitable vulnerability. Unfortunately, the vulnerability was independently rediscovered and disclosed a few days before we were ready to report it to Microsoft, but Tim still got credited in the MS07-021 bulletin.

Technical details

If the MB_SERVICE_NOTIFICATION flag is specified when calling the MessageBox function from the Windows API, it will use the NtRaiseHardError syscall to send a HardError message to CSRSS. This message contains the caption and text of a message box to be displayed by CSRSS on behalf of the caller. This functionality is designed to allow non-interactive services to notify the user of critical errors.

The HardError message is handled by the UserHardError function in WINSRV.DLL. It calls GetHardErrorText to read the message parameters from the address space of the sender. The GetHardErrorText function returns pointers to the caption and text of the message box. If the caption or text parameters start with the \??\ prefix, the function inexplicably frees the buffer and returns a pointer to freed memory. After the message box is closed by the user, the same buffer is freed again in the FreePhi function, resulting in a double free vulnerability.

By sending a second message to CSRSS before the user closes the first message box, it is possible to overwrite the freed memory with arbitrary data before the second free call. This allows an attacker to free a fake malloc chunk that will trigger an arbitrary 4-byte memory overwrite. The vulnerability is trivially exploitable on Windows 2000 and Windows XP before SP2, and might still be exploitable on later systems.

Proof of concept

The following piece of code is sufficient to trigger a double free in CSRSS, causing heap corruption and overwriting random memory. The most likely outcome is for the CSRSS request thread to terminate, making it impossible to start new processes or use certain Win32 API function. In some cases the CSRSS process will crash and cause a blue screen of death.

while (1) {
    MessageBoxW(NULL, L"\\??\\AAAAAAAA", L"\\??\\AAAAAAAA", MB_SERVICE_NOTIFICATION);
}

Solution

The GetHardErrorText function in WINSRV.DLL should not free the buffers with the text and caption parameters when they start with the \??\ prefix.

Credit

Discovery: Tim Garnett
Vulnerability research: Alexander Sotirov