在 python 中 shell=True 的子流程的净化输入

Sanitized input for subprocess with shell=True in python

我有 python 脚本,里面有代码。

...
...
p = subprocess.Popen(cmd,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     shell=True)
output, error = p.communicate()
...
...

当我运行 bandit时它给出错误。

>> Issue: [B602:subprocess_popen_with_shell_equals_true] subprocess call with shell=True identified, security issue.
   Severity: High   Confidence: High
   Location: mypackage/myfile.py:123
123                                          stderr=subprocess.PIPE,
124                                          shell=True)
125                     output, error = p.communicate()

然后我做了一些 google,发现我必须清理我的输入,使用 shlex.split and shlex.quote 我可以清理它。

我将代码更改为。

...
...
p = subprocess.Popen(shlex.split(shlex.quote(cmd)),
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     shell=True)
output, error = p.communicate()
...
...

但我仍然遇到同样的错误,当 运行 bandit -r mypackage/myfile.py

时,有什么方法可以消除此错误

So, user enter command which he want to run

如果用户已经可以 运行 包含 bash 的任何命令,则 bandit 关于 shell=True 的警告不适用。

如果只允许用户为固定命令选择一些参数,例如 grep 命令的搜索查询:

,则警告会有意义
rc = call(['grep', '-e', query, path])

无论用户指定的 query 是什么;它不会执行 运行 一些其他命令(只有 grep 是 运行)。

shell=True比较:

rc = call("grep -e '%s' '%s'" % (query, path), shell=True) #XXX don't do it

用户可以传递 query = "a' /dev/null; rm -rf '" 将产生 grep -e 'a' /dev/null; rm -rf '' 'path' 命令。

在这种情况下,

shell=True 允许用户 运行 任意命令,即使这不是故意的。它被称为 shell 注入。

您可以调用 pipes.quote(query),以避免天真的攻击,但在一般情况下它可能会失败,这就是为什么如果输入不是来自受信任的来源,则应避免 shell=True