Linux bash shell注入命令的可能列表是什么?[closed]

bwleehnv  于 2022-11-16  发布在  Shell
关注(0)|答案(1)|浏览(143)

已关闭。此问题需要更多focused。当前不接受答案。
**想要改进此问题吗?**更新问题,使其仅关注editing this post的一个问题。

三年前就关门了。
Improve this question
我们正在编写一个接收参数的Linux bash shell脚本。我们希望在脚本接收可能的shell注入命令作为参数时使脚本失败。我在下面使用regex添加了一些命令。有人能给予我所有此类命令的可能列表吗?这样我们就可以避免威胁

invalid_format="(^.*[;&|].*$)|(\brmdir\b)|(\bls\b)|(rm\s-)|(\bping\b)"

if [[ $LOCAL_DIR =~ $invalid_format ]]; then

echo "Error! LOCAL_DIR cannot contain command chaining characters like ; && || or possible shell injection commands"

exit 1
0sgqnhkj

0sgqnhkj1#

不要使用黑名单。

在你的数据中明确禁止的内容的阻止列表只是邀请某人想出一个不在上面的漏洞,或者混淆他们的代码,使正则表达式无法匹配它,或者找到一个古怪的语法,你的 * 实际 * shell 支持,但阻止列表/验证程序是为之编写的。
不要打那必败之仗;相反,编写安全的代码 * 无论数据包含什么内容 *,永远不要将数据注入到可以作为代码计算和执行的上下文中。

在Shell脚本中安全使用参数

*这本身就不安全:

eval "grep -e \"$1\" /var/log/*"         ## DO NOT EVER DO THIS
eval "grep -e '$1' /var/log/*"           ## DO NOT EVER DO THIS EITHER
sh -c "grep -e \"$1\" /var/log/*"        ## DO NOT EVER DO THIS EITHER
sh -c "grep -e '$1' /var/log/*"          ## DO NOT EVER DO THIS EITHER
ssh somehost "grep -e \"$1\" /var/log/*" ## DO NOT EVER DO THIS EITHER
ssh somehost "grep -e '$1' /var/log/*"   ## DO NOT EVER DO THIS EITHER

在所有这些情况下,用户提供的值($1)都在一个上下文中使用,在该上下文中它将被shell解析为代码。在所有这些情况下,一个值因此可以运行任意命令。

*这永远是安全的

grep -e "$1" /var/log/*          ## ALWAYS DO THIS INSTEAD

即使在$1中有类似$(rm -rf ~)\'$(rm -rf ~\)'的内容,shell也不会将这些内容作为语法来计算,因此这些值本质上无法作为代码来解析。

安全生成Shell命令行

如果强制使用system()或某些等效项

*这本身就不安全:

system("grep -e \"" + input + "\" /var/log/*")       /* DO NOT EVER DO THIS */
system("grep -e '" + input + "' /var/log/*")  /* DO NOT EVER DO THIS EITHER */

*这是固有的安全:

setenv("logs_to_grep", input); /* IF YOU MUST USE system(), DO THIS INSTEAD */
system("grep -e \"$logs_to_grep\" /var/log/*")

请注意,我们根本没有将值放在传递给shell的字符串中,而是在带外将其传递到环境变量中(使用小写名称,因此它无法覆盖任何对操作系统和支持工具具有安全敏感意义的环境变量)。

从其他Shell脚本生成安全命令行

假设您需要通过SSH运行一个带有不可信输入的命令。printf %q可以帮助您:

printf -v args_q '%q ' "$@"
ssh somehost 'bash -s' <<EOF
command_with $args_q
EOF

为什么选择bash -s?为了确保bash能够解析您的args_str,因为printf %q不保证POSIX安全输出。

但更好的选择是不调用额外的Shell。

不要使用system()或任何调用sh -c的方法,而是使用直接使用execve()系统调用的语言级工具来调用脚本。例如,在Python中:

# BAD/EVIL/INSECURE
subprocess.Popen('yourscript ' + arg, shell=True)  ## DO NOT EVER DO THIS

# GOOD/SECURE
subprocess.Popen(['yourscript', arg])              ## DO THIS INSTEAD.

不要做其他不安全的事情

  • 因为你的占位符,{},替换了一个被sh解析为代码的值,所以它被解析为代码,而不是数据,不要这样做。

相反,请在带外传递数据:xargs -d $'\n' sh -c 'for arg; do something_with "$arg"; done' _(如果您的数据本来就不能包含换行符;如果不能证明这是真的,请使用NUL分隔符和xargs -0)。

  • find . -type f -exec sh -c 'something_with {}' \;--与上述xargs相同的问题,使用相同的解决方案:find . -exec sh -c 'for arg; do something_with "$arg"; done' _ {} +
  • 不要使用evalsource或其他任何解析非常数字符串的代码。您根本不应该 * 在代码中 * 使用它们。
  • 不要对文件名做假设,除非你的操作系统自己强制执行。不要在脚本中使用ls。不要用换行符分隔文件名--用NULL代替。

相关问题