SELinuxのsandbox環境から脱出可能な脆弱性(CVE-2016-7545)
こんにちは。SIOS OSSエバンジェリスト/セキュリティ担当の面です。
10月26日にpolicycoreutilsのsandboxコマンド(SELinuxのラベルを使ったサンドボックス提供コマンド)にsandbox環境から脱出可能なバグ(脆弱性)があるとの報告がCVE-2016-7545として公開されました。主要ディストリビューターから修正済みのパッケージもリリースされましたので、改めてCVE-2016-7545の経緯と情報について簡単にまとめてみます。
Priority
Important
影響するバージョン
policycoreutilsの全バージョン(最新のものでは修正されています)
脆弱性概要(詳細はリンク先のサイトをご確認ください)
9/23に、NSAのselinux-users MLに「SELinux sandbox escape via TIOCSTI ioctl」というタイトルで、下記のサンプルプログラム
#include #include ioctl.h> int main() { char *cmd = "id\n"; while(*cmd) ioctl(0, TIOCSTI, cmd++); execlp("bin/id", "id", NULL); }
をコンパイルして/bin/sandbox(selinuxを用いたsandbox環境を提供するユーティリティ。デフォルトではプログラムはsandbox_tドメインで動作する)で実行すると、本来は
[sios@cent7poc work]$ /bin/sandbox ./no_exploit uid=1000 gid=1000 groups=1000,10 context=unconfined_u:unconfined_r:sandbox_t:s0:c147,c515
と出力されるべき所が
[sios@cent7poc work]$ /bin/sandbox ./TIOCSTI_test id uid=1000 gid=1000 groups=1000,10 context=unconfined_u:unconfined_r:sandbox_t:s0:c99,c979 [sios@cent7poc work]$ id <-- これはコマンド入力ではなくsandbox_tドメイン内で動作しているプログラムから呼び出されたものです uid=1000(sios) gid=1000(sios) groups=1000(sios),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
と出力されてしまう(sandbox_tドメインから脱出して、unconfined_tドメインで動作してしまう)という問題が報告されました。
そもそもTIOCSTIは入力を偽装するもので、ioctl(0, TIOCSTI, cmd++)で標準入力にcmdに入った文字列を入力として引き渡して実行しています。この際、同じセッションIDのグループはセッションリーダーが最初にオープンした端末を共有しているため、このセッションリーダーがオープンした端末からの入力として処理されてしまいます。
例えば、一般ユーザでsandboxを用いてviコマンドを実行すると
ps -ejHZの結果) LABEL PID PGID SID TTY TIME CMD system_u:system_r:kernel_t:s0 2 0 0 ? 00:00:00 kthreadd ----snip---- unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2954 2950 2950 ? 00:00:00 sshd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2955 2955 2955 pts/0 00:00:00 bash unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 3076 3076 2955 pts/0 00:00:00 sandbox unconfined_u:unconfined_r:sandbox_t:s0:c5,c677 3077 3076 2955 pts/0 00:00:00 vi
として、SIDが2955(bash)のTTYはsandboxで実行されたviに至るまでpts/0(/dev/pts/0)で共有されています。そのため、sandboxで先のプログラムを実行した際には、TIOCSTIでpts/0に文字列を引き渡され、unconfined_tドメインからの実行として処理されてしまうわけです。
これは単純に、TIOCSTIを用いた際に/dev/pts/0等へのioctlが許可されてしまっている(ポリシの中で粗く設定されている)のが問題なため、例えばこのStephen Smalley氏のメールのように、下記のような
(allowx sandbox_domain ptynode (ioctl chr_file (not (0x5412))))
ポリシをCILを用いて追加して、TIOCSTI(0x5412)以外のptynodeへのアクセスを明示的に許可する(0x5412は許可しない)と記述すれば、
$ sandbox ./test uid=1000 gid=1000 groups=1000 context=unconfined_u:unconfined_r:sandbox_t:s0:c466,c667 type=AVC msg=audit(1474638454.617:6045): avc: denied { ioctl } for pid=2935 comm="test" path="/dev/pts/0" dev="devpts" ino=3 ioctlcmd=5412 scontext=unconfined_u:unconfined_r:sandbox_t:s0:c72,c552 tcontext=unconfined_u:object_r:user_devpts_t:s0 tclass=chr_file permissive=0
として防ぐことが出来ます。どうしても必要な場合にはこのポリシ変更(ポリシをより細かくする)により、この脆弱性を防ぐことが出来ます。
或いは、policycoreutilsのsandboxコマンド内で、seunshareのようにsetsid()をコールして新たにセッショングループを作る方法にすれば防ぐことが出来ますが、それにはpolicycoreutilsの修正が必要になります。
また、この議論の中で、TIOCSTI自体が旧いものなので、「そもそも未だに使ってるの?(殆どexploit書くためにしか使われてないなじゃない?」という議論も起こりましたが、少なくとも
util-linux: used in agetty in wait_for_term_input()
kbd: contrib utility sti equal to tiocsti utility.
irda: Used by handle_scancode() to emulate input.
tcsh: Used in ed mode and in pushback().
emacs: Used in stuff_char() (putting char to be read from terminal)
今回のpolicycoreutilsの修正では
+ pid = os.fork() + if pid == 0: + rc = os.setsid() + if rc: + return rc
のように、sandboxで実行する際にsetsid()で新しいセッションを作成します。これにより、ここにもあるように制御端末を持たない新しいセッションが作成されます。
これにより、例えばsandboxでviを実行すると
ps -ejHZの結果) LABEL PID PGID SID TTY TIME CMD system_u:system_r:kernel_t:s0 2 0 0 ? 00:00:00 kthreadd ----snip---- unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 10623 10619 10619 ? 00:00:00 sshd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 10624 10624 10624 pts/0 00:00:00 bash unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 10645 10645 10624 pts/0 00:00:00 sandbox unconfined_u:unconfined_r:sandbox_t:s0:c568,c642 10646 10646 10646 ? 00:00:00 vi
のように、新たなセッションID(SID)グループ: 10646でviが実行され、TTYも共有されないため、sandboxから脱出してプログラムを実行されることがなくなりました。
というように、未だ使われているプログラムは現役であるようです。
主なディストリビューションの対応方法
詳細は、各ディストリビューションの提供元にご確認ください
debian
Red Hat Enterprise Linux/CentOS
Oracle Linux
ubuntu
SUSE/openSUSE
https://people.canonical.com/~ubuntu-security/cve/2016/CVE-2016-7545.html
対処方法
各ディストリビューションの案内に従い、アップデートを行ってください。
また、policycoreutilsのsandboxを使ってサービスを提供している場合には、サービスの再起動が発生しますので、pacemakerなどOSSのクラスタ製品やLifeKeeperなどの商用のクラスタリング製品を使うとサービス断の時間を最小限にすることが出来ます。
[セミナー告知]
11/30(水)に「OSSセキュリティナイター vol.3」と題して、セキュリティのセミナーを行います。
この回では、世界で最も利用されているオープンソースデータベースであるMySQLを取り上げ、『MySQLデータベースのセキュリティを考える 〜 重要データを守るために必要なこと〜』と題してセミナーを開催します。
今回も、前回に引き続き、ゲスト講師としてMySQLスペシャリストをお招きし講演をいただきます。
http://connpass.com/event/44819/がプログラム内容と申し込みの詳細になりますので、是非お申し込み下さい。