Ok, I have a some command wich MUST be executed in shell=True
mode.
好吧,我有一个必须在shell = True模式下执行的命令。
os.system
or subprocess.Popen(..., shell=True)
os.system或subprocess.Popen(...,shell = True)
And this command contain string substitution like: cmd = "some_secret_command {0}".format(string_from_user)
此命令包含字符串替换,如:cmd =“some_secret_command {0}”。format(string_from_user)
I want escape string_from_user
variable to prevent ANY injections.
我想要转义string_from_user变量来防止任何注入。
Simple wrong answers:
简单的错误答案:
- Use
shlex.quote
- incorrect
使用shlex.quote - 不正确
print(shlex.quote('file.txxt; &ls . #'))
-> 'file.txxt; &ls . #'
(injection)
print(shlex.quote('file.txxt;&ls。#')) - >'file.txxt; &ls。 #'(注射)
Example:
> python -c "import sys; print(sys.argv[1])" 'file.txxt; &ls . #'secret.txtsecret2.txt
-
Use escape
^
- incorrect
使用转义^ - 不正确
Example:
import osCMD = '''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.
现在我可以使用(空格)并注入多个参数。
- Use
^
and"
or'
- incorrect
使用^和“或” - 不正确
Example:
import osCMD = '''some arg with spaces'''.replace('', '^').replace('^"', '')os.system('python -c "import sys; print(sys.argv[1])" "{0}"'.format(CMD))
print ^s^o^m^e^ ^a^r^g^ ^w^i^t^h^ ^s^p^a^c^e^s^
打印^ s ^ o ^ m ^ e ^ ^ a ^ r ^ g ^ ^ w ^ i ^ t ^ h ^ ^ s ^ p ^ a ^ c ^ e ^ s ^
and if '
而如果 '
import osCMD = '''some spaces'''.replace('', '^').replace('^\'', '')os.system('python -c "import sys; print(sys.argv[1])" \'{0}\''.format(CMD))
print 'some
I now about shell=False
but this is incorrect for me.
我现在关于shell = False,但这对我来说是不正确的。
1 个解决方案
#1
9
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.
引用Windows命令行的问题在于有两个分层的解析引擎受到引号的影响。首先,有一个Shell(例如cmd.exe)可以解释一些特殊字符。然后,有一个被调用的程序解析命令行。这通常发生在Windows提供的CommandLineToArgvW函数中,但并非总是如此。
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.
也就是说,对于一般情况,例如,使用cmd.exe和一个用CommandLineToArgvW解析其命令行的程序,你可以使用Daniel Colascione所描述的技术在Everyone中以错误的方式引用命令行参数。我原本试图将其改编为Ruby,现在尝试将其转换为python。
import redef 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)
Applying this code, you should be able to successfully escape your parameters for the cmd.exe shell.
应用此代码,您应该能够成功转义cmd.exe shell的参数。
print escape_argument('''some arg with spaces''')# ^"some arg with spaces^"
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
.
请注意,该方法应引用一个完整的参数。如果你从多个源收集你的参数,例如,通过构建一串python代码传递给python命令,你必须在将它传递给escape_argument之前组装它。
import osCMD = '''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!
#1
9
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.
引用Windows命令行的问题在于有两个分层的解析引擎受到引号的影响。首先,有一个Shell(例如cmd.exe)可以解释一些特殊字符。然后,有一个被调用的程序解析命令行。这通常发生在Windows提供的CommandLineToArgvW函数中,但并非总是如此。
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.
也就是说,对于一般情况,例如,使用cmd.exe和一个用CommandLineToArgvW解析其命令行的程序,你可以使用Daniel Colascione所描述的技术在Everyone中以错误的方式引用命令行参数。我原本试图将其改编为Ruby,现在尝试将其转换为python。
import redef 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)
Applying this code, you should be able to successfully escape your parameters for the cmd.exe shell.
应用此代码,您应该能够成功转义cmd.exe shell的参数。
print escape_argument('''some arg with spaces''')# ^"some arg with spaces^"
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
.
请注意,该方法应引用一个完整的参数。如果你从多个源收集你的参数,例如,通过构建一串python代码传递给python命令,你必须在将它传递给escape_argument之前组装它。
import osCMD = '''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!