作为对
mklement0的精彩回答的补充:
几乎所有可执行文件都接受
\"
作为转义符号来表示
"
。然而,在cmd中安全使用这种方法几乎只有通过DELAYEDEXPANSION才能实现。
如果要将一个字面上的
"
发送到某个进程,则需要将
\"
赋值给一个环境变量,然后在需要传递引号的地方使用该变量。例如:
SETLOCAL ENABLEDELAYEDEXPANSION
set q=\"
child "malicious argument!q!&whoami"
注意
SETLOCAL ENABLEDELAYEDEXPANSION
似乎仅在批处理文件中起作用。要在交互式会话中启用 DELAYEDEXPANSION,请启动
cmd /V:ON
。
如果您的批处理文件无法使用 DELAYEDEXPANSION,则可以暂时启用它:
::region without DELAYEDEXPANSION
SETLOCAL ENABLEDELAYEDEXPANSION
::region with DELAYEDEXPANSION
set q=\"
echoarg.exe "ab !q! & echo danger"
ENDLOCAL
::region without DELAYEDEXPANSION
如果您想从包含转义引号的变量中传递动态内容,可以在扩展时使用
\"
替换
""
。
SETLOCAL ENABLEDELAYEDEXPANSION
foo.exe "danger & bar=region with !dynamic_content:""=\"! & danger"
ENDLOCAL
这种替换方式不安全,不能与
%...%
样式扩展一起使用!
如果遇到 OP,则 bash -c "g++-linux-4.1 !v_params:"=\"!"
是安全版本。
如果由于某些原因暂时无法启用DELAYEDEXPANSION,可以继续阅读以下内容:
在cmd中使用
\"
会更加安全,如果总是需要转义特殊字符的话。 (如果保持一致,就不太可能忘记插入一个脱字符...)
为了实现这个目标,在引号前面加上一个脱字符 (
^"
),作为字面值传递给子进程的引号必须额外用反斜杠进行转义 (
\^"
)。所有shell元字符也必须用
^
进行转义,例如:
&
=>
^&
;
|
=>
^|
;
>
=>
^>
; 等等。
示例:
child ^"malicious argument\^"^&whoami^"
来源:每个人都错误地引用命令行参数,请参阅“更好的引用方法”
为了传递动态内容,需要确保以下几点:
包含变量的命令部分必须被 cmd.exe
“引用”(如果变量中包含引号,则无法实现 - 不要写成 %var:""=\"%
)。为了实现这一点,在变量之前的最后一个 "
和变量之后的第一个 "
不应该进行 ^
转义。在这两个 "
之间的 cmd 元字符不得转义。例如:
foo.exe ^"danger ^& bar=\"region with %dynamic_content% & danger\"^"
如果%dynamic_content%
中包含不匹配的引号,那么这是不安全的。
^
是转义字符;在双引号字符串中,则被视为文字。 与类Unix(POSIX风格)shell不同的是,在cmd.exe
中,双引号内部的双引号没有标准化的_shell_处理方式,其解释留给被调用程序处理。 - mklement0"
字符转义为\"
(适用于至少 C/C++、Python、Perl 和 Ruby)。 相比之下,""
仅在少数情况下被识别: 在传递给批处理文件的参数中,""
被视为嵌入的双引号,但在相应的%<n>
参数中保持不变,即使通过%~<n>
去除了双引号。 Python优雅地另外也接受""
作为\"
的替代。 - mklement0