いくつかのシェル関数foo
現在のシェルセッションで定義されています。次に、コマンド
typeset -f foo
この関数のソースコードを出力します。これは、少なくとも原則として、ssh
を介してリモートホストでこの機能を実行できることを意味します。 以下に示すように:
ssh <REMOTE-HOST> "$(typeset -f foo); foo"
(この質問の目的のために、foo
によって言及されたすべてのコマンドとファイルシステムパスを想定します <REMOTE-HOST>
で利用可能です 。また、bash
両端のシェルです。)
私の本能は、このような自動生成されたソースコードを盲目的に調達することは非常に脆弱であるということですが、関数foo
の例を思い付くことができませんでした。 このイディオムが失敗する場所。
私の質問は:このイディオムはどれくらい安全ですか?安全でない場合、誰かがそれがどのように失敗するかを説明する具体的な例を教えてもらえますか? (安全性の問題には次のものが含まれます:bash
typeset -f
のそのような使用を保証します 安全ですか?)
NB: この投稿では、私は代替案を探していません。この特定のイディオムの特性を理解したいだけです。
編集:bash
両端のシェルです。
承認された回答:
コードが生成されたロケールと同じロケールで解釈されない場合(またはロケール name の場合)は安全ではありません。 は同じですが、そのロケールの定義はsshクライアントホストとサーバーホストで異なります。
特に重要なのは、blank
内の文字のエンコードと文字のメンバーシップです。 、alpha
およびalnum
カテゴリ。
たとえば、α
BIG5文字セットの文字(ギリシャ文字の小文字のアルファ)は0xa3 0x5cとしてエンコードされ、0x5cはです。 ASCII(およびBIG5を含むすべての文字セット)。
したがって、foo
がある場合 その文字セットで次のように定義された関数:
foo() {
echo α
}
typeset -f
はそのように出力しますが、Cのような別のロケールで解釈された場合、その0xa30x5cはα
とは見なされません。 ただし、不明な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の文字は、0xc30xa0としてエンコードされます。 iso8859-1および他のいくつかのiso8859
文字セット、0xa0はノーブレークスペース文字です。一部のシステムでは、その文字は空白に含まれています 文字クラス。構文のトークン区切り文字としてbashによって尊重されます。
Solarisは、U + 00A0が空白と見なされるそのようなシステムの1つです:
$ 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がアルファであるロケールで関数が定義されている場合は、typeset -f
空白のロケールで呼び出された場合でも、同じように出力されます(解釈すると異なる出力が生成されます)
$ LC_ALL=zh_TW.big5 bash -c $'f() { echo xa3x5c$(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
すべて意味がある シェルへの再入力に適していますが、これらのロケールの問題に加えて、さまざまな実装にいくつかの問題があることが知られており、さらに多くの問題があったとしても驚かないでしょう。
ですから、そうです、あなたはそれを危険だと考えるのは正しいと思います。出力されるデータがどこから来ているのかがわかっている状況でのみ使用することをお勧めします。たとえば、typeset -f foo
の場合 、foo
でのみ使用してください あなたの機能 定義済み(および非ASCII文字の使用は避けてください)。