「EximのGHOST脆弱性の影響とバリデーションの関係」への疑問

徳丸さんが日記で以下の記事を公表されました。

いつも緻密な記事を書かれる徳丸さんですが、この記事には少々疑問が残りましたので、疑問点をあげておきたいと思います。

誤りなどありましたら、どなたでも根拠とともにご指摘ください。

(2015-02-05 追記) 大垣さんは自身のブログで以下のようにコメントされていました。

徳丸さんは私がIPアドレスと書いたので間違っているかのような書き方をしていましたが、RFCで明確にドメイン名形式またはIPアドレス形式と書いており、gethostbynameもこの仕様にそった実装になっているのでドメイン名形式とIPアドレス形式を明確に区別することにあまり意味はありません。
http://blog.ohgaki.net/how-to-validate-ipv4-host-names

疑問点

まず、この記事の核となる主張に以下があります。

攻撃経路となる入力値はIPアドレスではなくホスト名である

そして、大垣さんが「これをIPv4形式のIPアドレスと誤認」しているが「これは間違い」と断定しています。

果たしてこのように単純に間違いと言いきれるのでしょうか?以下の疑問が生じました。

本当に攻撃経路となる入力値はIPアドレスではなくホスト名と言えるのか?

以下に理由を述べます。

(1) gethostbyname()はIPアドレスも受け取る

記事では、

gethostbyname()が受け取る引数もbynameとあるようにホスト名

と説明されています。確かにgethostbyname()はホスト名から情報を取得するものですが、ホスト名以外にもIPアドレスを受け取ることも想定されています。manページには「ドット区切りのIPv4アドレス」も明記されています。

gethostbyname() 関数は与えられたホスト名 name に対応する構造体 hostent を返す。 name にはホスト名、ドット区切りの IPv4 アドレス (inet_addr(3) 参照)、コロン区切りの IPv6 アドレス (おそらくドット区切りでも大丈夫) のいずれかを指定する (IPv6 アドレスの記述方法については RFC 1884 を参考にしてほしい)。name が IPv4 か IPv6 のアドレスだった場合、 名前解決 (lookup) は行われない。
http://linuxjm.sourceforge.jp/html/LDP_man-pages/man3/gethostbyname.3.html

(2) SMTPのHELOコマンドもIPアドレスを受け取る

こちらもホスト名でなくIPアドレスが入力される場合があります。ただし、SMTPの仕様ではIPアドレスの場合、[ ]で囲む必要があります(アドレスリテラル)が。

EHLO コマンド内で与えられるドメイン名は、主要なホスト名(アドレス RR を決定するドメイン名)か、ホストが名前を持たない場合にはアドレスリテラル(セクション 4.1.3 で説明され、セクション 4.1.4 の EHLO の考察においてさらに議論されている)か、どちらかでなければならない(MUST)。
http://srgia.com/docs/rfc5321j.html#p2.3.5

(3) そもそもホスト名にはIPアドレスも入力できる

RFC1123によれば、

Whenever a user inputs the identity of an Internet host, it SHOULD be possible to enter either (1) a host domain name or (2) an IP address in dotted-decimal ("#.#.#.#") form. The host SHOULD check the string syntactically for a dotted-decimal number before looking it up in the Domain Name System.

参考訳:

ユーザがインターネットホストの身元を入力する場合は常に、次のいずれかの入力を可能にすべきである (SHOULD)。(1) ホストドメイン名、(2) ドット付き 10進数字 ("#.#.#.#") 形式の IP アドレス。ホストは、ドット付き 10進数字番号の文字列をドメイン名システムで検索する前に、シンタックス上のチェックを行うべきである (SHOULD)。
http://www2s.biglobe.ne.jp/~hig/tcpip/HostReq_Appl.html#HREQAPP_2_1

とあります。「ホストドメイン名」または「ドット付き10進数字形式のIPアドレス」を入力可能にすべきとされています。

(4) 数字のみのドメイン名は存在しない

現在、数字とドットのみのドメイン名は存在しません。トップレベルドメインには必ずアルファベットが含まれています。

存在しないものを「ホスト名」と呼ぶのは少々疑問が残ります。

(5) 攻撃経路となる入力値はIPアドレスと考えるべきではないか?

Qualysの発表したEximに対する攻撃手法によると、脆弱性があった関数の目的はすでにIPアドレスである引数の場合にコストの高いDNS検索をしないことです。

The purpose of this function is to avoid expensive DNS lookups if the hostname argument is already an IPv4 or IPv6 address.

攻撃条件の「数字とドットのみ」というのは、少なくとも脆弱性があったこの関数の中では、それがIPアドレスかどうかを判定するための条件と考えられます。

結論

以上(1)~(5)のように、攻撃経路となる入力値はホスト名ではなくIPアドレスではないか?という疑問が生じます。

これを「IPアドレス」であると考えるならば、その場合にIPアドレスとしての入力値に対してIPアドレスとしての形式をチェックするバリデーションを実施するというアプリケーション仕様も考えられます。

そして、そのようなバリデーションを実施していれば、今回のEximのGHOST脆弱性は防げていたという主張にとくに問題はないように感じました。

Date: 2015/02/04

Tags: security, validation