つい数時間前に存在を知りました。
某ニュースサイトとかで「マジやべえ今すぐ対処しないと死ぬぞ」みたいなことを書かれていたので超焦っていたのですが、かくかくしかじかの理由で独自パッチの作成を検討するために https://www.qualys.com/research/security-advisories/GHOST-CVE-2015-0235.txt の報告書を読んでいたところ、そこまで超ヤバい急ぎの要件でもなくね? みたいな感じになったので共有します。
なお、私の英語力がヤムチャレベルであること、ネットワークやLinuxシステムに関わる知識がチャオズレベルであること、急ぎの翻訳なので他の節はほとんど読めていないこと、あくまで2014年1月28日時点での情報であること、などの理由から誤解、誤訳が含まれている可能性があります。
参照するのはあくまで元の報告書をベースにして、あとは自己責任でよろしくお願いします。なお公開していることで悪影響があるような誤訳、誤解は随時修正していくつもりなので間違いはバンバン指摘してもらえるとありがたいです。
以下、"GHOST: glibc gethostbyname buffer overflow"の"3 - Mitigating factors"の節の翻訳です。
ChangeLog
3 - 問題を緩和する要素
このバグの影響は、以下の理由で大幅に軽減されます。
理由:
- 2013年5月21日時点でパッチがすでに存在している(2013年8月12日にリリースされたglibc-2.18)。そしてそのパッチはすでに2013年の8月12日の適用以降から、テスト(ユーザに利用)されているということ。
[BZ #15014] * nss/getXXbyYY_r.c (INTERNAL (REENTRANT_NAME)) [HANDLE_DIGITS_DOTS]: Set any_service when digits-dots parsing was successful. * nss/digits_dots.c (__nss_hostname_digits_dots): Remove redundant variable declarations and reallocation of buffer when parsing as IPv6 address. Always set NSS status when called from reentrant functions. Use NETDB_INTERNAL instead of TRY_AGAIN when buffer too small. Correct computation of needed size. * nss/Makefile (tests): Add test-digits-dots. * nss/test-digits-dots.c: New test.
IPv6アドレスの出現によって、gethostbyname*() 関数はすでに非推奨です。
最近のアプリケーションは、getaddrinfo()を代わりに使用しています。ローカル到達可能な多くのプログラム、特にSUIDバイナリですが、gethostbyname()はinet_aton()が失敗した場合にだけ予備的に呼ばれます。
しかしながら、バッファオーバーフロー(訳注: 今回の脆弱性の引き金)を引き起こすためには、(__nss_hostname_digits_dots内部で呼ばれている)inet_atonを成功("inet-aton requirement(訳注: 第2節を参照)"を満たす)必要があります。
これは不可能です。したがってこれらのプログラムは、安全です。リモートから到達可能な他のプログラムのほとんど、特にサーバーですが、forward-comfirmedな逆引きDNS(FCrDNS: "full-circle reverse DNS" として知られる)を実行するためにgethostbyname()を使っています。
これらのプログラムは基本的に安全です。何故なら、このgethostbyname()に渡されたホスト名は、通常DNSのソフトウェアによって事前に値をチェックされているからです。
というような感じです。
もちろん重大な脆弱性であることは事実であるとおもいますが、現状としてはそれを突くのが難しいといった形で、ある程度の余裕をもって対処出来るかなとおもいました。
補足
そもそも脆弱性が見つかった関数
nss/digits_dot.c
にある__nss_hostname_digits_dots()
という関数。"inet-aton requirement" とは
抜粋です。ちゃんと理解するためには"2 Analysis"の全文を読んだ方がいいっぽいです。
「数値とドットで構成された」ホストネームをinet_pton()でIPv6としてパースすることは不可能です。
したがって、もしもIPアドレスファミリーがAF_INET6
だった場合は、gethostbyname2()
とgethostbyname2_r()
を使ってオーバーフロー脆弱性を突くのは不可能です。Conclusion: inet_aton() is the only option, and the hostname must have one of the following forms: "a.b.c.d", "a.b.c", "a.b", or "a", where a, b, c, d must be unsigned integers, at most 0xfffffffful, converted successfully (ie, no integer overflow) by strtoul() in decimal or octal (but not hexadecimal, because 'x' and 'X' are forbidden).