https://www.sektioneins.de/en/blog/15-07-07-dyld_print_to_file_lpe.html でStefan Esserによって報告されたDYLD権限昇格の脆弱性について読むだけ
これにより、誰でもrootが所有する任意のファイルをファイルシステム内の任意の場所で作成または開くことができることを理解していますが、ファイル記述子を子プロセスにリークすると、そうでない場合よりも脅威が大きくなることを理解したいと思います。
設定時:
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
が含まれています。
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の修正は非常に単純なはずです。ファイルは、環境が適切にサニタイズされた後にのみ開く必要があります。