MySQL脆弱性 CVE-2016-6662 について (2016 09 13現在)
これは何
MySQLにリモートでコード実行される可能性のある脆弱性 CVE-2016-6662 が発覚。その概要と対応をまとめる。
目次
- これは何
- 目次
- 資料
- 対象バージョン
- ざっくり言うと?
- 設定ファイルが書き換えられるとなぜ攻撃になる?
- 今回の脆弱性
- my.cnfに追記する
- ファイルが無い状態から作る
- 対応方針案
資料
CVE-2016-6662 http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.html
対象バージョン
2016 09 13日現在の全てのバージョン。 具体的に言うと、現時点での最新のバージョンの以下を含む、それ以前のバージョンに脆弱性が存在。
- 5.7.15
- 5.6.33
- 5.5.52
要するにパッチがまだない。 MySQL cloneの MariaDBとPerconaDBにも影響。
ざっくり言うと?
SQLインジェクションを使って、 my.cnf を上書きできる。 攻撃するには以下の条件が必要
- SQLインジェクションができること
- /etc/my.cnfがmysqlユーザから書き換えられるパーミッションになっていること または その他my.cnfの置けるディレクトリにmysqlユーザが書き込み権限があること
設定ファイルが書き換えられるとなぜ攻撃になる?
mysqld_safeがrootプロセスで起動して、mysqldプロセスがmysqlユーザに落として起動される。mysqld_safeのスクリプト(配置場所によるが、例えば /usr/local/mysql/bin/mysqld_safe)のset_malloc_lib()でshared library がmysqlサーバ起動前に読み込まれて--malloc-lib=LIB へセットされる。 設定ファイルを書き換えられるということは、この変数で読み込む値を my.cnfの [mysqld]か[mysqld_safe]セクションで好きに設定できるということ。そうすると、任意のライブラリ(任意コード)がmysqlサーバ起動時にroot権限でされる(mysqld_safe実行時なので)。 3.23.55以前のバージョンだと
SELECT 'malicious config entry' INTO OUTFILE '/var/lib/mysql/my.cnf'
このコマンドでファイルが作れて、設定ファイルとして読み込むことができる。ファイル作成の例としては /tmp/ 下に作成してみると
$ mysql -uroot -p -e "SELECT 'malicious config entry' INTO OUTFILE '/tmp/my_temp'" $ ls -ltr /tmp/my_temp -rw-rw-rw- 1 mysql mysql 23 Sep 13 16:50 /tmp/my_temp $ cat /tmp/my_temp malicious config entry
今はこの脆弱性は修正されている。MySQLは 0666 permissionsのファイル(というかotherに書き込み権限がある場合)を設定ファイルとして読み込まないようになっている。具体的には以下のエラーが出て読み込まない。
Warning: World-writable config file '/etc/my.cnf' is ignored
しかし、MySQL logging関数で出力されたファイルは 0660 になっているので、設定ファイルとして読み込むことができる。これが今回の問題
今回の脆弱性
my.cnfに追記する
仮に my.cnfが以下の様なmysqlユーザの持ち物だった場合(例えば以下のようなパーミッションだった場合)
root@debian:~/# ls -l /etc/my.cnf -rw-r--r-- 1 mysql mysql 72 Jul 28 17:20 /etc/my.cnf
以下の内容をファイルに追記できる。
mysql> set global general_log_file = '/etc/my.cnf'; mysql> set global general_log = on; mysql> select ' '> '> ; injected config entry '> '> [mysqld] '> malloc_lib=/tmp/mysql_exploit_lib.so '> '> [separator] '> '> '; mysql> set global general_log = off;
ファイルが無い状態から作る
/etc/ 以下にmy.cnfが無い場合には、/etc/ ディレクトリのパーミッションで縛られる。root かつ 0644 だったばあいには mysqlユーザは作ることができない。 どのようなファイルが作られるか、/tmp/以下で試してみる。この方法で作られたファイルは以下のようなPermissionになる 。
$ ls -ltr /tmp/my_temp.txt -rw-rw---- 1 mysql mysql 685074 Sep 13 16:33 /tmp/my_temp.txt
しかし、この脆弱性だけでは、my.cnfに loggingの最初の行(version情報など)が入ってしまい、設定ファイルとして機能しない。 さらに他の脆弱性 CVE-2016-6663 (2016 09 13現時点では詳細非公開) を使用すると、(余計な情報を消して?)FILE権限なしに、任意の内容を書き込むことができる。
一次対応策
MySQL 5.5だと以下のような設定ファイルが置ける 参考: http://dev.mysql.com/doc/refman/5.5/en/option-files.html
/etc/my.cnf Global options /etc/mysql/my.cnf Global options SYSCONFDIR/my.cnf Global options $MYSQL_HOME/my.cnf Server-specific options defaults-extra-file The file specified with --defaults-extra-file=file_name, if any ~/.my.cnf User-specific options
- /etc/my.cnf がmysqlユーザで書き込み権限がないこと(例えば rootで 0644 )を確認する
- /usr/local/mysql 直下が mysqlユーザの書き込み権限がないこと (例えば以下のようになっていること。mysqlユーザはここにmy.cnfを配置できない)を確認する
$ ls -ltrd /usr/local/mysql/ drwxr-xr-x 13 root mysql 4096 Sep 13 17:27 /usr/local/mysql/
- ファイルを置く権限がある場合には、 root パーミッションで作った my.cnf をダミーとして置いておく。作成も上書きも出来ないように。
- /etc/mysql/ ディレクトリが存在しないことを確認する
- /etc/sysconfig/ が mysql ユーザの権限がないことを確認する
$ ls -ltrd /etc/sysconfig/ drwxr-xr-x. 7 root root 4096 Sep 13 17:17 /etc/sysconfig/
- extra fileとして /home/simainte/my.cnf がある場合はそれが root 0600 になっていることを確認する
- /home/mysql/ に root 0600 で my.cnfを配置しておく。または /home/mysql/ を削除する
根本対応
パッチはまだない。mysqld_safe で shared_libraryを読み込まないという手もある。