Zabbix 2.2.1rc1 がリリースされたので直されているリモートシェル実行の脆弱性について調べてみた

http://www.zabbix.com/rn2.2.1rc1.php
http://www.zabbix.com/rn2.0.10rc1.php
http://www.zabbix.com/rn1.8.19rc1.php

特定の条件でAgentが外部のシェルコマンドを実行してしまう脆弱性があったようだ。2.2.1rc1のリリース中に見たものなのでスルーしようかと思いきや、1.8, 2.0のこれまでの全てのバージョンで同様の脆弱性があったらしい。興味が出たのでちょっと深入りする。

結論から言うと、UserParameterをそれなりにしっかり使ってないと発生しない脆弱性に見える。

まず前提知識として、Zabbix AgentのUserParameterについて見てみる。これはユーザがカスタマイズされた監視項目を自分で追加できるスグレモノで、1.8には既にある。

UserParameter=キー,コマンド

キーが送られてきたらAgent上でコマンドが実行される。コマンドはシェルで実行出来るもので良い。つまり、コマンドで数値をトラップ出来さえすればほぼなんでもZabbix Serverへ送信出来るようになる。Agentが標準ではサポートしていない項目でも良い。わふー。

例として手元のzabbix_agentd.confでコメントアウトされている部分を示そう。MySQLの内部データを追加で監視する例がある。

####### USER-DEFINED MONITORED PARAMETERS #######
# Format: UserParameter=,
# Note that shell command must not return empty string or EOL only
#UserParameter=system.test,who|wc -l
### Set of parameter for monitoring MySQL server (v3.23.42 and later)
### Change -u and add -p if required
#UserParameter=mysql.ping,mysqladmin -uroot ping|grep alive|wc -l
#UserParameter=mysql.uptime,mysqladmin -uroot status|cut -f2 -d":"|cut -f1 -d"T"
#UserParameter=mysql.threads,mysqladmin -uroot status|cut -f3 -d":"|cut -f1 -d"Q"
#UserParameter=mysql.questions,mysqladmin -uroot status|cut -f4 -d":"|cut -f1 -d"S"
#UserParameter=mysql.slowqueries,mysqladmin -uroot status|cut -f5 -d":"|cut -f1 -d"O"
#UserParameter=mysql.qps,mysqladmin -uroot status|cut -f9 -d":"
#UserParameter=mysql.version,mysql -V

引数を受け取らない「静的」なUserParameter機能に脆弱性はない。上の例を使っても今回の脆弱性とは関係がない。

この状態だと実行されるコマンドに柔軟性がゼロである。引数を指定できる欲しいかもしれない。例えば1ホスト内に複数監視したいテーブルがMySQL上にあったとすれば、テーブル名を指定する、とか。それをflexible user parameters、日本語訳では「引数付きユーザパラメータ」と(・∀・)イイ!!

……日本語訳では「引数付きユーザパラメータ」と言い、以下のように記述する。

UserParameter=キー[*],コマンド

これで引数を受け取るようになる。詳細は公式ドキュメントに譲ろう。

さて、レポートを見てみる。

https://support.zabbix.com/browse/ZBX-7479

UserParameter=vfs.dir.size[*],du -s -B 1 "${1:-/tmp}" | cut -f1 

Agent側の設定 (zabbix_agentd.conf等) に上記のように記述した上でZabbix Server上で下記のようなコマンドを実行すると……

echo -e "vfs.dir.size[\nid\n]" | nc localhost 10050

"id"コマンドが実行されてしまう。

問題はUserParameterの「[*]」部分だ。レポートで言うに改行が含まれていた時にのみ問題が発生する。

この引数はPHPフロントエンド等でパラメータを指定してZabbix Agentにその値を使わせることが出来る。本来はコマンドとして実行されてはいけない。

元のコードでも怪しい文字列 ("\\'\"`*?[]{}~$!&;()<>|#@\0") が入っていたら無視するようにはなっていた。しかし改行については処理がなかった。そして改行後はコマンドと理解されてしまうらしい。

例えば1.8.18のパッチ
https://support.zabbix.com/secure/attachment/25562/zbx-7479-1.8.18.patch

引数部分はPHPフロントエンド等で指定すると述べた。つまり、PHPフロントエンド等が攻撃され、かつZabbix Agentで引数付きユーザパラメータが設定されているときにのみ問題が発生する。Zabbix Proxyが挟まっていれば、そこからも同様のことは出来るだろう、というのがレポートで述べられている。

振り返ってもう一度見てみると、条件は厳し目で、通常ホビーレベルで監視を実行している人だとあまりお世話にならなそうな感じだ。自分でカスタマイズしている人は、それなりに確認すること。

最後にUserParameterの日本語の1.8のドキュメントを挙げておく。面白くないことに2.0以降、日本語のドキュメントはほぼない状態だ (というかjaじゃなくてjpなのか)
https://www.zabbix.com/documentation/jp/1.8/manual/config/user_parameters

2.2の英語ドキュメントはこちら。上記の特殊文字は無視される、と現時点でのドキュメントには記載があるが、今後この文面は変更されるだろう。
https://www.zabbix.com/documentation/2.2/manual/config/items/userparameters

このブログの人気の投稿

LibreOfficeで表紙、目次、本体でフッターのページ番号のスタイルを変える

WiiUのコントローラが通信不良に陥った話

技術書典2 あ-03 『もわねっとのPythonの本』