web-dev-qa-db-ja.com

bashシェル関数のインポート機能は、必然的に特権昇格の問題を引き起こしますか?

Shellshock後続コマンドの即時コード実行問題がなくても、環境から関数をインポートするbashの機能が総合的な特権を生み出す範囲エスカレーションの脆弱性?

明確にするために、多くのsetuidプログラムがあり、それらの一部は直接または間接的にスクリプトを呼び出すか、またはほとんどのLinuxではbashを経由するsystem(3)呼び出しを使用します。問題は、システムにそのようなsetuidバイナリがインストールされていると想定していることですbashのこの機能により、ローカル権限が許可されますエスカレーション。

  • たとえば、スクリプトを呼び出すと、組み込みのオーバーライドが許可されますか?もしそうなら、これはsetuid実行可能ファイルとsystem(3)呼び出しと組み合わせて特権を昇格させることができます。 lscdまたは何か無害ですか?
  • そのようなエスカレーションベクトルrequire呼び出されるスクリプト(この場合、lsまたはフルパスを使用しないスクリプトで使用されるコマンドをオーバーライドする可能性があります)?
  • インポートされた関数は、最初の引数がスクリプトではない場合でも、_/bin/sh -c ARGUMENTS_の通常の実行パスによっていつでも使用される可能性がありますか?
  • systemへの最初の引数と同じ名前を環境変数に単に与えることができますか?
  • もしそうなら、それは、_/bin/sh_がbashであるシステムで、setuid実行可能ファイルによるsystem(3)へのすべての呼び出しが特権エスカレーションベクトルであることを意味しますか?
13
Ben

これらのテストは、パッチが適用されていないシステムで実行されます。

# ls='() { echo NO; }' bash -c 'ls'
NO

*ワイルドカードが必要です。そうしないと、Perlがシステムコールをfork/execの組み合わせに置き換えます。

# ls='() { echo NO; }' Perl -e 'system("ls *");'
NO

ただし、lsは組み込みではありません。

# type ls
ls is hashed (/bin/ls)
# type echo
echo is a Shell builtin

組み込みのエコーを上書きしてみてください(再帰を回避するために、「コマンド」が組み込みをオーバーライドします)。

# echo='() { command echo NO; }' bash -c 'echo YES'
NO

これまでのところ、次のことを示しました。

  1. 組み込みをオーバーライドできます
  2. require呼び出されないスクリプト
  3. 最初の引数がスクリプトでない場合でも
  4. 「システム」へのすべての呼び出しはベクトルであり、呼び出し元の特権を与えます

裸の「システム」と「popen」は腐敗していると思います。これらのほとんどの使用法は、ユーザーデータのシェルメタ文字をエスケープすることに煩わされていないと思います。

シェルにパイプラインを生成させたい場合、またはシェルのビルトインを使用させたい場合に、この呼び出しを行いますが、それでもfork/execが必要です。

exec("sh", "-c", "\"$0\" \"$1\" | tee -a \"$2\"", ...);

この手法では、bashが-cコマンドの引数を参照するようになり、$ 0が最初の引数、または「-」をフィラーとして使用できます。

exec("sh", "-c", "\"$1\" \"$2\" | tee -a \"$3\"", "--", ...);

このテストは、パッチが適用されたシステムで実行されます。

$ env "BASH_FUNC_ls()=() { echo NO ; }" bash -c 'ls'
NO

この問題はShellshockとは関係がないことを明確に示しています。

スクリプトまたはスクリプトを使用するツールの作成者は、ユーザー入力を検証することを知っている必要があり、(ユーザー入力が含まれているため)環境を検証/クリーンアップすることを知っている必要があります。環境の一部を保持する必要がある場合がありますそれらがどちらであるかを簡単に確認できます。

XAUTHORITY、DBUS_SESSION_BUS_ADDRESS、XDG_SESSION_DESKTOP、SSH_AUTH_SOCKはいくつかあり、他の重要な環境変数はまだ発明されていない可能性があります

それは「環境」と呼ばれています。 PATHはサニタイズされる可能性がありますが、system()に発行された最初のコマンドは置き換えられます

Sudoeditのmanページには次のように書かれています:

Running Shell scripts via Sudo can expose the same kernel bugs that make
setuid Shell scripts unsafe on some operating systems (if your OS has a
/dev/fd/ directory, setuid Shell scripts are generally safe).

ただし、すべてのbash関数のインポートを拒否しない限り、これはsetuid bashシェルスクリプトには当てはまりません。

6
Sam Liddicott

Set(u | g)idバイナリが実際の[ug] idを保持する場合、答えは「いいえ」です。

E [ug] id!= real [ug] idで、特権モード(_-p_)で呼び出されない場合、bashはその特権を削除します。

バッシュShell.c:main()

_  if (running_setuid && privileged_mode == 0)
    disable_priv_mode ();
_

特権モードで実行している場合、または/ bin/shとして呼び出されたときに特権を削除しないようにbashにパッチが適用されている場合(例: Debianにはこのようなパッチがあります 、古いset [ug] idプログラムなどの破壊を避けるためUUCPとして)、bashは環境から関数をインポートしません。 Bashは、set [ug] idが実行されているかどうか、または特権モード(_-p_)で実行されているかどうかをチェックし、そうであれば環境から関数をインポートしません。

バッシュShell.c:main()

_  /* Initialize internal and environment variables.  Don't import Shell
     functions from the environment if we are running in privileged or
     restricted mode or if the Shell is running setuid. */
#if defined (RESTRICTED_Shell)
  initialize_Shell_variables (Shell_environment, privileged_mode||restricted||running_setuid);
#else
  initialize_Shell_variables (Shell_environment, privileged_mode||running_setuid);
#endif
_

バッシュvariables.c:initialize_Shell_variables()

_  /* If exported function, define it now.  Don't import functions from
 the environment in privileged mode. */
  if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
_
2
ninjalj

「これは、setuid実行可能ファイルと組み合わせて特権の昇格を引き起こすことができますか?」

GNUにsetuidスクリプトを含めることはできないため、Bashスクリプトを直接呼び出すsetuidバイナリを想定します。始める前に、これは非常に貧弱な設計であり、 GNU によって明示的に推奨され、 setuidマニュアル で再度推奨されます。また、ldは、最も悪質な環境変数を取り除き、 GNU/Linuxでは、setuidプロセスにコードを挿入したり、そのルートのダンプを取得したりすることはできません(つまり、rootでない限り)。

Shellshockは、このようなsetuidバイナリの悪用にまったく関与しません。バイナリが健全性の推奨事項に従っている場合は、シェルスクリプトを呼び出さず、システムを呼び出さず、実行されているすべてのexec*呼び出しが信頼できない環境変数の影響を受けないようにします。これは、設計による特権昇格に対して脆弱ではありません。 。 setuidバイナリが信頼できない入力を検証しない場合、とにかく脆弱になります。

システムを起動したりシェルを起動したりするべきではない理由は、信頼できない呼び出し先によって選択された環境が新しいシェルに引き継がれるためではありません(それはプログラミングの慣例に完全に依存します)。 混乱した代理 特定の操作を許可するだけでなく、無制限の範囲での攻撃:システムは、他のどのシナリオよりも広範囲に侵害されるだけです。

BashからShellshockのような環境でsetuidバイナリを呼び出すと、Bashのインスタンスは、your権限で追加のBashプリミティブを処理しますが、後で呼び出されるsetuidバイナリは、とにかく悪意のある環境を想定しています。

「そのようなエスカレーションベクトルには、スクリプトを呼び出す必要がありますか?」

Shellshockは、Bashが最初にBashを呼び出すよりも低い特権を持つプリンシパルの制御下にある環境でBashが呼び出されることを意味します。

誰もBashを呼び出していない場合、シェルショックペイロードは処理されないので役に立ちません(Microsoft SSLでOpenSSLエクスプロイトが機能しないように)。

「インポートされた関数は、最初の引数がスクリプトでない場合でも、/ bin/sh -c ARGUMENTSの通常の実行パスによっていつでも使用される可能性がありますか?」

引数がシェルスクリプトであり、/bin/shがBashを指している場合、Bashが悪用される可能性があります。ただし、独自の特権を使用してコマンドを実行しているため、これを行うことにはまったく関心がありません。何かを直接呼び出すよりも/bin/sh -cを使用してより多くの特権を持っているSELinuxまたはAppArmorのセットアップを想定していない限り、特権を取得しません。そのようなセットアップは意図的ではなく、壊れています。

引数がバイナリの場合、バイナリが呼び出されます。 Microsoft Wordは、同時に実行されているFirefoxの機能を使用しますか?いいえ、同じです。ローダーはバイナリのコードをロードしてバイナリを実行しますが、別のバイナリからバグのあるコードを実行することはありません。バイナリの動作を変更できる唯一のシナリオは、コードインジェクションによるもので、setuidプロセスでコードインジェクションを実行することはできません。

「環境変数にシステムの最初の引数と同じ名前を付けてもらえませんか?」

はい。ただし、システムは環境変数を読み取らず、コマンドを実行します。環境変数は、名前と文字列のペアの単なる辞書です。セマンティクスに関係なく、将来使用されるすべてのテキストが置き換えられるわけではありません。プログラムは、環境変数を読み取り、それを気にすることを決定することにより、環境変数を明示的に使用する必要があります。

「もしそうなら、それは/ bin/shがbashであるシステム上でのsetuid実行可能ファイルによるsystem(3)へのすべての呼び出しが特権昇格ベクトルであることを意味しますか?」

絶対違う。 setuidバイナリによるsystemの呼び出しは、脆弱性があった場合にその結果が途方もなく悲惨になるため、単に悪い考えです。 Bashを使用するOSでsystemを呼び出しても、特権の昇格には2つのプリンシパルが必要であるという事実は変わりません。より高い特権のプリンシパルが、より低い特権のプリンシパルによって提供される未検証の環境でBashを呼び出すことを決定した場合にのみ、Shellshockが特権の昇格を引き起こします。

ほとんどの場合、Shellshock以外の方法でセットアップが失敗する可能性があるため、このようなシステムコールはすでに望ましくありません。また、既存の混乱した代理攻撃を回避するために講じる予防策によって、Shellshockも防止されます。

2