Name:Linux Dirty Frag Kernel Privilege Escalation id:517e7bf8-d0aa-46ac-80e1-f9f498944b71 version:1 date:None author:Axsel Riando Soplanit, Alexander Wijaya, Matthew Roytua, Muhammad Rafdi Aufar Ahmad, Brian Stevan Ambarita, Ensign Infosecurity status:production type:TTP Description:The following analytic detects exploitation of Dirty Frag (CVE-2026-43284 and CVE-2026-43500), a Linux kernel local privilege escalation vulnerability.
The exploit corrupts the kernel page cache via the IPsec ESP or RxRPC subsystems using a high-frequency splice() syscall loop, followed by a privilege transition to root in the same audit session.
This analytic anchors on the exploit-specific behavioral signature, a sustained splice() spray (50 or more calls within a 60-second window) from an unprivileged process executing from a user-writable path (/home, /tmp, /dev/shm, /var/tmp, /run/user, /root), followed within 5 minutes by execution of a set-uid binary in the same auditd session. Data_source:
| bin _time span=60s | eval user = coalesce(user, auid, AUID)
| stats count AS splice_count values(exe) AS spray_binary values(pid) AS spray_pid values(user) AS user earliest(_time) AS spray_start latest(_time) AS spray_end BY auid host ses _time
how_to_implement:This analytic requires Linux auditd telemetry forwarded to Splunk
via the Splunk_TA_nix add-on with the linux_audit sourcetype (referenced through
the linux_auditd macro).
The detection depends on two audit rule keys, both of which
are standard in the Neo23x0 recommended ruleset (https://github.com/Neo23x0/auditd)
and the existing ESCU Copy Fail analytic (Linux Auditd Copy Fail Privilege Escalation),
so no detection-specific custom keys are introduced.
PREREQUISITE 1; splice_user key.
-a always,exit -F arch=b64 -S splice -S vmsplice -F success=1 -F auid>=1000 -F auid!=unset
-k splice_user
-a always,exit -F arch=b32 -S splice -S vmsplice -F success=1 -F auid>=1000 -F auid!=unset
-k splice_user
Operators should baseline splice volume in their environment before enabling.
Hosts running heavy zero-copy I/O workloads (specific: web servers, mail transfer agents, container runtimes) may need additional filtering.
PREREQUISITE 2; process_creation key.
-a always,exit -F arch=b64 -S execve -S execveat -F auid>=1000 -F auid!=unset -k
process_creation
-a always,exit -F arch=b32 -S execve -S execveat -F auid>=1000 -F auid!=unset -k
process_creation known_false_positives:The splice volume threshold (50 calls per 60 seconds from a single process in a user-writable path) is calibrated against the V4bel public PoC, which produces 100-460 splice calls in 90 seconds depending on system state.
Legitimate user-mode workloads that may produce splice() calls (web servers, mail transfer agents, language runtimes) typically execute from system paths (/usr/sbin, /usr/bin, /usr/lib) and are excluded by the user-writable path filter.
Custom-compiled applications, developer test binaries, or container runtimes executing from /home or /tmp could theoretically reach the volume threshold during legitimate I/O-heavy workloads (large file copies, log rotation, archive operations).
Operators should baseline splice volume in their environment before enabling as a notable event. If false positives occur, add an allowlist of trusted binary paths via the linux_dirty_frag_kernel_privilege_escalation_filter macro, or raise the splice_count threshold based on observed legitimate-workload baseline. References: -https://www.cve.org/CVERecord?id=CVE-2026-43284 -https://www.cve.org/CVERecord?id=CVE-2026-43500 -https://www.cve.org/CVERecord?id=CVE-2026-31431 -https://github.com/V4bel/dirtyfrag -https://www.openwall.com/lists/oss-security/2026/05/07/8 -https://www.microsoft.com/en-us/security/blog/2026/05/08/active-attack-dirty-frag-linux-vulnerability-expands-post-compromise-risk/ -https://attack.mitre.org/techniques/T1068/ -https://attack.mitre.org/techniques/T1548/001/ drilldown_searches: name:'View the detection results for - "$dest$" and "$user$"' search:'%original_detection_search% | search dest = "$dest$" user = "$user$"' earliest_offset:'$info_min_time$' latest_offset:'$info_max_time$' name:'View risk events for the last 7 days for - "$dest$" and "$user$"' search:'| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$dest$", "$user$") | stats count min(_time) as firstTime max(_time) as lastTime values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories) as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic) as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`' earliest_offset:'7d' latest_offset:'0' analytic_story:['Linux Privilege Escalation']