glibcのgethostbyname関数に存在するCVE-2015-0235(GHOST)脆弱性について

Linux 2015年1月28日

glibcのgethostbyname系関数に脆弱性の原因となるバグが発見されCVE-2015-0235(GHOST)と命名されたようです。相当多くのアプリケーションがこの脆弱性の影響を受けることが予想されます。

glibcは libcのGNUバージョンです。libcはアプリケーションではなく、事実上全てのアプリケーションが利用しているライブラリです。OSの中ではカーネルに次いで重要な部分と言えます。Linuxシステムでは例外なく glibcが使われています。

この glibcに含まれる gethostbyname系関数の実装に 2000年頃から存在したバグが今になって発見され、CVE-2015-0235 通称 GHOSTと命名されました。glibcのバージョン 2.17と2.18の間でこのバグは修正されているのですが(現在の最新版は2.20)、多くの Linuxシステムではバージョン2.17未満の glibcが使用されており脆弱性の影響を受けます。例えば RedHat Enterprise Linux(と CentOS) 6.6は glibc 2.12を使用していますし、Debian Wheezyは glibc 2.13を使用しています。

RedHat Enterprise Linux と CentOSでの対策

RedHat社による glibc セキュリティアップデートの情報

yumコマンドで glibcをアップデートしてください。

yum update glibc

これを書いている時点ではまだ CentOSにはアップデートが来ていないようです。CentOSのフォーラムにおけるやりとり を意訳すると、

  • RedHat社から修正版のソースがリリースされるのを待つ
  • 修正されたglibcをビルドする (でかいので時間がかかる)
  • ↑しかも32bitと 64bitの両方やんなきゃいけない
  • 誰かFOSDEMに行かない奴を探し出してバイナリパッケージに署名してもらう
  • ミラーにプッシュして反映されるのを待つ

という長い道のりがあるようで・・・。

Debian GNU/Linux での対策

Debianによる CVE-2015-0235 についての情報

apt-getコマンドで glibcをアップデートしてください。

apt-get update
apt-get upgrade glibc

再起動は必要?

共有ライブラリを更新しても、既に起動しているアプリケーションはまだ古いコードを読み込んだまま動作しているはずなので、脆弱性の影響を受ける可能性のあるアプリケーションは全て再起動するべきだと思います。といっても、かなり多くのアプリケーションが gethostbyname系の関数を使用しているでしょうから、万全を期するならシステムごと再起動したほうが良さそうです。

glibcはC言語のライブラリだから (Perl/PHP/Python/Ruby ...)のアプリケーションは大丈夫だよね?

残念ながらそれらの言語も結局内部ではC言語のAPIを呼び出すことで動いているので大丈夫ではありません。

具体的には脆弱性によって何が引き起こされる?

今回発見されたglibcの問題は、攻撃者がリモートから細工されたホスト名文字列を(例えばURLのホスト名部分などに埋め込んで)与えることによって、アプリケーション側のメモリを数バイト上書きできてしまうことです。といっても任意の値で上書きできるわけではないので、それで具体的に何ができるかというと何でも出来るわけではないと思うのですが、アプリケーションによっては任意コードの実行につなげることが出来てしまうだろうと予想されています。C言語のコードが読める方でスタックやらヒープやらのマップが脳内に描ける人はこの後に引用しているコードから想像して下さい。

自分のシステムが脆弱かどうかを調べるには?

調査用のプログラムをコンパイル・実行してください。

oss-security - Qualys Security Advisory CVE-2015-0235 - GHOST: glibc gethostbyname buffer overflow から引用

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define CANARY "in_the_coal_mine"

struct {
  char buffer[1024];
  char canary[sizeof(CANARY)];
} temp = { "buffer", CANARY };

int main(void) {
  struct hostent resbuf;
  struct hostent *result;
  int herrno;
  int retval;

  /*** strlen (name) = size_needed - sizeof (*host_addr) - sizeof (*h_addr_ptrs) - 1; ***/
  size_t len = sizeof(temp.buffer) - 16*sizeof(unsigned char) - 2*sizeof(char *) - 1;
  char name[sizeof(temp.buffer)];
  memset(name, '0', len);
  name[len] = '\0';

  retval = gethostbyname_r(name, &resbuf, temp.buffer, sizeof(temp.buffer), &result, &herrno);

  if (strcmp(temp.canary, CANARY) != 0) {
    puts("vulnerable");
    exit(EXIT_SUCCESS);
  }
  if (retval == ERANGE) {
    puts("not vulnerable");
    exit(EXIT_SUCCESS);
  }
  puts("should not happen");
  exit(EXIT_FAILURE);
}

上記を GHOST.c という名前で保存し、

gcc -o GHOST GHOST.c

でコンパイル(GHOSTという名前の実行ファイルが生成される)したのちに

./GHOST

として実行してください。vulnerable(脆弱)か not vulnerable(脆弱でない)かが表示されます。コンパイラの入っていない(インストールできない・したくない)環境の場合は、他のマシンでコンパイルして実行ファイルだけコピーすれば良いでしょう。当然ですが 64bit OS上でコンパイルした実行ファイルは32bit OS上で動かないので注意して下さい。どうしても 32bit環境で動作する実行ファイルを64bit環境で作りたければ gccに -m32 オプションをつけてください。

同じカテゴリの記事

DFSがどうこうと言われて Sambaの共有にアクセスできなくなった時の対処 2015年1月21日
Linuxをクラッシュさせられるバグが権限昇格のバグに進化した件 2014年12月18日
Linux 3.18リリース 2014年12月8日
BASHの脆弱性でCGIスクリプトにアレさせてみました 2014年9月25日

お勧めカテゴリ

英語でアニメ観ようず
なじみ深い日本製アニメの英語版DVDで、字幕と音声から英語を学びましょうという趣旨のシリーズ記事です。
ScalaのようでJavaだけど少しScalaなJSON API
Scalaと Spring Frameworkを使って REST的なJSON APIを実装してみましょう。
ドクジリアン柔術少女 すから☆ぱいそん
代表 嶋田大貴のブログです。写真は神仏に見せ金をはたらく罰当たりの図