web-dev-qa-db-ja.com

Bash関数の操作の説明

私は最近 キャプチャのフラグLinux VulnHubマシンに書き込む を読んでいました。特権の昇格については、著者は「bash関数の操作」を参照しています。 Googleの検索では、これがどのように機能するかはほとんどわかりません。つまり、ルートSUIDバイナリで次のように文字列を実行します。

strings run on root SUID ELF binary

次に、作成者は、プログラムによって呼び出されたプログラムの1つ(つまり、「/ usr/bin/sl」)に一致するbash関数の作成/エクスポートに進みました。

enter image description here

私の主な質問は、これはどのように機能するのですか?

最終的にバイナリがbash関数/コード、つまりルートシェルを実行することは明らかですが、それは魔法のようです。再現する条件は何でしょうか。たとえば、この場合は、

  1. 「/ dev/tty」を使ってもらえますか?
  2. 「プット」はどうですか?
  3. / usr/bin/aafireはどうですか?なぜか、なぜそうでないのか?
  4. 「悪夢」プログラムがFQパスなしで「sl -al」を呼び出しただけでも機能しますか?
  5. ルートSUIDファイルがどのようなバイナリ/ ELFであるかは重要ですか?

この攻撃が別の名前で知られている場合、Googleと同様に知っておくと役立ちますが、この攻撃では不十分です。


編集:

私はたまたま これに関連するウォークスルー に遭遇しました。これは、(ルートSUID)「悪夢」バイナリのコードの一部を分解して分析します。ただし、「悪夢」のとき、「/ usr/bin/sl -al」を呼び出す前に、「train()」メソッドがUIDとGIDを0(ルート)に設定する理由などの質問が残ります。バイナリはすでにルートSUIDですか?

train method nightmare binary

これを行わない場合、「/ usr/bin/sl」がrootとして実行できないということですか?それが事実である場合、これは現実の世界ではありそうもない、人為的な特権昇格シナリオであると言うのは公正でしょうか?

6
n00b

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

あなたの質問は、nightmarerootによって所有されており、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_にシンボリックリンクできます。

ルートSUIDファイルがどのようなバイナリ/ ELFであるかは重要ですか?

はい、そうです SetUID-Bitはシェルスクリプトでは無視されます 。ネイティブ実行可能ファイルである必要があります。

3
MechMK1

プログラム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として実行されているシェルセッション。

1
Scottie H