Menu

Search for hundreds of thousands of exploits

"Microsoft Windows - DfMarshal Unsafe Unmarshaling Privilege Escalation"

Author

Exploit author

"Google Security Research"

Platform

Exploit platform

windows

Release date

Exploit published date

2018-11-20

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
Windows: DfMarshal Unsafe Unmarshaling Elevation of Privilege (Master)
Platform: Windows 10 1803 (not tested earlier, although code looks similar on Win8+)
Class: Elevation of Privilege

Note, this is the master issue report for the DfMarshal unmarshaler. Im reporting multiple, non-exhaustive, issues in this marshaler in case you decide that you want to try and fix it rather than blocking the marshaler outright.

Summary: The unmarshaler for Storage objects is complete unsafe and yet is marked as a system trusted marshaler. There are multiple ways of abusing this to unmarshaler to get privilege escalation.

Description:

Storage objects are used by different parts of the OS and Office as a structured container format for sub-streams of data. You can create a new instance using APIs such as StgCreateDocFile. Being a COM object it can be marshaled around between processes, including special support during COM activation through CoGetInstanceFromIStorage. While all the important interfaces have proxy support the object also supports custom marshaling to improve performance when marshaling either INPROC or a LOCAL context. 

The COM class DfMarshal CLSID:0000030b-0000-0000-c000-000000000046 (in coml2.dll on Windows 10, ole32.dll downlevel) implements the custom unmarshaling for storage objects. When marshaling the implementation generates the following output:

MSHFLAGS <4 bytes>
Object Type IID <16 bytes> - Either IID_IStream or IID_IStorage.
Standard Marshaled Interface <Variable> - Used if the custom marshal fails.
SDfMarshalPacket <0x70 bytes on 64 bit, 0x44 on 32 bit> - Data for the custom marshal.

The SDfMarshalPacket has the following structure, note this comes from the Windows 8.1 private symbols for OLE32.DLL which are available on the public symbol server. On Windows 10 when the code was moved to COML2.DLL the private symbols didnt move with it, however the code only seems to have had minor changes between 8.1 and 10.

struct SDfMarshalPacket
{
  CBasedPubDocFilePtr pdf;
  CBasedPubStreamPtr pst;
  CBasedSeekPointerPtr psp;
  CBasedMarshalListPtr pml;
  CBasedDFBasisPtr pdfb;
  CBasedGlobalContextPtr pgc;
  CBasedGlobalFileStreamPtr fsBase;
  CBasedGlobalFileStreamPtr fsDirty;
  CBasedGlobalFileStreamPtr fsOriginal;
  unsigned int ulHeapName;
  unsigned int cntxid;
  GUID cntxkey;
  CPerContext *ppc;
  HANDLE hMem;
};

The Ptr structures are native pointer sized values which are used as relative offsets into a shared memory section. The cntxid is the PID of the marshaling process, the hMem a handle to a section object which contains the shared allocation pool for use between processes. When the custom unmarshaling process starts the receiving process will try and open the process containing the shared memory handle (using cntxid and hMem) and duplicate it into the current process. Then it will map the section into memory and rebuild a local storage object based on the various relative pointers stored in the marshaled structure. Note that there is provision for performance improvements for in-process marshaling where cntxkey is a random GUID value which is known only to the process (its not set for cross context marshal). In that case ppc is used as a valid pointer, but ppc is always set so this leaks memory layout information to the process the object is marshaled to (not reporting this one separately). 

This will only work if the process can open the marshalling process for PROCESS_DUP_HANDLE access. This restricts this to processes at the same or higher privilege, therefore an obvious target would be unmarshaling this data from a user into a system service. Fortunately theres some protection against that, the unmarshal occurs in CSharedMemoryBlock::InitUnMarshal and looks something like the following:

int CSharedMemoryBlock::InitUnMarshal(void *hMem, 
                                      unsigned int dwProcessId, 
                                      unsigned int culCommitSize) {
  unsigned int dwCurrentSession;
  unsigned int dwSourceSession;

  ProcessIdToSessionId(dwProcessId, &dwSourceSession);
  ProcessIdToSessionId(GetCurrentProcessId(), &dwCurrentSession);
  if (dwSourceSession != dwCurrentSession)
    return E_ACCESSDENIED;
  HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, 0, dwProcessId);
  ...
}

The code contains a check that the process containing the shared section is in the same console session as the process doing the unmarshal. If theyre not in the same session then the unmarshal process will fail. Its unclear if this is a security check or whether its a reliability check, and even if its a security check its not hard to find a way around this.

One thought would be to try and use this to escape a sandbox, such as AppContainer as the sandbox process and a likely COM target would all be in the same session. While there are checks for the current process being in an AppContainer (so an AC process will never use the custom unmarshaling) there are no checks for the caller being an in AC. In fact there would be as the default HYBRID custom marshaling policy should kick in and block the custom unmarshal. However as DfMarshal is marked as a system trusted marshaler, it will still execute. It turns out that its difficult to trivially use this from a sandbox as later in the initialization an event object is opened by name (in CDfMutex::Init) from the current sessions BaseNamedObjects directory which an AC cant write to. However if some other process in the same session had already shared a storage object, creating the event _and_ the AC could read the randomly assigned name it could be hijacked. 

So were back to either abusing something like UAC elevated processes/runas on the same desktop (doable but not a security boundary) or try and bypass the check to unmarshal from a user process into a system process. The key is the knowledge that the unmarshaler will open any process we tell it to, including other services in Session 0. The code could try and query the PID of the caller through COM (and thereby through MSRPC/ALPC) but it doesnt. This means as long as we can get a writable section shared between our process and a process in session 0 we can tell the unmarshaler to look there for the section handle.

After some investigation I discovered that the Audio Service will create a writable section handle for you (actually via AUDIODG) and share it back to you when you create a rendering buffer (I didnt investigation any further). This section is large enough to copy our existing shared memory from the marshal process. We can therefore create the section, copy over the existing shared memory (or fake one from scratch) then provide the PID and handle to the system service for use in unmarshaling. We dont have to guess the handle as the handle table from NtQuerySystemInformation reports object addresses so you just match the current processs handle and the AUDIODG handles. When the system service unmarshals this it will now pass the session check, we also have to create a duplicate event object in the global BNO but a normal user has access to that.

During the unmarshal process the implementation interacts with the shared memory as an allocation region, this is where all the issues occur. In theory if you could find a system process which actually interacts with the storage object you might find some more interesting behaviors (such as getting the system service to write to arbitrary files) but everything Ill describe in other issues all occur during the unmarshal process and so can be used to target any system COM service using CoGetInstanceFromStorage. Basically the storage object code uses the shared memory section as if everything is running at the same level of trust and doesnt take any real precautions against a malicious actor which has access to the same shared section or controls the existing data.

As mentioned Im reporting 4 other issues/bug classes at the same time. This is the master issue, and potentially you can mark the others as duplicates depending on how you want to fix them. Though Id remind you that when you marked a bug as duplicate last time it didnt get fixed so perhaps exercise caution. The four issues Im reporting at the same time are:

- DfMarshal Missing Bounds Checking Elevation of Privilege
- DfMarshal Shared Allocator Elevation of Privilege
- DfMarshal Arbitrary File Delete Elevation of Privilege
- DfMarshal Handle Duplication TOCTOU Elevation of Privilege

Possible fixing ideas:

DO NOT just remove the class from the trusted marshalers list. Some COM services such as SearchIndexer runs without the EOAC_NO_CUSTOM_MARSHAL flag set.

You could query the PID of the caller in the unmarshal process and only duplicate from that process, or processes in the same session as the caller. However bear in mind that when unmarshaling during activation (through CoGetInstanceFromStorage) the caller will actually be RPCSS so this might be bypassable. Depending on how you did it this might mean that a session hopping bug (which Ive found before) would allow you to elevate privilege.

You could just rewrite the whole thing, its an incredibly bad piece of code.

You could just restrict it to a very limited set of scenarios, but again you risk bypasses due to mistakes in the checks.

Proof of Concept:

See the separate reports for PoCs for various issues I identified. The source for all PoCs is attached to this issue.


After looking again at the implementation of the unmarshaler there is a check in DfUnmarshalInterface for the caller being in an AC using the IMarshalingStream::GetMarshalingContextAttribute method which ultimately tries to impersonate the caller and check if the impersonation token is an AC or not.

Quick update on RS5, as this was also discovered internal to Microsoft (I believe). There has been changes to the unmarshaler in three ways:

1) A check is now performed on the owner of the section from its security descriptor which must now match the current process' user.
2) All classes now have a GUID associated with them which is verified before trusting the data from the shared section.
3) Addition of bounds checking on structure data size.

1 isn't that hard to bypass, although the PoC provided won't as it gets a section from the Audio Service which is running as LOCAL SERVICE. 2 and 3only matters for the cases where we we're trying to read out of bounds such as  issue 1645 . Microsoft will apparently be fixing RS5 as well and won't be backporting this changes verbatim to prior versions as it wouldn't be possible in some cases (such as 1 not working on Windows 7). This does look in many ways like a non-backported fix, even if it doesn't really fix much. Due to the opaqueness of MSRC it's hard to confirm or deny that they weren't going to fix down level at some point.

Fixed in https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2018-8550.


Proof of Concept:
https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/45893.zip
Release Date Title Type Platform Author
2020-12-02 "aSc TimeTables 2021.6.2 - Denial of Service (PoC)" local windows "Ismael Nava"
2020-12-02 "Anuko Time Tracker 1.19.23.5311 - No rate Limit on Password Reset functionality" webapps php "Mufaddal Masalawala"
2020-12-02 "Ksix Zigbee Devices - Playback Protection Bypass (PoC)" remote multiple "Alejandro Vazquez Vazquez"
2020-12-02 "Mitel mitel-cs018 - Call Data Information Disclosure" remote linux "Andrea Intilangelo"
2020-12-02 "Artworks Gallery 1.0 - Arbitrary File Upload RCE (Authenticated) via Edit Profile" webapps multiple "Shahrukh Iqbal Mirza"
2020-12-02 "ChurchCRM 4.2.0 - CSV/Formula Injection" webapps multiple "Mufaddal Masalawala"
2020-12-02 "ChurchCRM 4.2.1 - Persistent Cross Site Scripting (XSS)" webapps multiple "Mufaddal Masalawala"
2020-12-02 "DotCMS 20.11 - Stored Cross-Site Scripting" webapps multiple "Hardik Solanki"
2020-12-02 "NewsLister - Authenticated Persistent Cross-Site Scripting" webapps multiple "Emre Aslan"
2020-12-02 "IDT PC Audio 1.0.6433.0 - 'STacSV' Unquoted Service Path" local windows "Manuel Alvarez"
Release Date Title Type Platform Author
2020-12-02 "aSc TimeTables 2021.6.2 - Denial of Service (PoC)" local windows "Ismael Nava"
2020-12-02 "IDT PC Audio 1.0.6433.0 - 'STacSV' Unquoted Service Path" local windows "Manuel Alvarez"
2020-12-02 "PRTG Network Monitor 20.4.63.1412 - 'maps' Stored XSS" webapps windows "Amin Rawah"
2020-12-02 "Microsoft Windows - Win32k Elevation of Privilege" local windows nu11secur1ty
2020-12-01 "Global Registration Service 1.0.0.3 - 'GREGsvc.exe' Unquoted Service Path" local windows "Emmanuel Lujan"
2020-12-01 "Pearson Vue VTS 2.3.1911 Installer - VUEApplicationWrapper Unquoted Service Path" local windows Jok3r
2020-12-01 "Intel(r) Management and Security Application 5.2 - User Notification Service Unquoted Service Path" local windows "Metin Yunus Kandemir"
2020-12-01 "10-Strike Network Inventory Explorer 8.65 - Buffer Overflow (SEH)" local windows Sectechs
2020-12-01 "EPSON Status Monitor 3 'EPSON_PM_RPCV4_06' - Unquoted Service Path" local windows SamAlucard
2020-11-30 "YATinyWinFTP - Denial of Service (PoC)" remote windows strider
Release Date Title Type Platform Author
2020-02-10 "iOS/macOS - Out-of-Bounds Timestamp Write in IOAccelCommandQueue2::processSegmentKernelCommand()" dos multiple "Google Security Research"
2020-02-10 "usersctp - Out-of-Bounds Reads in sctp_load_addresses_from_init" dos linux "Google Security Research"
2020-01-28 "macOS/iOS ImageIO - Heap Corruption when Processing Malformed TIFF Image" dos multiple "Google Security Research"
2020-01-14 "WeChat - Memory Corruption in CAudioJBM::InputAudioFrameToJBM" dos android "Google Security Research"
2020-01-14 "Android - ashmem Readonly Bypasses via remap_file_pages() and ASHMEM_UNPIN" dos android "Google Security Research"
2019-12-18 "macOS 10.14.6 (18G87) - Kernel Use-After-Free due to Race Condition in wait_for_namespace_event()" dos macos "Google Security Research"
2019-12-16 "Linux 5.3 - Privilege Escalation via io_uring Offload of sendmsg() onto Kernel Thread with Kernel Creds" local linux "Google Security Research"
2019-12-11 "Adobe Acrobat Reader DC - Heap-Based Memory Corruption due to Malformed TTF Font" dos windows "Google Security Research"
2019-11-22 "Internet Explorer - Use-After-Free in JScript Arguments During toJSON Callback" dos windows "Google Security Research"
2019-11-22 "macOS 10.14.6 - root->kernel Privilege Escalation via update_dyld_shared_cache" local macos "Google Security Research"
2019-11-20 "iOS 12.4 - Sandbox Escape due to Integer Overflow in mediaserverd" dos ios "Google Security Research"
2019-11-20 "Ubuntu 19.10 - Refcount Underflow and Type Confusion in shiftfs" dos linux "Google Security Research"
2019-11-20 "Ubuntu 19.10 - ubuntu-aufs-modified mmap_region() Breaks Refcounting in overlayfs/shiftfs Error Path" dos linux "Google Security Research"
2019-11-11 "iMessage - Decoding NSSharedKeyDictionary can read ObjC Object at Attacker Controlled Address" dos multiple "Google Security Research"
2019-11-11 "Adobe Acrobat Reader DC for Windows - Use of Uninitialized Pointer due to Malformed OTF Font (CFF Table)" dos windows "Google Security Research"
2019-11-11 "Adobe Acrobat Reader DC for Windows - Use of Uninitialized Pointer due to Malformed JBIG2Globals Stream" dos windows "Google Security Research"
2019-11-05 "macOS XNU - Missing Locking in checkdirs_callback() Enables Race with fchdir_common()" dos macos "Google Security Research"
2019-11-05 "WebKit - Universal XSS in JSObject::putInlineSlow and JSValue::putToPrimitive" dos multiple "Google Security Research"
2019-11-05 "JavaScriptCore - Type Confusion During Bailout when Reconstructing Arguments Objects" dos multiple "Google Security Research"
2019-10-30 "JavaScriptCore - GetterSetter Type Confusion During DFG Compilation" dos multiple "Google Security Research"
2019-10-28 "WebKit - Universal XSS in HTMLFrameElementBase::isURLAllowed" dos multiple "Google Security Research"
2019-10-21 "Adobe Acrobat Reader DC for Windows - Heap-Based Buffer Overflow due to Malformed JP2 Stream (2)" dos windows "Google Security Research"
2019-10-10 "Windows Kernel - win32k.sys TTF Font Processing Pool Corruption in win32k!ulClearTypeFilter" dos windows "Google Security Research"
2019-10-10 "Windows Kernel - Out-of-Bounds Read in nt!MiParseImageLoadConfig While Parsing Malformed PE File" dos windows "Google Security Research"
2019-10-10 "Windows Kernel - Out-of-Bounds Read in nt!MiRelocateImage While Parsing Malformed PE File" dos windows "Google Security Research"
2019-10-10 "Windows Kernel - Out-of-Bounds Read in CI!HashKComputeFirstPageHash While Parsing Malformed PE File" dos windows "Google Security Research"
2019-10-10 "Windows Kernel - NULL Pointer Dereference in nt!MiOffsetToProtos While Parsing Malformed PE File" dos windows "Google Security Research"
2019-10-10 "Windows Kernel - Out-of-Bounds Read in CI!CipFixImageType While Parsing Malformed PE File" dos windows "Google Security Research"
2019-10-09 "XNU - Remote Double-Free via Data Race in IPComp Input Path" dos macos "Google Security Research"
2019-10-04 "Android - Binder Driver Use-After-Free" local android "Google Security Research"
import requests
response = requests.get('http://127.0.0.1:8181?format=json')

For full documentation follow the link above

Cipherscan. Find out which SSL ciphersuites are supported by a target.

Identify and fingerprint Web Application Firewall (WAF) products protecting a website.