使用来自外部源的输入参数生成命令行时防止脚本注入

prevent script injection when spawning command line with input arguments from external source

我有一个 python 脚本,它包装了一个 bash 命令行工具,它从外部源(环境变量)获取变量。有什么方法可以执行一些软转义以防止恶意用户在其中一个参数中执行错误代码。

例如,如果脚本看起来像这样

/bin/sh 

/usr/bin/tool ${VAR1} ${VAR2}

有人将 VAR2 设置如下

export VAR2=123 && \rm -rf /

所以它可能不会将 VAR2 视为纯输入,并执行 rm 命令。

有什么方法可以使变量不可执行并将字符串原样作为命令行工具的输入吗?

将变量 VAR1VAR2 的值作为参数传递给 /usr/bin/tool 的正确且安全的方法是:

/usr/bin/tool -- "$VAR1" "$VAR2"
  • 引号防止对字符串中的分隔符或模式匹配字符进行任何特殊处理。
  • 如果变量值以 - 字符开头,-- 应该可以防止变量值被视为选项。如果 tool 写得不好并且不接受 -- 终止命令行选项,您可能需要做其他事情。
  • 有关 shell 编程中引用的优秀信息,请参阅 Quotes - Greg's Wiki
  • Shellcheck 可以检测到很多引号丢失的情况。它可以作为在线工具或可安装程序使用。如果您想消除 shell 代码中的许多常见错误,请始终使用它。
  • 问题中代码行中的大括号是完全多余的,通常是这样。有些人误以为他们充当引号。要了解它们的用法,请参阅 When do we need curly braces around shell variables?
  • 我猜问题中的 /bin/sh#! /bin/sh shebang. Since the question was tagged bash, note that #! /bin/sh should not be used with code that includes Bashisms/bin/sh 可能不是 Bash,即使它是 Bash,当作为 /bin/sh 而不是 /bin/bash 调用时,它的行为也不同。
  • 请注意,即使您忘记了引号,问题中的代码行也不会导致变量值中嵌入的命令(如 rm -rf /)此时变为 运行。危险在于,使用变量的编写错误的代码将创建 运行 命令,这些命令以不安全的方式包含变量值。有关(仅)部分危险的解释,请参阅

为了最好地避免注入,请考虑切换到 [T]csh。 与 Bourne Shells 不同,C Shell 是“有限的”,因此指示人们采用不同的、更安全的途径来编写脚本。 C Shell 施加的“限制”使其成为最可靠的 Shell 之一。 (例如:嵌套很少甚至不可能,因此不惜一切代价防止注入;有更好的方法来实现一个人想要的。)