私は最近 キャプチャのフラグLinux VulnHubマシンに書き込む を読んでいました。特権の昇格については、著者は「bash関数の操作」を参照しています。 Googleの検索では、これがどのように機能するかはほとんどわかりません。つまり、ルートSUIDバイナリで次のように文字列を実行します。
次に、作成者は、プログラムによって呼び出されたプログラムの1つ(つまり、「/ usr/bin/sl」)に一致するbash関数の作成/エクスポートに進みました。
私の主な質問は、これはどのように機能するのですか?
最終的にバイナリがbash関数/コード、つまりルートシェルを実行することは明らかですが、それは魔法のようです。再現する条件は何でしょうか。たとえば、この場合は、
この攻撃が別の名前で知られている場合、Googleと同様に知っておくと役立ちますが、この攻撃では不十分です。
編集:
私はたまたま これに関連するウォークスルー に遭遇しました。これは、(ルートSUID)「悪夢」バイナリのコードの一部を分解して分析します。ただし、「悪夢」のとき、「/ usr/bin/sl -al」を呼び出す前に、「train()」メソッドがUIDとGIDを0(ルート)に設定する理由などの質問が残ります。バイナリはすでにルートSUIDですか?
これを行わない場合、「/ usr/bin/sl」がrootとして実行できないということですか?それが事実である場合、これは現実の世界ではありそうもない、人為的な特権昇格シナリオであると言うのは公正でしょうか?
setresuid()
とsetresgid()
は何をしますか?この例をよりよく理解するために、これらの2つの関数とそれらが取る3つのパラメーターを確認する必要があります。
この答え (および credentials(7)のマニュアルページ )から:
Linuxでは、各プロセスには次のユーザーおよびグループ識別子があります。
実ユーザーIDと実グループID。これらのIDは、プロセスの所有者を決定します。要約すると、これはあなたが誰であるかです。
有効なユーザーIDと有効なグループID。カーネルはこれらのIDを使用して、メッセージキュー、共有メモリ、セマフォなどの共有リソースにアクセスするときにプロセスが持つ権限を決定します。ほとんどのUNIXシステムでは、これらのIDによって、ファイルにアクセスするときの権限も決定されます。ただし、LinuxはこのタスクにファイルシステムIDを使用します。要約すると、これはあなたができることです。
保存されたset-user-IDおよび保存されたset-group-ID。これらのIDは、set-user-IDおよびset-group-IDプログラムで使用され、プログラムの実行時に設定された対応する有効IDのコピーを保存します。 set-user-IDプログラムは、実効ユーザーIDを実際のユーザーIDの値と保存されたset-user-IDの値との間で切り替えることにより、特権を引き受けて削除できます。要約すると、これは以前の人物です。
さらに、SetUID-Bitを理解することが重要です。これは、それを呼び出すのではなく、所有者の権限で実行可能プログラムを実行することです。
nightmare
あなたの質問は、nightmare
がroot
によって所有されており、SetUID-Bitセットを持っていることを具体的に述べています。つまり、nightmare
の実行を許可されているユーザーは、基本的にroot
として実行されます。これは、nightmare
のすべての子プロセス(system()
の呼び出し時に生成されるなど)もroot
として実行されることを意味します。
setresuid()
は何をしますか?この文脈で?何もない。ユーザーはすでにroot
として実行しているため、それ以上の悪用には影響しません。
/dev/tty
_を使用できますか?この質問は、この文脈ではあまり意味がありません。関連するコードスニペットを見て、文字列_/dev/tty
_がどこから来ているかを確認する必要があります。
_if (open("/dev/tty", O_RDWR) != -1) {
fire();
rax = sub_4008d0();
}
_
これは、プログラムが読み取りおよび書き込みのために_/dev/tty
_を開こうとしていることを意味し、それが成功した場合はfire()
を呼び出します。
Bash関数に/dev/tty()
という名前を付けると、open()
の最初のパラメーターとしてファイルへのパスが必要になるため、希望する結果が得られません。 bash
から完全に独立しており、bash関数の概念はありません。
puts()
はどうですか?同様に、これはあまり意味がありません。 strings
は魔法ではなく、コンテキストを理解していません。それが行うすべては、印刷可能な一連のバイトを探すことですASCII文字。
puts()
は、文字列を出力するC関数です。
/usr/bin/aafire
_はどうですか?私は個人的には試していませんが、実際には_/usr/bin/aafire
_の代わりに_/usr/bin/sl -al
_を使用できたようです。これが正しくない場合は、コメントしてください。この部分を編集します。
はい、実際にはもっと良いです! system()
は、_sh -c
_変数を解決してsl
を見つける必要がある_$PATH
_を内部的に呼び出します。パス変数が_.
_または_/usr/bin
_よりも優先度の高い他のユーザー書き込み可能ディレクトリを含むように変更された場合、_./sl
_を_/bin/bash
_にシンボリックリンクできます。
はい、そうです SetUID-Bitはシェルスクリプトでは無視されます 。ネイティブ実行可能ファイルである必要があります。
プログラムnightmare
にはスティッキービットが設定されています。これは、このコマンドを実行するすべてのユーザーが、このコマンドのためにUIDを実質的に0に設定していることを意味します。
stringsコマンドは、実行可能ファイルにコンパイルされたバイナリファイルを表示します。その1つは/usr/bin/sl
です
ここでの秘訣は、nightmare
にslプログラムを毎回確実に実行させることです(おそらくエラーと関係があります)。
現在のシェルのfunctionコマンドは、実質的にsl
コマンドのエイリアスです。したがって、nightmare
が/usr/bin/sl
を実行しようとすると、内部関数がディスク上のsl
コマンドの代わりに実行されます。
例えば。:alias /usr/bin/sl /bin/sh
今、nightmare
は0のUIDで実行されており、nightmare
は/usr/bin/ls
のエイリアスである/bin/sh
(rootとして)を実行しようとするため、Born初期ユーザーにrootアクセス権がない場合でも、rootとして実行されているシェルセッション。