Overwriting modprobe_path

A simple way to pop a shell

The kernel can request that a kernel module is loaded at runtime. If it does so, it will try to call request_module, which will spawn the modprobe tool using call_modprobe. modprobe is a userspace program that runs with root privileges, finds the required kernel module binary on filesystem and loads it.

The path to modprobe is in modprobe_path, a global variable in the kernel. We can read the value as a non-root user through /proc/sys/kernel/modprobe, with the default value being /sbin/modprobe.

If we can overwrite modprobe_path with another binary, e.g. /tmp/exec, this will be run with root privileges! That makes it very easy. To trigger modprobe, the easiest way is to execute a binary with an unknown signature:

echo -e '\xff\xff\xff\xff' > /tmp/fake
chmod +x /tmp/fake
/tmp/fake

To identify what program should be run to handle the signature, the kernel uses binfmt (code is slightly different in newer versions). This is run by request_module, but the signature must contain at least one non-printable character.

The approach, therefore is simple. First compile a /tmp/hijack with source:

int main()
{
    system("cp /usr/bin/sh /tmp/sh");
    system("chown root:root /tmp/sh");
    system("chmod 4755 /tmp/sh");
}

There are lots of possible payloads, but the end result is the same. This will copy /bin/sh to /tmp/sh and make it SUID. Now we create a file with an unknown signature:

echo -n -e '\xff\xff\xff\xff' > /tmp/fake
chmod +x /tmp/fake

Finally, overwrite modprobe_path to /tmp/hijack. When we execute /tmp/fake as a regular user, the kernel will spawn /tmp/hijack with root privileges and execute it!

Example

TODO

Last updated

Was this helpful?