python - 如何在 Windows 上安全地转义 cmd.exe shell 的命令行参数?

标签 python windows cmd

好的,我有一些命令必须在 shell=True 模式下执行。

os.systemsubprocess.Popen(..., shell=True)

此命令包含字符串替换,例如:cmd = "some_secret_command {0}".format(string_from_user)

我想转义 string_from_user 变量以防止任何注入(inject)。

简单的错误答案:

  1. 使用 shlex.quote - 不正确

print(shlex.quote('file.txxt; &ls . #')) -> 'file.txxt; &ls。 #'(注入(inject))

例子:

> python -c "import sys; print(sys.argv[1])" 'file.txxt; &ls . #'
secret.txt
secret2.txt
  1. 使用转义 ^ - 不正确

例子:

import os

CMD = '''string with spaces'''.replace('', '^').replace('^"', '')
os.system('python -c "import sys; print(sys.argv[1])" {0}'.format(CMD))

现在我可以使用 (空格)并注入(inject)不止一个参数。

  1. 使用 ^"' - 不正确

例子:

import os

CMD = '''some arg with spaces'''.replace('', '^').replace('^"', '')
os.system('python -c "import sys; print(sys.argv[1])" "{0}"'.format(CMD))

打印 ^s^o^m^e^ ^a^r^g^ ^w^i^t^h^ ^s^p^a^c^e^s^

如果 '

import os

CMD = '''some spaces'''.replace('', '^').replace('^\'', '')
os.system('python -c "import sys; print(sys.argv[1])" \'{0}\''.format(CMD))

打印'some

我现在关于 shell=False 但这对我来说是不正确的。

最佳答案

在 Windows 中引用命令行的问题在于,有两个分层的解析引擎会受到您的引用的影响。首先,有解释一些特殊字符的 Shell(例如 cmd.exe)。然后是被调用的程序解析命令行。 Windows 提供的 CommandLineToArgvW 函数经常会发生这种情况,但并非总是如此。

也就是说,对于一般情况,例如将 cmd.exe 与使用 CommandLineToArgvW 解析其命令行的程序一起使用,您可以使用 Daniel Colascione 在 Everyone quotes command line arguments the wrong way 中描述的技术.我最初尝试将其改编为 Ruby,现在尝试在此处将其转换为 Python。

import re

def escape_argument(arg):
    # Escape the argument for the cmd.exe shell.
    # See https://learn.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way
    #
    # First we escape the quote chars to produce a argument suitable for
    # CommandLineToArgvW. We don't need to do this for simple arguments.
  
    if not arg or re.search(r'(["\s])', arg):
        arg = '"' + arg.replace('"', r'\"') + '"'
  
    return escape_for_cmd_exe(arg)

def escape_for_cmd_exe(arg):
    # Escape an argument string to be suitable to be passed to
    # cmd.exe on Windows
    #
    # This method takes an argument that is expected to already be properly
    # escaped for the receiving program to be parsed by it. This argument
    # will be further escaped to pass the interpolation performed by cmd.exe
    # unchanged.
    #
    # Any meta-characters will be escaped, removing the ability to e.g. use
    # redirects or variables.
    #
    # @param arg [String] a single command line argument to escape for cmd.exe
    # @return [String] an escaped string suitable to be passed as a program
    #   argument to cmd.exe

    meta_re = re.compile(r'([()%!^"<>&|])')
    return meta_re.sub('^\1', arg)

应用此代码,您应该能够成功转义 cmd.exe shell 的参数。

print escape_argument('''some arg with spaces''')
# ^"some arg with spaces^"

请注意,该方法应该引用一个完整的参数。如果您从多个来源收集参数,例如,通过构建一串 python 代码传递给 python 命令,则必须在将其传递给 escape_argument 之前对其进行组装。

import os

CMD = '''string with spaces and &weird^ charcters!'''
os.system('python -c "import sys; print(sys.argv[1])" {0}'.format(escape_argument(CMD)))
# string with spaces and &weird^ charcters!

关于python - 如何在 Windows 上安全地转义 cmd.exe shell 的命令行参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29213106/

相关文章:

python - 对派生类中的 self 以及与基类成员变量的关系感到困惑

c++ - 如何处理覆盖某些函数名称的 WinAPI 宏?

android - 笔记本电脑无法ping通安卓设备

windows - 在 Windows 上使用 PHP 通过中继发送邮件

batch-file - 如何跳过批处理文件中发现的错误并继续执行命令行?

python - 请求响应的 Xpath 返回空列表

Python在循环执行其他代码时捕获用户输入?

python - 获取 pdb 中的最后一个异常

windows - 从 cmd.exe 或 Windows Run 运行命令的区别

c# - 在 process.startinfo.arguments 中添加/C 开关后,Cmd.exe 进程不会启动隐藏