Python3 - 为 shell 使用净化用户输入

Python3 - Sanitizing user input for shell use

我正忙着编写一个需要用户输入的 Python3 脚本,该输入用作传递给 shell 的命令的参数。

该脚本仅供受信任的内部用户使用 - 但是我宁愿准备一些应急措施以确保命令的有效执行。

示例 1:

import subprocess

user_input = '/tmp/file.txt'
subprocess.Popen(['cat', user_input])

这将输出'/tmp/file.txt'的内容

示例 2:

import subprocess

user_input = '/tmp/file.txt && rm -rf /'
subprocess.Popen(['cat', user_input])

结果(如预期):

cat: /tmp/file.txt && rm -rf /: No such file or directory

这是一种可以接受的清理输入的方法吗?根据最佳实践,除此之外我还应该做些什么吗?

您选择的方法,

import subprocess
user_input = 'string'
subprocess.Popen(['command', user_input])

非常好,因为 command 是静态的,user_input 作为 一个参数 传递给 command。只要你不做像

这样非常愚蠢的事情
subprocess.Popen(['bash', '-c', user_input])

你应该注意安全。


对于需要多个参数的命令,我建议您向用户请求多个输入,例如这样做

user_input1='file1.txt'
user_input2='file2.txt'
subprocess.Popen(['cp', user_input1, user_input2])

而不是这个

user_input="file1.txt file2.txt"
subprocess.Popen(['cp'] + user_input.split())

如果您想进一步提高安全性,您可以:

  • 明确设置 shell=False(以确保您永远不会 运行 shell 命令;这已经是当前的默认值,但默认值可能会随着时间的推移而改变):
    subprocess.Popen(['command', user_input], shell=False)
    
  • command 使用绝对路径(以防止通过 PATH 注入恶意可执行文件):
    subprocess.Popen(['/usr/bin/command', user_input])
    
  • 明确指示支持它的命令停止解析选项,例如
    subprocess.Popen(['rm', '--', user_input1, user_input2])
    
  • 尽你所能,例如cat /tmp/file.txt 可以用几行 Python 代码代替(如果这应该是一个因素,这也会增加可移植性)