インターネットの危機:ISC BINDパッチの分析(第1部)

Internet Systems Consortium(インターネットシステムズコンソーシアム、以下ISC)が先日、世界で最も広く利用されているDNSサーバーソフトウェアのいくつかの問題を修正する新しいパッチ(バージョン9.10.3-P4)を公開しました。

このパッチのリリースノートは、https://kb.isc.org/article/AA-01363/81/BIND-9.10.3-P4-Release-Notes.htmlに公開されています。

2部構成のこの記事では、今回のパッチの対象となった脆弱性に対するフォーティネットの調査を詳しく説明し、フォーティネットのソリューションによる検出方法を広く導入することでお客様の環境をどのように保護できるかを解説します。

ISCは、BIND rndc制御チャネルのDoS脆弱性(CVE-2016-1285)を修正するパッチを公開しました。ISCによると、この脆弱性は、namedと呼ばれるアプリケーションにおいて、制御チャネルで不正パケットを受信した時に発生する異常終了に起因するものです。

rndcは、制御チャネルに要求を送信することでBIND DNSサーバーを制御するように設計されたユーティリティです。以下に、正常なrndc要求のイメージを示します。

このイメージでわかるように、この要求には、_auth_ctrl、および_dataを含む複数のレコードが含まれています。レコード_authは、rndcクライアントの認証に使用されます。サブレコードhmd5は、_authに含まれており、dnsサーバーに対してhmac-md5ダイジェストを認証に使用するよう指示します。_ctrlには、3つのサブレコード、すなわち、_ser(この要求のシリアル番号)、_time(rndcクライアントの現在の時刻)、および_exp(この要求の期限切れ時間)がネストされています。レコード_dataは、この要求の操作を指定しています。このパケットでは、operationフィールドがnullであり、これは、接続の初期化に使用されるものです。

DNSサーバーは、構造体iscc_sexprを使用して、上記のレコードとサブレコードを格納します。この構造体の定義は以下のとおりです。

struct isccc_sexpr {
    unsigned int type;
    union {
        char *as_string;
        isccc_dottedpair_t as_dottedpair;
        isccc_region_t as_region;
    } value;
};

コードに定義されているタイプは以下のとおりです。

#define ISCCC_SEXPRTYPE_NONE                    0x00
#define ISCCC_SEXPRTYPE_T                       0x01
#define ISCCC_SEXPRTYPE_STRING                  0x02
#define ISCCC_SEXPRTYPE_DOTTEDPAIR              0x03
#define ISCCC_SEXPRTYPE_BINARY                  0x04

この脆弱性は、iscc_sexprのtypeエレメントの解析時のエラーチェックの欠如によるものです。特別な形式で作成したrndc要求を送信することで、正しくないタイプ値をこの構造体iscc_sexprのレコード_authまたは_ctrlに設定でき、それによって、その後の手順でnamedにおいて異常終了の条件が発生することになります。

以下のコードスニペットは、BIND version 9.10.3-P3ソースコードから取得したもので、コードのフローを説明するコメントが追加されています。

cc.c:

383     static isc_result_t
384     verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length,
            isc_uint32_t algorithm, isccc_region_t *secret)
//This function verifies the hmd5 digest
            {
...
...

405                 _auth = isccc_alist_lookup(alist, "_auth");
//It looks for the sexpr structures of _auth by calling function isccc_alist_lookup, then isccc_alist_assq which are defined in alist.c

alist.c:

107     isccc_sexpr_t *
108     isccc_alist_assq(isccc_sexpr_t *alist, const char *key)
            {
                        isccc_sexpr_t *car, *caar;
112                 REQUIRE(isccc_alist_alistp(alist)); 
//isccc_alist_assq requires isccc_alist_alistp to return ISC_TRUE, but the following code (line 79) returns ISC_FALSE, which means assertion failure

alist.c:

74       isc_boolean_t
75       isccc_alist_alistp(isccc_sexpr_t *alist)
            {          
                        isccc_sexpr_t *car;
79                   if (alist == NULL || alist->type != ISCCC_SEXPRTYPE_DOTTEDPAIR)
                                    return (ISC_FALSE);

この脆弱性コードに到達するには、要求を周到に準備して複数の評価をnamedで渡すようにする必要があります。異常終了時のnamedでのスタックトレースを以下に示します。

この脆弱性を悪用するにあたり、認証は必要ありません。

フォーティネットが実施した分析で、この脆弱性をエスカレーションしてリモートコードを実行することはできないことが確認されました。

フォーティネットは、この脆弱性から保護するための、IPSのシグネチャISC.BIND.rndc.Control.Channel.Input.Handling.DoSを公開しました。

第2部では、CVE-2016-1286とCVE-2016-2088の脆弱性について解説する予定です。

Dehui Yin、FortiGuard Lion Team