web-dev-qa-db-ja.com

OS XでDYLD権限昇格の脆弱性はどのように機能しますか?

https://www.sektioneins.de/en/blog/15-07-07-dyld_print_to_file_lpe.html でStefan Esserによって報告されたDYLD権限昇格の脆弱性について読むだけ

これにより、誰でもrootが所有する任意のファイルをファイルシステム内の任意の場所で作成または開くことができることを理解していますが、ファイル記述子を子プロセスにリークすると、そうでない場合よりも脅威が大きくなることを理解したいと思います。

10
Josh

分析

設定時:

DYLD_PRINT_TO_FILE=/tmp/log some_command

macOS Xダイナミックローダーは/tmp/logをログファイルとして開きます。つまり、ダイナミックローダー内の潜在的なデバッグ問題への追加アクセス権があります。このファイルは、シェル呼び出しコンテキストの最初の空きファイル記述子3で開かれています。したがって、ファイル記述子の関連付けは次のとおりです。

0   →   stdin
1   →   stdout
2   →   stderr
3   →   /tmp/log

このコンテキスト内では、プロセスsome_commandがforkされます。

残念ながら、ダイナミックローダーは3を閉じません。したがって、プロセスsome_commandは、開く必要のない開いたファイルで実行されており、通常のファイルシステムアクセス制御を通過することはありません。これは、some_commandが通常それを開こうとした場合にアクセスできないファイルである可能性があります。

たとえば、newgrpはsetuidバイナリですが、正しく保護されたファイルに書き込むことはできません。

 $ newgrp 
 $ echo '#comment'>&3 
 zsh:3:不正なファイル記述子

このエラーは正常です。newgrpが明確に表示することを許可しているため、lsofによって分岐されたシェルはファイル記述子3を開いていません(3の列FDを参照)。

 $ lsof -p $$ 
コマンドPIDユーザーFDタイプデバイスサイズ/オフノード名
 [...] 
 zsh 2405 bob 0u CHR 16,3 0t28 1405 /dev/ttys003
zsh 2405 bob 1u CHR 16,3 0t28 1405 /dev/ttys003
zsh 2405 bob 2u CHR 16,3 0t28 1405 /dev/ttys003
zsh 2405ボブ5(失効)
 [...] 

しかし、ダイナミックローダーで3を閉じることができないため:

 $ DYLD_PRINT_TO_FILE =/etc/sudoers newgrp 
 $ echo '#comment'>&3 
 $ 

注意:ここでエラーメッセージが表示されない場合、echoは機能しています。さらに、lsofはホールを示します(行3w、つまり、ファイル記述子3が書き込みアクセスで開かれたことを意味します)。

 $ lsof -p $$ 
コマンドPIDユーザーFDタイプデバイスサイズ/オフノード名
 [...] 
 zsh 2430 bob 0u CHR 16,3 0t1024 1405 /dev/ttys003
zsh 2430 bob 1u CHR 16,3 0t1024 1405 /dev/ttys003
zsh 2430 bob 2u CHR 16,3 0t1024 1405 /dev/ttys003
zsh 2430 bob 3w REG 1,7 1293 2034681610 /private/etc/sudoers
zsh 2430 bob 5(取り消し済み)
 [...] 

newgrp/etc/sudoersファイルへの書き込みを許可します。

警告

この例を試す場合は、この例が無害であっても、後で/etc/sudoersをクリーンアップすることを忘れないでください。その最後の行には現在#commentが含まれています。

7
dan

newgrpは、新しいグループIDでシェルを実行するUNIXユーティリティです( NIX仕様ページ を参照)。このユーティリティは、グループIDを現在のシェルのグループリストの外に変更できるため(たとえば、uidのグループリスト内の任意のグループ)、root権限が必要です。したがって、newgrpはシェルを起動するsetuidルートアプリケーションです。

_DYLD_PRINT_TO_FILE_は、デバッグ情報を出力する場所をdyldに指示するdyld(OS Xダイナミックリンカー)環境変数です。この特定の変数は、OS X 10.10「Yosemite」で追加されました。これは 多数の_DYLD__変数 の1つにすぎず、共有ライブラリのロードのデバッグを容易にします。 dyldが_DYLD_PRINT_TO_FILE_を検出すると、指定されたファイルに接続された新しいファイル記述子を開きます。 fds 0、1、2はすでにstdin、stdout、およびstderrに接続されているため、ファイルはfd 3として開かれます。特に、newgrpはルートとして開始されるため、newgrpが後で特権を生成する権限をドロップしても、ファイルはルートの権限を使用して開かれますシェル。

_DYLD__環境変数はプログラムの動作を予期しない方法で変更する可能性があるため(特に_DYLD_INSERT_LIBRARIES_、OS Xの_LD_PRELOAD_に相当するOS X)、それらは通常、setuidプログラムを実行する前に削除またはサニタイズされます。 Apple Yosemiteの出荷時に新しい_DYLD_PRINT_TO_FILE_をサニタイズすることを明らかに忘れており、この特定の欠陥が明らかになった。

最後に、(外部)エコーコマンドは、newgrpによって生成されたサブシェルに(内部)エコーコマンドを実行するように指示します。これにより、文字列$(whoami) ALL=(ALL) NOPASSWD:ALLがfd 3に出力されます。これは、現在_/etc/sudoers_です。この行は、anyアカウントにSudoアクセスが許可され、Sudoを使用するためにパスワードは不要であることをSudoに伝えます。

次にサブシェルが終了し(実行するコマンドがなくなります)、最後のコマンド_Sudo -s_が実行されます。 Sudoはパスワードを必要とせず、すべてのアカウントがSudoを使用できるため、_Sudo -s_はプロンプトを表示せずにすぐにルートシェルを開きます。


_DYLD__dyld関数で確認できるように、OS Xのsetuidは実際にpruneEnvironmentVariablesアプリの環境からすべての_dyld.cpp_変数を削除します。では、なぜこのバグが存在するのでしょうか。その答えは、_DYLD_PRINT_TO_FILE_はサニタイズが実行される前に十分に処理されるということです。実際、これは基本的にdyldが起動後に最初に行うことです(__main_ in _dyld.cpp_を参照)。 )。したがって、Appleの修正は非常に単純なはずです。ファイルは、環境が適切にサニタイズされた後にのみ開く必要があります。

3
nneonneo