如何防止 bash 脚本中的代码/选项注入
我编写了一个名为“isinFile.sh”的小型 bash 脚本,用于检查是否可以在文件“file.txt”中找到给定脚本的第一个术语:
#!/bin/bash
FILE="file.txt"
if [ `grep -w "$1" $FILE` ]; then
echo "true"
else
echo "false"
fi
但是,运行脚本会
> ./isinFile.sh -x
破坏脚本,因为 - x
被 grep
解释为一个选项。 改进了我的脚本
#!/bin/bash
FILE="file.txt"
if [ `grep -w -- "$1" $FILE` ]; then
echo "true"
else
echo "false"
fi
因此,我使用 --
作为 grep 的参数 。现在正在运行
> ./isinFile.sh -x
false
。但是使用 --
是防止 bash 脚本中代码/选项注入的正确且唯一的方法吗?我没有在野外看到过它,只是在 ABASH:寻找中发现了它Bash 脚本中的错误。
I have written a small bash script called "isinFile.sh" for checking if the first term given to the script can be found in the file "file.txt":
#!/bin/bash
FILE="file.txt"
if [ `grep -w "$1" $FILE` ]; then
echo "true"
else
echo "false"
fi
However, running the script like
> ./isinFile.sh -x
breaks the script, since -x
is interpreted by grep
as an option.
So I improved my script
#!/bin/bash
FILE="file.txt"
if [ `grep -w -- "$1" $FILE` ]; then
echo "true"
else
echo "false"
fi
using --
as an argument to grep. Now running
> ./isinFile.sh -x
false
works. But is using --
the correct and only way to prevent code/option injection in bash scripts? I have not seen it in the wild, only found it mentioned in ABASH: Finding Bugs in Bash Scripts.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
该脚本中实际上还有另一个代码注入(或任何您想称呼的名称)错误:它只是将
grep
的输出传递给[
(又名test< /code>) 命令,并假设如果不为空则返回 true。但如果输出的长度超过一个“单词”,
[
会将其视为一个表达式并尝试对其求值。例如,假设文件包含行0 -eq 2
并且您搜索“0” -[
将判定 0 不等于 2,并且脚本尽管找到了匹配项,但仍会打印 false。解决这个问题的最佳方法是使用 Ignacio Vazquez-Abrams 的建议(由 Dennis Williamson 澄清)——这完全避免了解析问题,而且速度更快(因为
-q
使grep
在第一个匹配处停止搜索)。如果该选项不可用,另一种方法是用双引号保护输出:if [ "$(grep -w -- "$1" "$FILE")" ];然后
(请注意,我还使用 $() 而不是反引号,因为我发现它们更容易阅读,并且在 $FILE 周围加上引号,以防它包含任何有趣的内容,例如空格)。There's actually another code injection (or whatever you want to call it) bug in this script: it simply hands the output of
grep
to the[
(akatest
) command, and assumes that'll return true if it's not empty. But if the output is more than one "word" long,[
will treat it as an expression and try to evaluate it. For example, suppose the file contains the line0 -eq 2
and you search for "0" --[
will decide that 0 is not equal to 2, and the script will print false despite the fact that it found a match.The best way to fix this is to use Ignacio Vazquez-Abrams' suggestion (as clarified by Dennis Williamson) -- this completely avoids the parsing problem, and is also faster (since
-q
makesgrep
stop searching at the first match). If that option weren't available, another method would be to protect the output with double-quotes:if [ "$(grep -w -- "$1" "$FILE")" ]; then
(note that I also used $() instead of backquotes 'cause I find them much easier to read, and quotes around $FILE just in case it contains anything funny, like whitespace).防止在接下来的内容中进行这种解释——
编辑
(抱歉,我没有阅读最后一部分)。是的,这是唯一的方法。另一种方法是避免将其作为搜索的第一部分;例如
".{0}-x"
也可以工作,但很奇怪,所以eg也应该可以工作。
prevents that interpretation in what follows --
EDIT
(I did not read the last part sorry). Yes, it is the only way. The other way is to avoid it as first part of the search; e.g.
".{0}-x"
works too but it is odd., so e.g.should work too.
虽然在这种特殊情况下不适用,但可以使用另一种技术来防止以连字符开头的文件名被解释为选项:
或
Though not applicable in this particular case, another technique can be used to prevent filenames that start with hyphens from being interpreted as options:
or