メモ:curlの国際化ドメイン名関連のバグ・CVE-2016-8625

curlの中の人がこんなことを言ってます。

IDN(Internationalizing Domain Names; 国際化ドメイン名)っていうのはあれです。「こっち.みんな」みたいなドメイン名のことです。それのサポートをやめるってどういうこと??と思ったのでメモ。

事の発端はこのバグです。

cURL - IDNA 2003 makes curl use wrong

For example, straße.de is translated into strasse.de using IDNA 2003 but is translated into xn--strae-oqa.de using IDNA 2008. Needless to say, those host names could very well resolve to different addresses and be two completely independent servers. IDNA 2008 is mandatory for .de domains.

IDNには、IDNA 2003とIDNA 2008という互換性のない2つの規格があって、curlが使ってるのは古いほうのIDNA 2003に基づくライブラリだったので変換に失敗するドメイン名がある、と。変換がうまくいかない文字の例として、UTS #46: Unicode IDNA Compatibility Processingというドキュメントに以下のような表があります。

f:id:yutannihilation:20161102225708p:plain:w450

このUnicodeのレポートは、冒頭から、

Client software, such as browsers and emailers, faces a difficult transition from the version of international domain names approved in 2003 (IDNA2003), to the revision approved in 2010 (IDNA2008).

とか書いてあってつらさを漂わせています。ただちょっと全部読むには長いので、手短には以下のJPRSのページが参考になります。

ここに挙げられているものの中に、

IDNA2003は国際化ドメイン名として入力された文字列の正規化(大文字小文字や全角半角文字の統一、文字の合成など)はプロトコルの一部として方式を規定していますが、IDNA2008は国際化ドメイン名として入力された文字列は正規化されていることを前提としておりプロトコルでは正規化の方式を規定していません(正規化はアプリケーションの責任としています)。

と書いてあります。実は、curlは以下のコミットでIDNA 2008をサポートするライブラリ(libidn2)に切り替えたんですが、このあたりの前提を勘違いしていたらしくてうまく動かない、ということのようです。

github.com

で、古い実装は不完全だから切り戻すこともできないし、新しい実装はまだバグってるし、ということで「とりあえずIDNをオフってくれ」と言うに至ったらしい。なるほどなあ...。つらそう。