読者です 読者をやめる 読者になる 読者になる

風柳メモ

ソフトウェア・プログラミング関連の覚書が中心。

脆弱性案件はかわいいGHOSTの夢を見るか?

glibcのgethostbyname系関数にバッファオーバーフローを引き起こす重大な脆弱性(CVE-2015-0235)が発見されたとして騒ぎになっている。

The Laws of Vulnerabilities: The GHOST Vulnerab... | Qualys Community
Qualys Security Advisory CVE-2015-0235
glibc の脆弱性 CVE-2015-0235(通称:GHOST)についてまとめてみた - piyolog
glibcのgethostbyname関数に存在するCVE-2015-0235(GHOST)脆弱性について - ブログ - ワルブリックス株式会社
JVNVU#99234709: glibc ライブラリにバッファオーバーフローの脆弱性
glibc の脆弱性対策について(CVE-2015-0235):IPA 独立行政法人 情報処理推進機構

こちらの記事には、RedHat Enterprise Linux・CentOS・Debian GNU/Linux等の対処方法も書かれている

脆弱性の概要

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


この glibcに含まれる gethostbyname系関数の実装に 2000年頃から存在したバグが今になって発見され、CVE-2015-0235 通称 GHOSTと命名されました。ネットワークで何らかの通信を行うアプリケーションは必ずこの関数を使用します。

glibcのgethostbyname関数に存在するCVE-2015-0235(GHOST)脆弱性について - ブログ - ワルブリックス株式会社

今回発見されたglibcの問題は、攻撃者がリモートから細工されたホスト名文字列を(例えばURLのホスト名部分などに埋め込んで)与えることによって、アプリケーション側のメモリを数バイト上書きできてしまうことです。

実際に、Exim(メールサーバ)に対して攻撃を行い任意コードの実行が出来る実証コードを作成できたそうです。32bit/64bitの両方が攻略可能で、CPUの不正命令実行防止機構(ASLR, PIE, and NX)は役に立たないとのこと。

glibcのgethostbyname関数に存在するCVE-2015-0235(GHOST)脆弱性について - ブログ - ワルブリックス株式会社

ということで、少なくともLinuxを用いている場合には*1早々に確認の上、必要に応じて対応しなければならない。


……のだが。


え、これは……?

「GHOST」という通称(GetHOSTbynameに由来)もさることながら

GHOST vulnerability

The Laws of Vulnerabilities: The GHOST Vulnerab... | Qualys Community

用意されたこのアイコンのせいで、事態の深刻さと比較して、どうにも危機感が薄まってしまうのは否めない。


これは孔明の罠か?……いやいや、惑わされてはならない。きちんと確認の上、対応しなければ。

脆弱性の確認方法

基本的には、

Qualys Security Advisory CVE-2015-0235

中にある、GHOST.cをコンパイル・実行すると、"vulnerable"か"not vulnerable"か(実行したシステムが脆弱か否か)が表示されるので、"vulnerable"だった場合には対応が必要となる。


ただ、自分のような英弱には、"vulnerable"という単語を見て、即座に「危険だ!」と判断することは困難である。
そこで、脆弱性があった場合の結果を目立たせるように簡単なパッチをあててみた。

ghost.c
#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 };

void ghost(void) {
  int a, b=0, c=10; for (; (a="!nBACAAUBJBPAOANAQALAFBFBCAJAFDDDBCHATBIACAFMGAESFAKCAAHACCEGADBDBAEBLMGCRANCBHBBE"[b++]);) for(;64 < a--;) putchar((++c == 42) ? (c-=32) : (32^(b&1)));
  puts("GHOST IN THE SHELL\n");
}

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");
    ghost();
    exit(EXIT_SUCCESS);
  }
  if (retval == ERANGE) {
    puts("not vulnerable");
    exit(EXIT_SUCCESS);
  }
  puts("should not happen");
  exit(EXIT_FAILURE);
}
CVE-2015-0235_GHOST/ghost.c at develop · furyutei/CVE-2015-0235_GHOST · GitHub

これを使用しているシステムでコンパイルして

$ gcc -o ghost ghost.c

実行すると、該当する脆弱性がある場合には、

$ ./ghost

              !! !!! !
           !!          !!
         !               !
        !                 !
       !      !!      !!   !
      !      !!!!    !!!!  !!!
      !                    !!
      !   !      !!!!!!!!!!!!!
     !     !!!!!!!!!!!!!!!!!!!
    !           !!! !        !
 !!!     !!!!!!! !!!!  !!!!  !
   !!            !!!!!!!!!!!!!
     !!!                  !
         !!!  !!!!!!!!  !!     GHOST IN THE SHELL

$ 

このように一目でわかるので、迅速な対応が可能になると思われる。適宜活用されたし。

などと、まじめに対応するつもりでもついついネタに走りたくなってしまうので、脆弱性案件にかわいい通称やアイコンはよくない。

追記:GitHubにも登録

mholzinger/CVE-2015-0235_GHOST · GitHub

をForkさせてもらい、

furyutei/CVE-2015-0235_GHOST at develop · GitHub

上のファイルを読み込んで実行できるようになった。

wget で実行
$ wget -q -O - "https://raw.githubusercontent.com/furyutei/CVE-2015-0235_GHOST/develop/build_aa.sh" | bash
not vulnerable
curl で実行
$ curl -skL "https://raw.githubusercontent.com/furyutei/CVE-2015-0235_GHOST/develop/build_aa.sh" | bash
not vulnerable

*1:GNU glibcの問題なので、Linux以外でも影響する場合はある