Cybersecurity researchers have demonstrated a proof-of-concept (PoC) rootkit dubbed Curing that leverages a Linux asynchronous I/O mechanism called io_uring to bypass traditional system call monitoring.
This causes a “major blind spot in Linux runtime security tools,” ARMO said.
“This mechanism allows a user application to perform various actions without using system calls,” the company said in a report shared with The Hacker News. “As a result, security tools relying on system call monitoring are blind’ to rootkits working solely on io_uring.”
io_uring, first introduced in Linux kernel version 5.1 in March 2019, is a Linux kernel system call interface that employs two circular buffers called a submission queue (SQ) and a completion queue (CQ) between the kernel and an application (i.e., user space) to track the submission and completion of I/O requests in an asynchronous manner.
The rootkit devised by ARMO facilitates communication between a command-and-control (C2) server and an infected host to fetch commands and execute them without making any system calls relevant to its operations, instead making use of io_uring to achieve the same goals.
ARMO’s analysis of currently available Linux runtime security tools has revealed that both Falco and Tetragon are blind to io_uring-based operations owing to the fact that they are heavily reliant on system call hooking.
The security risks posed by io_uring have been known for some time. In June 2023, Google revealed that it decided to limit the use of the Linux kernel interface across Android, ChromeOS, and its production servers as it “provides strong exploitation primitives.”
“On the one hand, you need visibility into system calls; on the other, you need access to kernel structures and sufficient context to detect threats effectively,” Amit Schendel, Head of Security Research at ARMO, said.
“Many vendors take the most straightforward path: hooking directly into system calls. While this approach offers quick visibility, it comes with limitations. Most notably, system calls aren’t always guaranteed to be invoked. io_uring, which can bypass them entirely, is a positive and great example.”