如何在Windows上安全地对cmd.exe Shell的命令行参数进行转义? [英] How to securely escape command line arguments for the cmd.exe shell on Windows?

查看:129
本文介绍了如何在Windows上安全地对cmd.exe Shell的命令行参数进行转义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Ok, I have a some command wich MUST be executed in shell=True mode.

os.system subprocess.Popen(...,shell = True)

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

And this command contain string substitution like: cmd = "some_secret_command {0}".format(string_from_user)

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

I want escape string_from_user variable to prevent ANY injections.

简单错误的答案:


  1. 使用 shlex.quote -错误

  1. Use shlex.quote - incorrect

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

示例:

> python -c "import sys; print(sys.argv[1])" 'file.txxt; &ls . #'
secret.txt
secret2.txt




  1. 使用转义 ^ -错误

  1. Use escape ^ - incorrect

示例:

import os

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

现在我可以使用 (空格),然后插入多个参数。

Now I can use (space) and inject more then one argument.


  1. 使用 ^ '-错误

  1. Use ^ and " or ' - incorrect

示例:

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 ,但这对我来说是不正确的。

I now about shell=False but this is incorrect for me.

推荐答案

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

The problem with quoting command lines for windows is that there are two layered parsing engines affected by your quotes. At first, there is the Shell (e.g. cmd.exe) which interprets some special characters. Then, there is the called program parsing the command line. This often happens with the CommandLineToArgvW function provided by Windows, but not always.

一般情况下,例如,将 cmd.exe 与通过 CommandLineToArgvW 解析其命令行的程序一起使用,您可以使用所描述的技术由Daniel Colascione在每个人的报价命令行参数使用错误的方式。我最初尝试将其适应Ruby,现在尝试将其转换为python。

That said, for the general case, e.g. using cmd.exe with a program parsing its command line with CommandLineToArgvW, you can use the techniques described by Daniel Colascione in Everyone quotes command line arguments the wrong way. I have originally tried to adapt this to Ruby and now try to translate this to python here.

import re

def escape_argument(arg):
    # Escape the argument for the cmd.exe shell.
    # See http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
    #
    # 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 properly parsed. 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_chars = '()%!^"<>&|'
    meta_re = re.compile('(' + '|'.join(re.escape(char) for char in list(meta_chars)) + ')')
    meta_map = { char: "^%s" % char for char in meta_chars }

    def escape_meta_chars(m):
        char = m.group(1)
        return meta_map[char]

    return meta_re.sub(escape_meta_chars, arg)

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

Applying this code, you should be able to successfully escape your parameters for the cmd.exe shell.

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

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

Note that the method is expected to quote a single complete argument. If you are collecting your argument from multiple sources, e.g., by building a string of python code to pass to the python command, you have to assemble this before passing it to 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!

这篇关于如何在Windows上安全地对cmd.exe Shell的命令行参数进行转义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆