You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Shell启动进程存在注入漏洞,如何用Bandit排查并替换commands.getoutput?

Hey there! Let's tackle your questions one by one—since you're new to security, I'll keep things clear and practical.


如何修复Shell启动进程的注入漏洞

Shell注入漏洞的核心原因是直接将用户可控的输入拼接进Shell命令中,让Shell解析了恶意输入。修复的关键思路是绕过Shell直接调用进程,或者严格处理输入:

  • 优先选择无Shell的进程调用方式:使用subprocess模块的列表参数形式,让操作系统直接执行二进制程序,参数独立传递,不会被Shell解析。
    比如原来有风险的代码:

    import subprocess
    # 危险:用户输入会被Shell解析
    subprocess.call("ls " + user_controlled_path, shell=True)
    

    修复后:

    import subprocess
    # 安全:参数独立传递,无Shell解析
    subprocess.call(["ls", user_controlled_path])
    
  • 如果必须使用Shell特性(如管道、通配符):一定要对用户输入进行严格的转义处理,使用shlex.quote()来转义所有Shell特殊字符:

    import subprocess
    import shlex
    safe_input = shlex.quote(user_controlled_input)
    subprocess.call("grep " + safe_input + " logfile.txt | wc -l", shell=True)
    

    注意:这种方式只能降低风险,依然不如无Shell的方式安全。


Python 2.7下commands库的替代方案

commands库确实存在于Python 2.7中,但它的所有方法(getoutputgetstatusoutput)都是通过Shell执行命令的,天生带有注入风险,官方也推荐用subprocess模块替代:

  • 替代commands.getoutput(cmd)
    如果可以放弃Shell,尽量用无Shell的subprocess.check_output

    import subprocess
    # 无Shell的安全方式(如果cmd不需要Shell特性)
    output = subprocess.check_output(["echo", "hello"]).strip()
    

    如果必须保留Shell(比如需要管道),可以用:

    import subprocess
    output = subprocess.check_output("echo hello | tr 'a-z' 'A-Z'", shell=True, stderr=subprocess.STDOUT).strip()
    

    但同样要注意对用户输入做转义处理。

  • 替代commands.getstatusoutput(cmd)
    可以用subprocess.Popen获取返回码和输出:

    import subprocess
    proc = subprocess.Popen(["ls", "/invalid/path"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = proc.communicate()
    return_code = proc.returncode
    # 类似commands.getstatusoutput的返回格式:(return_code, stdout + stderr)
    result = (return_code, (stdout + stderr).strip())
    

关于Bandit检测commands.getoutput存在漏洞的说明

Bandit标记commands.getoutput有漏洞,本质是因为这个方法默认通过Shell执行命令。如果你的代码中用它执行的命令包含任何用户可控的输入,攻击者就可以通过输入特殊字符(比如;|&&)来拼接恶意命令,比如:

假设代码是commands.getoutput("echo " + user_input),如果用户输入"; rm -rf /",实际执行的命令会变成echo ; rm -rf /,这会直接执行删除系统文件的恶意操作。

所以不管是commands库还是subprocessshell=True,只要命令中拼接了未处理的用户输入,都存在注入风险——这也是为什么推荐优先用无Shell的进程调用方式。


内容的提问来源于stack exchange,提问作者kRazzy R

火山引擎 最新活动