成语 `ssh ... "$(typeset -f foo); foo"` 有多安全?

成语 `ssh ... "$(typeset -f foo); foo"` 有多安全?

假设foo在当前 shell 会话中定义了某个 shell 函数。然后命令

typeset -f foo

打印出该函数的源代码。这意味着,至少在原则上,人们可以通过ssh如下所示在远程主机上执行此功能:

ssh <REMOTE-HOST> "$(typeset -f foo); foo"

(出于本问题的目的,假设 中提到的所有命令和文件系统路径foo都可用<REMOTE-HOST>。此外,假设bash两端都是 shell。)

我的直觉是,盲目地获取一些像这样自动生成的源代码将是非常脆弱的,但我无法提出foo这个习惯用法失败的函数的示例。

我的问题是:这个习语有多安全?如果它不安全,有人可以给我一个具体的例子来说明它是如何失败的吗? (安全问题包括以下内容:是否bash保证这种使用typeset -f是安全的?)

注意:在这篇文章中,我并不是在寻找替代方案;而是在寻找替代方案。我只是想了解这个特定习语的属性。


编辑:澄清这bash是两端的外壳。

答案1

如果代码没有在与生成它的语言环境相同的语言环境中解释(或者如果语言环境姓名是相同的,但 ssh 客户端主机和服务器主机之间的区域设置的定义不同)。

blank特别重要的是、alpha和类别中的字符编码和字符成员资格alnum

例如,αBIG5 字符集中的字符(希腊字母小写 alpha)被编码为 0xa3 0x5c,0x5c\在 ASCII 中(以及包括 BIG5 在内的所有字符集)。

因此,如果您foo在该字符集中定义了一个函数:

foo() {
  echo α
}

typeset -f会这样输出,但如果在不同的语言环境(如 C)中解释,则 0xa3 0x5c 不会被视为 a,α而是被视为未知的 0xa3 字符,后跟反斜杠。可以这样利用:

$ env LC_ALL=zh_TW.big5 $'BASH_FUNC_foo%%=() { echo \xa3\\\\;}; echo gotcha; }' bash -c 'typeset -f foo' | bash
gotcha
bash: line 5: syntax error near unexpected token `}'
bash: line 5: `}'

当在不同的语言环境中解释时,就foo() { echo α\;}; echo gotcha; }变成了。foo() { echo <0xa3>\\; }; echo gotcha; }

其他问题:

UTF-8 中的字符à编码为 0xc3 0xa0。在iso8859-1和其他几个iso8859字符集中,0xa0 是不间断空格字符。在某些系统上,该字符包含在空白的字符类,因此 bash 在其语法中将其作为标记分隔符。

Solaris 就是这样一个系统,其中 U+00A0 被视为空白:

$ env $'BASH_FUNC_foo%%=() { nawk -v x=àBEGIN\'{system("echo gotcha")}\' 1;}' bash -c 'typeset -f foo; echo foo'  | ssh solaris LC_ALL=en_GB.ISO8859-1 bash
gotcha

看看如何:

nawk -v x=àBEGIN... 1

被解释为:

nawk -v x=<0xc3> 'BEGIN{system("...")}' 1

请注意,如果该函数是在 0xa0 不是空白或 0xa3 0x5c 是 alpha 的语言环境中定义的,typeset -f即使在它是空白的语言环境中调用,仍会输出相同的结果(解释时产生不同的输出)

$ LC_ALL=zh_TW.big5 bash -c $'f() { echo \xa3\x5c$(uname); }; export LC_ALL=C; typeset -f f | bash'
bash: line 3: syntax error near unexpected token `('
bash: line 3: `    echo �\$(uname)'

更一般地说,输出typeset, alias, export -p, set,locale都是意思是适合重新输入到 shell,但除了这些区域设置问题之外,已知各种实现也存在几个问题,如果还有更多问题,我也不会感到惊讶。

所以,是的,我同意你认为它是危险的,这是一个好主意,并且最好只在你知道输出数据来自哪里的上下文中使用它们。例如,在 的情况下typeset -f foo,仅将其用于foo,仅在满足以下条件的函数已定义(并避免在其中使用非 ASCII 字符)。

相关内容