您的位置:首页 >Python调用系统命令的风险与防范
发布于2026-02-28 阅读(0)
扫一扫,手机访问
subprocess.run() 应传入参数列表而非拼接字符串以避免shell注入;必须用shell时需用shlex.quote()转义变量,禁用os.system()等高危函数,并严格管控PATH、cwd等环境因素。

用 subprocess.run() 执行系统命令时,如果把用户输入或变量直接用 + 或 f-string 拼进命令字符串,就等于给 shell 开了后门。比如 f"ls {user_input}",用户输 ; rm -rf /,命令就变成 ls ; rm -rf / —— shell 会顺序执行。
真正安全的做法是让 subprocess 绕过 shell,把命令和参数拆成列表传进去:
subprocess.run(["ls", "-l", user_input])
这样 user_input 只会被当做一个参数值,不会触发分号、管道、重定向等 shell 特性。
shell=True,就默认不走 shell 解析,这是最有效的防护|、通配符 *),那就得自己清理输入:用 shlex.quote() 包裹每个外部变量,再拼进字符串shell=True + 字符串拼接 = 高危组合,生产环境应禁止os.system() 和 os.popen() 内部强制走 shell,且不提供参数分离接口。哪怕你只传一个变量,它也会被丢进 /bin/sh -c 执行,完全无法规避注入。
常见错误场景:日志归档脚本里写 os.system(f"tar -czf backup.tgz {target_dir}"),一旦 target_dir 是 /tmp; cat /etc/passwd,结果就是打包完还顺手把密码文件吐到终端。
Deprecated,新代码别碰subprocess.run() 的基础安全机制都绕过去了,纯属历史包袱真要依赖 shell 特性(比如 grep | awk 管道、$(date) 命令替换、~ 展开),就不能躲,但得控制风险范围。
核心原则:只让 shell 处理固定模板,所有动态部分提前转义,且限定执行环境:
import shlex
cmd = f"ls -l {shlex.quote(user_path)} | head -n 5"
subprocess.run(cmd, shell=True, check=True)
shlex.quote() 是唯一靠谱的字符串转义工具,它能处理空格、单双引号、反斜杠等各种边界情况os.path.expanduser("~") 这类函数拼路径后再进 shell,改用 pathlib.Path.home() 获取绝对路径,直接走参数列表方式subprocess.run() 调用,用 Python 处理中间数据,而不是全塞给 shell很多人只盯着命令参数,忘了 PATH 环境变量和 cwd 同样能被利用。比如设置 env={"PATH": "/tmp:/usr/bin"},再执行 ls,实际跑的可能是 /tmp/ls —— 一个恶意二进制。
同理,如果 cwd 是用户可控目录,而命令里又用了相对路径(如 ./script.sh),就可能执行到非预期文件。
env 参数时,务必基于 os.environ.copy() 修改,不要凭空构造,否则可能丢失关键变量(如 LANG)导致编码异常cwd 时,先用 pathlib.Path.resolve() 规范化路径,再检查是否在白名单目录内(比如 if not target_path.is_relative_to(allowed_root): raise ValueError)timeout 和 limit memory(通过 resource.setrlimit()),防住 fork bomb 或无限循环安全不是靠某一行代码,而是每层调用都得问一句:这个字符串最终会不会被当成代码执行?这个路径最终会不会被当成可执行目标?这种警惕感比记住所有 API 更重要。
上一篇:取消简篇收藏步骤详解
下一篇:Excel内容提取方法详解
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9