alfort's Blog

Linuxエンジニアのメモ

`su(1)`できないマシンで四苦八苦した話

su(1)が使えない

ちょっとしたことでマシンが不調になり、su(1)ができなくなったときにやってみた知見をまとめた。

再現させて見たけれども、最悪の場合どうしようにもなくなってしまう可能性があるので、壊してもいい環境で遊んでいる。

何が起こったか

su(1)で実行するのに必要なライブラリがみつからなくなってしまった。

$ su -
su: error while loading shared libraries: libaudit.so.1: cannot open shared object file: No such file or directory

で、libaudit.so.1を探してみると、以下のように誰かが名前を書き換えて、libaudit.so.1を消してしまった(ここではlibaudit_dymmy.so.1に書き換えてしまった)らしい。。。

ll /lib/x86_64-linux-gnu/ |grep libaudit
-rw-r--r--  1 root root   133200  8月 16 15:37 libaudit.so.1.0.0
lrwxrwxrwx  1 root root       17 10月 19 01:07 libaudit_dummy.so.1 -> libaudit.so.1.0.0

マシン環境など

$ less /etc/os-releaseしてみた結果は以下の通り。 Hyper-Vで立ち上げた仮想マシンで、最悪の場合完全に復旧不可能になってしまうため、チェックポイントを立ててバックアップはとっている。

NAME="Ubuntu"
VERSION="19.10 (Eoan Ermine)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 19.10"
VERSION_ID="19.10"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=eoan
UBUNTU_CODENAME=eoan

どうやって対応するか

よくみると、libaudit.so.1.0.0自体は無傷でlibaudit.so.1が見つからなくなってしまっているように見える。

libaudit.so.1.0.0はライブラリの実態で、ここを書き換えられるとどうしようにもないけれど、libaudit.so.1は単なるシンボリックリンクに過ぎない。

といったことを考えた。

シンボリックリンクを張る

こんな感じで、適当な場所にシンボリックリンクを張る。 今回は一般ユーザのホームディレクトリ直下に張ってみた。

$ ln -s /lib/x86_64-linux-gnu/libaudit.so.1.0.0 libaudit.so.1
$ ls
ダウンロード  デスクトップ  ビデオ    ミュージックlibaudit.so.1  テンプレート  ドキュメント  ピクチャ  公開

シンボリックリンクを見るようにする

環境変数LD_LIBRARY_PATHLD_PRELOADを使ってなんとかならないかやってみた。

LD_LIBRARY_PATHを使う

環境変数LD_LIBRARY_PATHを使うことで、バイナリ実行時に動的ライブラリを探索するパスを追加することが可能になる。

以下のように、libaudit.so.1が見つからなかったのが、見つかるようになったので動くようになるはずなのだが、やっぱり動かない。

$ ldd /bin/su
        linux-vdso.so.1 (0x00007fe4ee3b9000)
        libpam.so.0 => /lib/x86_64-linux-gnu/libpam.so.0 (0x00007fe4ee37f000)
        libpam_misc.so.0 => /lib/x86_64-linux-gnu/libpam_misc.so.0 (0x00007fe4ee37a000)
        libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007fe4ee375000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe4ee184000)
        libaudit.so.1 => not found
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fe4ee17e000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fe4ee3ba000)
$ export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH
$ ldd /bin/su
        linux-vdso.so.1 (0x00007ffe16fd6000)
        libpam.so.0 => /lib/x86_64-linux-gnu/libpam.so.0 (0x00007f1c13374000)
        libpam_misc.so.0 => /lib/x86_64-linux-gnu/libpam_misc.so.0 (0x00007f1c1336f000)
        libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f1c1336a000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1c13179000)
        libaudit.so.1 => ./libaudit.so.1 (0x00007f1c1314d000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f1c13147000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f1c133ab000)
        libcap-ng.so.0 => /lib/x86_64-linux-gnu/libcap-ng.so.0 (0x00007f1c1313d000)
$ su -
su: error while loading shared libraries: libaudit.so.1: cannot open shared object file: No such file or directory

LD_PRELOADを使う

環境変数 LD_PRELOADを使うことで、動的ライブラリの関数を置き換えることができる。

こっちを使ってみても、やっぱり動かない。

$ LD_PRELOAD=./libaudit.so.1 su -
su: error while loading shared libraries: libaudit.so.1: cannot open shared object file: No such file or directory

なんで?

セキュリティ的なものが原因で、su(1)のようなコマンドでは、LD_LIBRARY_PATHLD_PRELOADが無効にされてしまうらしい。

www.ipa.go.jp

悪意のあるユーザがLD_LIBRARY_PATHLD_PRELOADを使って認証を回避してしまうようなライブラリによる差し替えを行うことを防ぐためらしい。

もちろん、PATHなどを置き換えることもできないらしい。

まぁ言われてみればそれはそうか。。。となるけれど、セキュアなプログラミングはきちんと身につけておきたい。。。