setuid バイナリ用 LD_PRELOAD

setuid バイナリ用 LD_PRELOAD

setuid/setgid 権限を必要とするプログラムの malloc/free 機能をオーバーライドしようとしています。これには LD_PRELOAD 変数を使用します。 ~によるとld文書、私のライブラリを標準の検索ディレクトリの1つ(私は/ usr / libを選択)に入れ、setuid / setgid権限を付与する必要があります。私はすでにこれをしました。ただし、.soファイルに接続できず、エラーが発生します。

object 'liballoc.so' from LD_PRELOAD cannot be preloaded: ignored

考えられる理由は何ですか? setuid / setgid権限なしでプログラムでこの.soファイルをテストしましたが、すべてがうまくいきました。オペレーティングシステム:Red Hat 7.0

答え1

ldドキュメントによると、私のライブラリを標準の検索ディレクトリの1つに置く必要があります(私の選択/usr/lib)。

それは間違いです。これを入れる必要があります/usr/lib64(マシンがx86_64であると仮定)。

私はCentos 7 VM(RHEL 7と同じでなければなりません)のマンページでレシピを試してみました。

rootユーザーとして:

cynt# cc -shared -fPIC -xc - <<<'char *setlocale(int c, const char *l){ errx(1, "not today"); }' -o /usr/lib64/liblo.so
cynt# chmod 4755 /usr/lib64/liblo.so

setuidプログラムを使用する一般ユーザーとして:

cynt$ LD_PRELOAD=liblo.so su -
su: not today

この機能を使用するのが良いアイデアかどうかはまったく異なります(IMHO、そうではありません)。

答え2

man ld.so

安全実行モード
セキュリティ上の理由から、動的リンカーがバイナリを安全実行モードで実行する必要があると判断した場合、特定の環境変数の影響は無効になるか修正されます。
[...]
次の条件が満たされると、バイナリがセーフランモードで実行されます。モード実装:

  • プロセスの実際の実効ユーザーIDが異なります。

[...]
LD_予圧
セーフランモードでは、スラッシュを含む事前ロードパス名は無視されます。また、共有オブジェクトは標準検索ディレクトリからのみプリロードされ、ユーザーID設定モードビットが有効になっている場合にのみ(通常ではありません)。

SUIDバイナリを実行すると、これが発生します。実際のUIDと有効なUIDが異なります。ただし、このバイナリが別の(SUIDではなく)バイナリを実行している場合、親のEUIDは子のRUIDとEUIDになります。

sudo sleep 1000 &

ps -o pid,ruid,euid,args --pid $! --ppid $!
  PID  RUID  EUID COMMAND
 7286  1000     0 sudo sleep 1000
 7287     0     0 sleep 1000

したがって、LD_PRELOAD制限を回避するには、sudoを介してバイナリを呼び出すか、ラッパーSUIDバイナリを生成して実際のバイナリを呼び出すことができます。

答え3

その理由は、マルウェアが上昇するのを防ぐためです。 ACプログラムはいいえmain() で実行を開始します。代わりに、Cランタイムライブラリが最初に呼び出され、環境(STDIOストリームを含む)、コンパイル時定数ではなくグローバル変数を設定してからmain()を呼び出します。

悪意のある行為者は、LD_PRELOAD =を使用してlibc.oライブラリをカスタムライブラリで上書きし、起動機能(LD_PRELOADを復元してから/ bin / shを呼び出すなど)を修正する可能性があります。 SUIDプロセスがLD_PRELOAD =を無視しない場合、ユーザーは/ bin / passwdを実行できるようになり、ルートシェルを持つようになります。これでルートキットなどをインストールできます。

関連情報