Analysis of Drag and Drop security policies in IE sandbox
0x00 Preface
Internet Explorer sandbox escape is an important topic in Internet Explorer security research. One type of vulnerability uses the defects of the white list program in ElevationPolicy settings to complete sandbox escape. IE has a DragDrop policy setting similar to ElevationPolicy in the Registry, which attracts our attention. In this article, I will try to break through the security policy of the IE sandbox in various ways from the perspective of an attacker. By analyzing the obstacles encountered, to achieve detailed parsing of the IE sandbox drag-and-drop security policy.
0x01 IE sandbox dragging Policy
One type of IE sandbox escape technology is to execute arbitrary code using the White List program in ElevationPolicy. in the registry, there is a configuration similar to ElevationPolicy named DragDrop. The specific registry path is as follows:
HKLM\Software\Microsoft\Internet Explorer\Low Rights\DragDrop
As shown in:
The meaning of the DragDrop Policy value is as follows:
0: The target window is invalid DropTarget and rejected. 1: The target window is a valid DrZ container? Http://www.bkjia.com/kf/ware/vc/ "target =" _ blank "class =" keylink "> platform/y0a/platform/seq0sL/platform/wrzPwsSsyM/Platform + platform/yxL + x6rPM0PK0sL/azc/XP 87evp6jrelfu + platform/ 8qOsyOfPws28y/nKvqO6PC9wPjxwPjxpbWcgc3JjPQ = "http://www.2cto.com/uploadfile/Collfiles/20151218/20151218101509504.png" alt = "\"/>0x02 Explorer process draggingWhen you drag a file from IE to Explorer, although the value of DragDrop Policy is set to 3, IE will not pop up, but the Explorer process will pop up a prompt box, as shown in:
However, when we drag a file from IE to the tree folder structure on the sidebar of Explorer, the box does not pop up. This should be an omission in the implementation of the Explorer program. Further imagine that if we can simulate the drag-and-drop operation of the mouse in the IE sandbox, we can use this issue of Explorer to cross the security boundary of the IE sandbox.
0x03 do not drag OLE with the mouseOLE drag-and-drop is a common file drag-and-drop method. It adopts the OLE interface design method to implement the drag-and-drop function, making the drag-and-drop implementation universal and modular. OLE drag-and-drop technology includes three basic interfaces:
- IDropSource interface: indicates the source object of the drag and drop operation, implemented by the source object;
- IDropTarget interface: indicates the target object of the drag and drop operation, implemented by the target object;
- IDataObject interface: indicates the data transmitted during the drag and drop operation, which is implemented by the source object.
Describes the key components to be implemented for a complete OLE drag operation:
To simulate mouse dragging, you only need to implementIDropSource
AndIDataObject
Interface. The core of a normal OLE drag operation is calling.ole32!DoDragDrop
Function. The prototype of this function is as follows:
#!c++ HRESULTDoDragDrop( IDataObject*pDataObject, // Pointer to the data object IDropSource *pDropSource, // Pointer to the source DWORD dwOKEffect, // Effects allowed by the source DWORD *pdwEffect // Pointer to effects on the source );
The DoDragDrop parameter contains information about the drag and drop source object and the drag data. In the DoDragDrop function, the information about the drag target object is obtained through the cursor position. Next, the author provides a method to drag and drop files without using the mouse, but by simulating code.
To use the code to simulate the drag and drop operation, you need to extract the GUI operation part of the DoDragDrop function to find the function that actually performs the drag operation, directly pass the required parameters to complete the drag and drop operation. Here we useole32.dll 6.1.7601.18915
For example, describe the internal implementation of DoDragDrop.
Ole32!DoDragDrop
The main logic is as follows:
#!c++ HRESULT __stdcallDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource, DWORD dwOKEffects, LPDWORD pdwEffect) { CDragOperationdrgop; HRESULT hr; CDragOperation::CDragOperation(&drgop, pDataObj, pDropSource, dwOKEffects, pdwEffect, &hr); if ( hr>= 0 ){ while ( CDragOperation::UpdateTarget(&drgop) &&CDragOperation::DragOver(&drgop) &&CDragOperation::HandleMessages(&drgop) ) hr = CDragOperation::CompleteDrop(&drgop); } CDragOperation::~CDragOperation(&drgop); return hr; }
CDragOperation::CDragOperation
Is a constructor. Important initialization operations include:
#!c++ ole32!GetMarshalledInterfaceBuffer ole32!ClipSetCaptureForDrag -->ole32!GetPrivateClipboardWindow ole32!CreateSharedDragFormats
The following While LOOP determines the drag status and finally completes the drag by CompleteDrop. The key function call is as follows:
#!c++ ole32!CDragOperation::UpdateTarget ->ole32!CDragOperation::GetDropTarget -->ole32!PrivDragDrop ole32!CDragOperation::DragOver -->ole32!CDropTarget::DragOver -->ole32!PrivDragDrop ole32!CDragOperation::CompleteDrop -->ole32!CDropTarget::Drop -->ole32!PrivDragDrop
As you can see, the function that implements the drag-and-drop operation isole32!PrivDragDrop
By using the function offset hardcoded function address, you can call the internal function in ole32.dll. We define a DropData function to simulate mouse dragging. The input parameter is the IDataObject pointer of the target window handle and the dragged file. The main logic is as follows:
#!c++ auto DropData(HWND hwndDropTarget, IDataObject* pDataObject) { GetPrivateClipboardWindow(CLIP_CREATEIFNOTTHERE); CreateSharedDragFormats(pDataObject); void *DOBuffer = nullptr; HRESULT result = GetMarshalledInterfaceBuffer(IID_IDataObject, pDataObject, &DOBuffer); if (SUCCEEDED(result)){ DWORD dwEffect = 0; POINTL ptl = { 0, 0 }; void *hDDInfo = nullptr; HRESULT result = PrivDragDrop(hwndDropTarget, DRAGOP_ENTER, DOBuffer, pDataObject, MK_LBUTTON, ptl, &dwEffect, 0, &hDDInfo); if (SUCCEEDED(result)){ HRESULT result = PrivDragDrop(hwndDropTarget, DRAGOP_OVER, 0, 0, MK_LBUTTON, ptl, &dwEffect, 0, &hDDInfo); if (SUCCEEDED(result)){ HWND hClip = GetPrivateClipboardWindow(CLIP_QUERY); HRESULT result = PrivDragDrop(hwndDropTarget, DRAGOP_DROP, DOBuffer, pDataObject, 0, ptl, &dwEffect, hClip, &hDDInfo); } } } return result; }
The destination window handle can be obtained through the FindWindow function. Two methods are provided to encapsulate the dragged file into a DataObject and obtain its IDataObject interface pointer:
- Write your own C ++ class to implement the IDataObject interface;
- Use the implementation in the existing class library, such as MFC and Shell32, to implement the drag-and-drop interface.
The author provides methods to encapsulate files and obtain their IDataObject interfaces using the MFC class library. The implementation code is as follows:
#!c++ auto GetIDataObjectForFile(CStringfilePath) { COleDataSource* pDataSource = new COleDataSource(); IDataObject* pDataObject; UINT uBuffSize = 0; HGLOBAL hgDrop; DROPFILES* pDrop; TCHAR* pszBuff; FORMATETC fmtetc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; uBuffSize = sizeof(DROPFILES) + sizeof(TCHAR) * (lstrlen(filePath) + 2); hgDrop = GlobalAlloc(GHND " GMEM_SHARE, uBuffSize); if (hgDrop != nullptr){ pDrop = (DROPFILES*)GlobalLock(hgDrop); if (pDrop != nullptr){ pDrop->pFiles = sizeof(DROPFILES); #ifdef _UNICODE pDrop->fWide = TRUE; #endif pszBuff = (TCHAR*)(LPBYTE(pDrop) + sizeof(DROPFILES)); lstrcpy(pszBuff, (LPCTSTR)filePath); GlobalUnlock(hgDrop); pDataSource->CacheGlobalData(CF_HDROP, hgDrop, &fmtetc); pDataObject = (IDataObject *)pDataSource->GetInterface(&IID_IDataObject); }else{ GlobalFree(pDrop); pDataObject = nullptr; } }else{ GlobalFree(hgDrop); pDataObject = nullptr; } return pDataObject; }
0x04 Implementation of IE sandbox draggingWhen we drag the mouse in the IE sandbox, the IE Tab process in the sandbox will forward data to the main process outside the sandbox through ShdocvwBroker, and complete the drag and drop operation in the main process. That is to say, the true drag and drop operation is within the IE main process outside the sandbox. The function calls of the two processes are roughly as follows:
IE sub-process (in the sandbox ):
#! C ++ MSHTML! CDoc: DoDrag --> MSHTML! CDragDropManager: DoDrag --> combase! ObjectStubless -->... Send an ALPC message to the IE master Process
Main IE process:
#! C ++... Receive ALPC messages from IE sub-processes --> RPCRT4! Invoke --> IEFRAME! CShdocvwBroker: Pull mdodragdrop --> IEFRAME! CShdocvwBroker: Export mdodragdropthreadproc --> ole32! DoDragDrop
0x05 security restrictions on Drag and Drop Operations in the IE sandboxIn the IE sandbox, we can directly tune the function in the Broker. You can create an IEUserBroker by yourself, and then create a ShdocvwBroker by IEUserBroker. Then we can adjust it to the IEFRAME in the main process! CShdocvwBroker: extends mdodragdrop function. The calling method is roughly as follows:
#!c++ typedef HRESULT(__stdcall *FuncCoCreateUserBroker)(IIEUserBroker **ppBroker); IIEUserBrokerPtrCreateIEUserBroker() { HMODULE hMod = LoadLibraryW(L"iertutil.dll"); FuncCoCreateUserBrokerCoCreateUserBroker; CoCreateUserBroker = (FuncCoCreateUserBroker)GetProcAddress(hMod, (LPCSTR)58); if (CoCreateUserBroker) { IIEUserBrokerPtr broker; HRESULT ret = CoCreateUserBroker(&broker); return broker; } return nullptr; } IIEUserBrokerPtr broker = CreateIEUserBroker(); IShdocvwBroker* shdocvw; broker->BrokerCreateKnownObject(clsid_CIERecoveryStore, _uuidof(IRecoveryStore), (IUnknown**)&shdocvw); shdocvw->PerformDoDragDrop(HWND__ *,IEDataObjectWrapper *,IEDropSourceWrapper *,ulong,ulong,ulong *,long *);
The drag function calls ole32! Implemented by the DoDragDrop function, the parameters required by DoDragDrop can be passed in by the javasmdodragdrop function (refer to the parameter information of the DoDragDrop function in section 0x03 ). So far, we can go directly from the sandbox to ole32 outside the sandbox! The DoDragDrop function, and the input parameters are controllable. There are two ways to simulate the mouse drag operation:
- Use the method described in section 0x02 to directly call the internal functions of ole32.dll;
- Call the API to change the mouse position.
For the first method, because we are in the sandbox, we can only go out of the sandbox through the Broker Interface proxy and enter the process space of the main IE process. Therefore, we cannot tune the internal functions of the dll in the main process. This method is not feasible.
The second method, if we can change the mouse position, then in ole32! In the DoDragDrop function, the steps for obtaining the information of the target window through the mouse position are successfully passed to simulate the mouse drag. However, during the experiment, we found that the API cannot be used to change the mouse pointer position in the IE sandbox. The following describes the problem.
I think there are two ways to change the cursor position:
-
Use the SendInput function to simulate the mouse action. The call relationship between the SendInput function and the kernel is as follows:
#!c++ User32!SendInput -->user32!NtUserSendInput -->win32k.sys!NtUserSendInput -->win32k.sys!xxxSendInput -->win32k.sys!xxxMouseEventDirect
-
Use the SetCursorPos function to change the cursor position. The call relationships between SetCursorPos functions from user to kernel are as follows:
#!c++ user32!SetCursorPos -->user32!SetPhysicalCursorPos -->user32!NtUserCallTwoParam -->win32k.sys!NtUserCallTwoParam -->win32k.sys!zzzSetCursorPos -->win32k.sys!zzzSetCursorPosByType
Let's take a look at SendInput. If the SendInput function is called directly in the IE sandbox to change the cursor position, the 0x5 access rejection error will be returned because of IEShims. the dll hooks the SendInput function and processes it in the hook function. The specific processing function location is as follows:
#!c++ IEShims.dll!NS_InputQueueLowMIC::APIHook_SendInput -->IEFRAME!FrameUtilExports::PreSendInput -->ShimHelper::PreSendInput
This hook is easy to bypass. We can directly call NtUserSendInput. However, this function is not exported and needs to be hardcoded by function offset.
Directly call NtUserSendInput. No error is returned for this function, but the cursor position has not changed. The reason is that the failure of function calling is due to the limitation of UIPI (User Interface Privilege Isolation. The same situation also occurs when the SetCursorPos function is called.
UIPI is a new security feature added to the system from Windows Vista. It is implemented in the Windows Kernel. The specific location is as follows:
win32k!CheckAccessForIntegrityLevel
On Win8.1, the logic of this function is as follows:
#!c++ signed int __stdcallCheckAccessForIntegrityLevelEx( unsigned intCurrentProcessIntegrityLevel, intCurrentIsAppContainer, unsigned intTargetProcessIntegrityLevel, intTargetIsAppContainer) { signed int result; if (gbEnforceUIPI&&CurrentProcessIntegrityLevel<TargetProcessIntegrityLevel ) result = 0; esleif ( gbEnforceUIPI&&CurrentProcessIntegrityLevel == TargetProcessIntegrityLevel ) result = (CurrentIsAppContainer == TargetIsAppContainer || TargetIsAppContainer == -1 || CurrentIsAppContainer == -1) || SeIsParentOfChildAppContainer( gSessionId, CurrentIsAppContainer, TargetIsAppContainer); else result = 1; return result; }
This function first determines the Integrity Level of the source and target processes. If the source IL is smaller than the target IL, the system rejects the operation. If the source IL is greater than the target IL, the system permits the operation. Then, determine the AppContainer attribute. If the source and target are of the same IL and both are running in the AppContainer, determine whether the two meet the constraints of the SeIsParentOfChildAppContainer function. If the two meet the constraints, they are allowed. Otherwise, the AppContainer is den.
Note: Both ProcessIntegrityLevel and IsAppContainer parameters are obtained from the EPROCESS-> Win32Process structure, which is an internal structure. SeIsParentOfChildAppContainer is an internal function in ntoskrnl.
0x06 SummaryThis article details the security policies of the IE sandbox for drag-and-drop operations, the drag-and-drop restrictions of the IE sandbox, the problems existing in the drag-and-drop restrictions of the Explorer process, the internal principle of ole32.dll drag-and-drop implementation, the principle of IE drag-and-drop operation in the sandbox, and the specific location and implementation details of the drag-and-drop operation for security restrictions. The IE sandbox imposes effective security restrictions on drag-and-drop operations by hook specific functions in IEShims. dll and by using the UIPI feature of the system (Windows Vista or above.
0x07 references Understanding and Working in Protected Mode Internet assumerhttps: // msdn.microsoft.com/en-us/library/bb250462 OLE Drag and Drop http://www.catch22.net/tuts/ole-drag-and-drop How to Implement Drag and Drop between Your Program and assumerhttp: // www.codeproject.com/Articles/840/How-to-Implement-Drag-and-Drop-Between-Your-Progra windows vista uipi https://www.coseinc.com/en/index.php? Rt1_download&act=publication&file=vista_uipi.ppt00000 x 08 Thank youThanks to Wins0n's help on ole32 reverse;
Thanks to FlowerCode for its guidance on ideas and technical difficulties.