New issue
Advanced search Search tips
Starred by 1 user

Issue metadata

Status: Duplicate
Merged: issue 1644
Owner:
Closed: Nov 17
Cc:

Blocking:
issue 1644



Sign in to add a comment
link

Issue 1645: Windows: DfMarshal Missing Bounds Checking Elevation of Privilege

Reported by forshaw@google.com, Aug 24 Project Member

Issue description

Windows: DfMarshal Missing Bounds Checking Elevation of Privilege
Platform: Windows 10 1803 (not tested earlier, although code looks similar on Win8+)
Class: Elevation of Privilege

Note, this is a report on a single issue class in the DfMarshal unmarshaler. For background see the master issue.

Summary: The unmarshaler for Storage objects oesn’t bounds check (any?) relative pointer values leading to DoS or EoP.

Description:

To share a storage document between processes using shared memory the implementation uses relative pointers for everything and looks up the real address when needed based on the mapped base address of the section, which is stored in a special field in the TEB. In theory these relative pointers should not be outside the mapped section, however nothing ever checks that to be the case as far as I can tell. A really early example is during the initial unmarshal a call is made to validate some magic signatures in memory.

void CExposedDocFile::Unmarshal(IStream *pstm, void **ppv, unsigned int mshlflags) {
  SDfMarshalPacket dfmp;
  UnmarshalSharedMemory(&dfmp);
  CPubDocFile* doc = NULL;
  if (dfmp.pdf._p)
    doc = (CPubDocFile *)(dfmp.pdf._p + NtCurrentTeb()->ReservedForOle->SharedMemory); <-- No bounds check
  doc->Validate();
  ...
}

We can see that the pdf pointer, which comes from the marshaled SDfMarshalPacket structure is used without bounds checks and cast straight to a pointer to a CPubDocFile class. The Validate method is then called on that instance. The Validate method looks like the following:

HRESULT CPubDocFile::Validate() {
  if (this->Magic == 'FDBP' || this->Magic == 'FDPR'))
    return S_OK;
  else
    return STG_E_INVALIDHANDLE;
}

The method just derefences the this pointer which due to a lack of bounds checking can be anywhere. This typically results in crashing the system service. In fact this could be done remotely by just guessing a valid handle for any section (as IPIDs leak process IDs) as it’s the first thing the code does after unmarshaling, causing a remote service crash, but of course if you can call DCOM methods remotely you have other problems.

There are places where the results of the dereference is used to write values back so it’s almost certainly possible to have partially controlled writes. A simple example is the code has a number of places that use singly linked lists, so you should be able to get an arbitrary value written to an arbitrary location during unlink.

It’s likely that this coding pattern is through a macro and so might be able to be fixed across the board without many changes to the code. However without source code access that’s hard to tell.

Proof of Concept:

I’ve provided a PoC as a C# project, I’ve provided one solution for all issues, but separate projects for each bug. This PoC uses the Audio Server to create a shared section and sends the marshaled object to the BITS service. This abuses the CPubDocFile::Validate issue I highlighted above. It’s the simplest one to demonstrate the general class of issue.

Note I’ve only tested this on Windows 10 1803. While I expect the underlying bugs exist on other versions offsets/behaviors I’m relying on might differ. Also note that once the BITS service crashes the DCOM activator might not realize for a while and so starting COM object will take a long time. You can get around this by manually starting the BITS service if it doesn’t auto-start. A final note, as this uses the Audio Server it might not work on VMs with the sound card disabled.

1) Compile the C# project. It will need to grab NtApiDotNet from NuGet to work.
2) Run the PoC CrashServer as a normal user.
3) When requested attach a debugger to the BITS service process to see the crash.
4) Hit enter in the PoC.

Expected Result:
The marshal fails, or the code falls back to using standard marshaled object.

Observed Result:
The BITS service crashes dereferencing an invalid address.

This bug is subject to a 90 day disclosure deadline. After 90 days elapse or a patch has been made broadly available (whichever is earlier), the bug report will become visible to the public.

Example Crash Report:

0:016> g
(27d0.27e0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
coml2!CExposedDocFile::Unmarshal+0x156:
00007ff9`40b6b996 813950424446    cmp     dword ptr [rcx],46444250h ds:000001ba`f2465680=????????
0:001> !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

GetUrlPageData2 (WinHttp) failed: 12002.

KEY_VALUES_STRING: 1


TIMELINE_ANALYSIS: 1

Timeline: !analyze.Start
    Name: <blank>
    Time: 2018-08-24T20:18:30.380Z
    Diff: 380 mSec

Timeline: Dump.Current
    Name: <blank>
    Time: 2018-08-24T20:18:30.0Z
    Diff: 0 mSec

Timeline: Process.Start
    Name: <blank>
    Time: 2018-08-24T20:16:17.0Z
    Diff: 133000 mSec

Timeline: OS.Boot
    Name: <blank>
    Time: 2018-08-24T20:15:56.0Z
    Diff: 154000 mSec


DUMP_CLASS: 2

DUMP_QUALIFIER: 0

FAULTING_IP: 
coml2!CExposedDocFile::Unmarshal+156
00007ff9`40b6b996 813950424446    cmp     dword ptr [rcx],46444250h

EXCEPTION_RECORD:  (.exr -1)
ExceptionAddress: 00007ff940b6b996 (coml2!CExposedDocFile::Unmarshal+0x0000000000000156)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 0000000000000000
   Parameter[1]: 000001baf2465680
Attempt to read from address 000001baf2465680

FAULTING_THREAD:  000027e0

PROCESS_NAME:  svchost.exe

FOLLOWUP_IP: 
coml2!CExposedDocFile::Unmarshal+156
00007ff9`40b6b996 813950424446    cmp     dword ptr [rcx],46444250h

READ_ADDRESS:  000001baf2465680 

ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s.

EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s.

EXCEPTION_CODE_STR:  c0000005

EXCEPTION_PARAMETER1:  0000000000000000

EXCEPTION_PARAMETER2:  000001baf2465680

WATSON_BKT_PROCSTAMP:  a38b9ab2

WATSON_BKT_PROCVER:  10.0.17134.1

PROCESS_VER_PRODUCT:  Microsoft® Windows® Operating System

WATSON_BKT_MODULE:  coml2.dll

WATSON_BKT_MODSTAMP:  53d8837d

WATSON_BKT_MODOFFSET:  3b996

WATSON_BKT_MODVER:  10.0.17134.1

MODULE_VER_PRODUCT:  Microsoft® Windows® Operating System

BUILD_VERSION_STRING:  17134.1.amd64fre.rs4_release.180410-1804

MODLIST_WITH_TSCHKSUM_HASH:  3c724b088962f9f2d67907fd54ae42eafd29e5ae

MODLIST_SHA1_HASH:  fffd8588dda47288d29983e3d01f8bfea34cb579

NTGLOBALFLAG:  0

PROCESS_BAM_CURRENT_THROTTLED: 0

PROCESS_BAM_PREVIOUS_THROTTLED: 0

APPLICATION_VERIFIER_FLAGS:  0

PRODUCT_TYPE:  1

SUITE_MASK:  272

DUMP_TYPE:  fe

GROUP:  netsvcs

FAULTING_SERVICE_NAME:  BITS

ANALYSIS_SESSION_HOST:  ONYX

ANALYSIS_SESSION_TIME:  08-24-2018 21:18:30.0380

ANALYSIS_VERSION: 10.0.17134.1 amd64fre

THREAD_ATTRIBUTES: 
OS_LOCALE:  ENU

PROBLEM_CLASSES: 

    ID:     [0n309]
    Type:   [@ACCESS_VIOLATION]
    Class:  Addendum
    Scope:  BUCKET_ID
    Name:   Omit
    Data:   Omit
    PID:    [Unspecified]
    TID:    [0x27e0]
    Frame:  [0] : coml2!CExposedDocFile::Unmarshal

    ID:     [0n281]
    Type:   [INVALID_POINTER_READ]
    Class:  Primary
    Scope:  DEFAULT_BUCKET_ID (Failure Bucket ID prefix)
            BUCKET_ID
    Name:   Add
    Data:   Omit
    PID:    [Unspecified]
    TID:    [0x27e0]
    Frame:  [0] : coml2!CExposedDocFile::Unmarshal

    ID:     [0n353]
    Type:   [SVCHOSTGROUP]
    Class:  Mandatory
    Scope:  DEFAULT_BUCKET_ID (Failure Bucket ID prefix)
            BUCKET_ID
    Name:   Add
    Data:   Add
            String: [netsvcs]
    PID:    [0x27d0]
    TID:    [0x27e0]
    Frame:  [Unspecified]

BUGCHECK_STR:  SVCHOSTGROUP_netsvcs_APPLICATION_FAULT_INVALID_POINTER_READ

DEFAULT_BUCKET_ID:  SVCHOSTGROUP_netsvcs_INVALID_POINTER_READ

PRIMARY_PROBLEM_CLASS:  SVCHOSTGROUP_netsvcs_APPLICATION_FAULT

LAST_CONTROL_TRANSFER:  from 00007ff940b6da50 to 00007ff940b6b996

STACK_TEXT:  
0000009d`78e7d0f0 00007ff9`40b6da50 : 00000000`00000000 0000009d`78e7d300 00000000`00000000 0000009d`78e7d760 : coml2!CExposedDocFile::Unmarshal+0x156
0000009d`78e7d290 00007ff9`4196509b : 000001ba`d6423950 00000000`00000001 0000009d`78e7d430 000001ba`d6423950 : coml2!DfUnMarshalInterface+0x198
0000009d`78e7d330 00007ff9`41ab7527 : 00000000`00000000 00000000`00000000 0000009d`78e7d868 000001ba`d6470168 : combase!_CoUnmarshalInterface+0x4ab
0000009d`78e7d680 00007ff9`41a4e5b9 : 00000000`00000000 0000009d`78e7d868 00400000`00000100 00007ff9`41a4e454 : combase!CObjServer::GetPersistentInstance+0x247
0000009d`78e7d7f0 00007ff9`412146f3 : 00000000`00000004 0000009d`78e7ded0 00007ff9`41989a60 000001ba`d64ff590 : combase!CObjServer::CreateInstance+0xc4b59
0000009d`78e7d9d0 00007ff9`411c2829 : 00007ff9`41b86612 000001ba`d7ae7d70 0000009d`78e7deb0 00000000`00000004 : RPCRT4!Invoke+0x73
0000009d`78e7da30 00007ff9`411c5553 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : RPCRT4!NdrStubCall2+0x9e9
0000009d`78e7e100 00007ff9`419b3942 : 00000000`00000000 0000009d`78e7e300 00000000`00000000 000001ba`d64fa770 : RPCRT4!NdrStubCall3+0xe3
0000009d`78e7e160 00007ff9`4194e80b : 00000000`00000001 000001ba`d7aa0158 00000412`9defddb2 00000000`00000000 : combase!CStdStubBuffer_Invoke+0x62
0000009d`78e7e1a0 00007ff9`4194e485 : 00000000`00000000 0000009d`78e7e2a0 0000009d`78e7e250 00000000`00000000 : combase!ObjectMethodExceptionHandlingAction<<lambda_76d9e92c799d246a4afbe64a2bf5673d> >+0x4b
0000009d`78e7e200 00007ff9`4194ef06 : 00000000`00000000 00000000`00000000 000001ba`d64fa770 00000000`00000000 : combase!DefaultStubInvoke+0x295
0000009d`78e7e380 00007ff9`4194aae8 : 00000000`00000000 00000000`00000010 000001ba`d7ae7d70 000001ba`d6423a28 : combase!ServerCall::ContextInvoke+0x496
0000009d`78e7e7b0 00007ff9`41949fcc : 000001ba`d6423950 000001ba`d6457c40 000001ba`d64fa770 000001ba`d647edc0 : combase!AppInvoke+0x328
0000009d`78e7e8c0 00007ff9`41942f00 : 000001ba`d6423950 000001ba`d7aa00d0 000001ba`d6423950 000001ba`d7aa00d0 : combase!ComInvokeWithLockAndIPID+0x59c
0000009d`78e7eb50 00007ff9`411af914 : 00000412`9defce62 00000000`00000000 000001ba`d7a73670 00007ff9`41b234c0 : combase!ThreadInvoke+0x1320
0000009d`78e7f4b0 00007ff9`411aea78 : 0000009d`78e7f708 000001ba`d644a358 0000009d`78e7f6d0 0000009d`78e7f708 : RPCRT4!DispatchToStubInCNoAvrf+0x24
0000009d`78e7f500 00007ff9`411af554 : 000001ba`d7a73724 00000000`00000000 00000000`00000000 00000000`00000000 : RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x1d8
0000009d`78e7f5d0 00007ff9`411b834d : 00000000`0000000d 00001100`00001100 00000000`00000000 000001ba`d644df20 : RPCRT4!RPC_INTERFACE::DispatchToStubWithObject+0x154
0000009d`78e7f670 00007ff9`411b8f0c : 00000000`0004f055 00000000`00000002 0000009d`78e7f819 000001ba`d7aee3e0 : RPCRT4!LRPC_SCALL::DispatchRequest+0x18d
0000009d`78e7f750 00007ff9`411b4d6d : 00000000`00000016 000001ba`d644df20 00000000`00000000 000001ba`e0110000 : RPCRT4!LRPC_SCALL::HandleRequest+0x86c
0000009d`78e7f870 00007ff9`411b646d : 00000000`00000000 000001ba`d643a490 00000000`00000001 0000009d`78e7fa10 : RPCRT4!LRPC_ADDRESS::HandleRequest+0x33d
0000009d`78e7f910 00007ff9`411d9318 : 000001ba`d64f2c40 0000009d`78e7fcd8 00007ff9`41293c14 00000000`00000000 : RPCRT4!LRPC_ADDRESS::ProcessIO+0x8ad
0000009d`78e7fa50 00007ff9`41f50c8e : 0000009d`78e7faf0 00000000`00000000 0000009d`78e7fcd8 000001ba`d643a670 : RPCRT4!LrpcIoComplete+0xd8
0000009d`78e7faf0 00007ff9`41f4f578 : 00000000`00000000 000001ba`d640d900 00000000`00000000 00000000`00000000 : ntdll!TppAlpcpExecuteCallback+0x22e
0000009d`78e7fb70 00007ff9`40c03034 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!TppWorkerThread+0x258
0000009d`78e7fe60 00007ff9`41fa1431 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x14
0000009d`78e7fe90 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21
 

Comment 1 by forshaw@google.com, Aug 24

Project Member
Blocking: 1644

Comment 2 by forshaw@google.com, Aug 29

Project Member
Labels: MSRC-47436

Comment 3 by taviso@google.com, Sep 28

Project Member
Blockedon: 1682

Comment 4 by taviso@google.com, Sep 28

Project Member
Blockedon: -1682

Comment 5 by forshaw@google.com, Nov 17

Project Member
Mergedinto: 1644
Status: Duplicate (was: New)
Marking as a duplicate of the master issue as only one fix was issue for all the bugs.

Comment 6 by forshaw@google.com, Nov 20

Project Member
Labels: -Restrict-View-Commit

Sign in to add a comment