应使用 subprocess.run() 替代 os.system() 和 os.popen(),传入参数列表而非拼接字符串,禁用 shell=True,显式控制 env 和 cwd,并警惕 SUID 二进制与环境变量劫持风险。
使用
替代
和
和
会直接将字符串交给 shell 解析,一旦参数含用户输入,极易触发命令注入。比如
遇到
就会执行恶意命令。
正确做法是用
并传入参数列表(而非拼接字符串),让 Python 绕过 shell,直接调用程序:
关键点:
始终用
形式传参,避免
若必须用 shell 功能(如管道、通配符),则需严格过滤或转义用户输入,不推荐
比
更清晰可控
警惕
的隐式风险
即使你没显式写
,某些封装函数(如旧版
,或第三方库的 exec 函数)内部可能默认启用 shell,导致参数被重新解析。
立即学习
“
Python免费学习笔记(深入)
”;
常见踩坑场景:
调用
——
由 shell 展开,但若
来自用户,就等于放行任意文件名匹配逻辑
用
处理用户输入再传给
,却仍设
,等于白做
在 Windows 上误以为
就绝对安全,其实
的某些内置命令(如
)仍依赖 shell 行为
建议:除非明确需要 shell 特性(且已评估输入完全可信),否则一律禁用
。
elasticsearch-9.4.0 win
PHP中文网提供Elasticsearch 9.4.0 Windows 版本压缩包下载解压即用,内置 OpenJDK 无需额外配置 Java 环境。该版本重磅推出原生 Prometheus 支持、正式版 Elastic Workflows 以及基于 NVIDIA cuVS 的 GPU 加速向量索引,大幅提升 AI 检索与可观测性能力。建议前往官网下载,快速体验极速搜索与强大的数据分析功能。
下载
环境变量
与工作目录的污染风险
子进程会继承父进程的
,其中可能含敏感信息(如
、
、
),或被恶意篡改影响命令行为。
实操建议:
显式传入干净的
参数,例如
用
明确指定工作目录,避免子进程在意外路径下读写文件
对敏感命令(如涉及密钥操作的
或
),考虑用
清空环境后按需注入必要变量
权限提升与进程逃逸的实际约束
Python 进程本身权限决定子进程上限:普通用户启动的脚本,无论怎么调用
,都无法直接执行
或写入
——除非提前配置了免密 sudo 规则,而这属于系统层配置问题,不是 Python 能绕过的。
但仍有两类易被忽略的越权路径:
子进程调用的二进制本身有 SUID 位(如
),此时它以文件所有者身份运行,可能提权
通过
或
等环境变量劫持子进程加载的库或模块,间接控制行为
所以不要只盯着“命令怎么拼”,还得看“谁在跑、在哪跑、带了什么环境”。尤其在容器或共享服务器中,这些边界比语法更关键。
subprocess.run()os.system()os.popen()os.system()os.popen()os.system(f"ls {user_input}")user_input = "; rm -rf /"subprocess.run()subprocess.run(["ls", "-l", user_input]) # 安全:user_input 被当作文本参数,不会被 shell 解析listshell=Truesubprocess.run(..., capture_output=True, text=True)check_output()shell=Trueshell=Truecommands.getoutput()subprocess.run("ls *.py", shell=True)**.pyshlex.split()subprocessshell=Trueshell=Falsecmd.exedirshell=Trueos.environHOMEPATHSSH_AUTH_SOCKenvenv=dict(os.environ, PATH="/usr/bin:/bin")cwdgpgsshenv={}subprocesssudo/etc/usr/bin/passwdLD_PRELOADpythonpath