如果输出将发送到终端,则根据其他答案,您可能会遇到很多问题(无论您如何打印,除非您去除特殊字符)。
如果文件可能很大,攻击者可以bash
利用大量 RAM。考虑head -c 100000
而不是cat
设置 100kB 的上限。或者head -c 10000 | cat -v
(将非打印字符显示为^M
或其他;可能会破坏 UTF-8 多字节字符)。
如果您希望数据可能很大,请考虑直接运行该命令(而不是在var=$()
捕获中),并将输出cat
直接连接到您的标准输出。
由于您在 shell 变量中拥有数据,而不是eval
在双引号内进行编辑,因此您可以避免某些事情。
例如命令替换将不起作用。
peter@volta:/tmp$ foo='$(touch bar)'
peter@volta:/tmp$ echo "${foo}"
$(touch bar)
攻击者可以通过使用 string 稍微修改输出-n
,这echo
将解释为选项而不是文字数据。
$ echo "-n" # notice that this doesn't print a newline.
$ echo "" # unlike a normal echo "" or echo with no args
$
但是 bash 的内置echo
函数并不"-n foo"
作为一种选择。它按字面意思打印:
$ echo "-nabcd"
-nabcd
由于您在双引号内扩展了 shell 变量,因此它无法成为echo 的多个参数,例如echo "-n" "leave the cursor at the end of this string"
同样-e
是不可能的,也不是危险,因为您的文件已经可以包含任意二进制数据。
/bin/echo
来自 GNU Coreutils 的选项支持一个--version
选项,因此如果您没有使用 shell 内置 echo,那么攻击者可以让您的程序打印软件版本信息。如果该输出最终以攻击者可见的形式出现,则它会披露有关目标系统的一些信息。
由于这些原因,便携式打印任意数据的建议是:
printf "%s\n" "${ATTACKERDATA}"
适用于所有 POSIX shell,不受echo
.
但请注意,这对终端漏洞没有任何作用,它只是一种无需echo
修改即可直接写入任何数据的安全方法。
在大多数 shell 中,二进制数据仍然将\0
(零字节)视为终止符,因为 bash 内部使用 C 字符串。OSexecve
接口也使用 C 字符串,但 shell 内置函数允许 shell 绕过echo
/ printf
,因此可以例如zsh
echo / printf 包含零字节的二进制数据。
顺便说一句,在 bash 中,您实际上并不需要cat
读取文件。带有重定向的命令替换让 bash 自己进行读取。
ATTACKERDATA="$(< attackerControlledFile.txt)"
但是如果你想要任何处理,比如head -c
and/or cat -v
,你应该使用一个真正的命令。