glibc: __nss_hostname_digits_dots() の脆弱性について

no extension

ふぅ。 やっと仕事が一段落したんで溜まった宿題を片付けていくか。

バッファオーバーフローが発見された関数は__nss_hostname_digits_dots()だが、ユーザランドのソフトウェアからはgethostbyname()などの関数を呼び出すことでこの関数が実行される。このため、gethostbynameをGetHOSTbynameともじって「GHOST」と命名されている。
Qualysの研究者によると、2013年の時点でこの脆弱性を発見して、glibc-2.17とglibc-2.18の間において修正を行っているが、当時はセキュリティに関わるリスクとしては認識されていなかったため、長期サポートの対象となっているバージョンのLinuxディストリビューションではこの脆弱性が修正されることなく残り続けているという。
Linuxできわめて重大で危険な脆弱性「GHOST」を確認より

NVD ではこの脆弱性の CVSS 値を 10.0(AV:N/AC:L/Au:N/C:C/I:C/A:C)と評価している。 脆弱性を報告した Qualys では

The gethostbyname*() functions are obsolete; with the advent of IPv6, recent applications use getaddrinfo() instead.
via GHOST: glibc gethostbyname buffer overflow

としていて,実際に影響のあるアプリケーションは多くないと見ているようだ(Exim を運用しているサーバは早急に対応が必要)。 こちらはトレンドマイクロの記事。

すべてのアプリケーションが等しく危険にさらされているわけではありません。この脆弱性の攻撃において攻撃者が利用できるのは4バイトもしくは 8バイトのエクスプロイトコードであり、実行できることは非常に限られています。この攻撃に利用できるバイト数は OS が 32ビット版か 64ビット版かで異なります。追加のコードは、変更可能なポインタに参照されるアドレスに攻撃者が脆弱性とは別の方法で書き込んで置かなければなりません。また、apache や postfix、OpenSSH など、多くの有名アプリケーションがこの脆弱性の影響を受けないことも確認されています。これまでのところ、トレンドマイクロでは、Web攻撃に利用される可能性のある感染媒体を確認しておらず、そのため攻撃の可能性はかなり低いものと考えられます。
Linuxに存在する脆弱性「GHOST」、システム管理者は落ち着いて対処をより

対策としては glibc-2.18 (以上)にアップデートすればよい。 glibc を取り込んでいるアプリケーションについては再コンパイルが必要かもしれない。 更新を確実に反映させるには再起動が必要。 したがって,特にサーバは,きちんと計画した上で更新を行う必要がある。 (慌てるなんとかは貰いが少ない)

対象のシステムが今回の脆弱性に該当しているかわからない場合は,以下の検証コードをコンパイル・実行すると良い。

#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);
}
view raw GHOST.c hosted with ❤ by GitHub
via GHOST: glibc gethostbyname buffer overflow

GitHub でも公開されているので参考にどうぞ。

気をつけるべきはルータやスイッチなどのファームウェアだろう(特に古いもの)。 JVN に日本製品の情報があるので注意すること。 (つっても殆ど無いけど)

とりあえず,こんなとこかな。 今回は,最初こそ騒がれたものの(私もびっくりした),だんだんトーンダウンしていくプロセスが面白い。 まぁ,こういうこともあるよね。