首页 > 解决方案 > Python3 - 清理作为参数传递给 shell 的用户输入

问题描述

对传递给 shell 的 user_input_parameter 进行清理的推荐方法是什么?

subprocess.Popen(['sudo', 'rm -rf', user_input_parameter])

该命令应接受所有参数,但应减轻诸如破坏命令之类的恶意活动。

标签: python-3.xsecuritysanitization

解决方案


Python的实现subprocess防止shell注入,文档是这样说的:

17.5.2. 安全注意事项

与其他一些 popen 函数不同,此实现永远不会隐式调用系统 shell。这意味着所有字符,包括 shell 元字符,都可以安全地传递给子进程。如果通过显式调用 shell,shell=True应用程序有责任确保正确引用所有空格和元字符以避免shell 注入 漏洞。

使用shell=True时,shlex.quote()函数可用于正确转义字符串中的空格和 shell 元字符,这些字符串将用于构造 shell 命令。

但是,这不会防止用户传递恶意输入 - 例如在您的情况下删除不打算删除的内容。我不会像这样直接将用户输入传递给命令 - 您应该验证您想要删除的内容是否正在被删除,而不是完全不同的东西。然而,这已经是应用程序逻辑的一部分——关于 shell 注入(中断命令)——应该可以使用subprocess.

我做了这个小例子:

#!/usr/bin/env python3

import subprocess

user_input_parameter = '/; id'
subprocess.Popen(['ls', user_input_parameter])

执行时输出:

$ python3 asdf.py
ls: /; id: No such file or directory
$

为了演示subprocess将输入作为参数传递给参数。

所有这一切只有shell=False(编写此答案时的默认值)对于subprocess方法而言才是正确的,否则您基本上启用 shell(bash 等)执行并允许在输入未正确清理时进行注入。


顺便说一句,您需要分别传递每个参数,因此您需要像这样运行它(但请不要这样做):

subprocess.Popen(['sudo', 'rm', '-rf', user_input_parameter])

推荐阅读