脆弱性BINDを使用すると、サーバーを「ドロップ」できます。その仕組みと理由





ほぼ1か月前の2017年1月11日、最も人気のあるオープンソースDNSサーバーBINDの開発者は、リモートの攻撃者がDNSサーバーをクラッシュさせる4つの新しい脆弱性に対する修正をリリースしました。 脆弱性にはCVE-2016-9147があり、これについては後で説明します。 攻撃には、攻撃者が脆弱なサーバーからのトラフィックを確認する必要がある場合を除き、特別な条件は必要ありません。



ネットワーク上のこれらの脆弱性の悪用を検出するルール(NAD)を作成することが目標でした。これを行うには、BINDコードをよりよく理解し、独自のエクスプロイトを作成する必要がありました。 この分析は、このような一般的なDNSサーバー内ですべてがどのように配置されているかを理解するのに役立ち、プロジェクト開発者によって行われた計算ミスとこれらの問題の可能な解決策について知るのに役立ちます。



問題は何ですか



最も危険なのは、DNSSECをサポートする再帰サーバーです。そのため、以下で再帰クエリのケースを検討します。



パッチの説明には、再帰的な要求に対するDNSSECレコードの特定の組み合わせがサーバーのサービス拒否、または単にクラッシュを引き起こす可能性があることが記載されています。 さらに、開発者は、このようなフィールドの組み合わせは通常のDNSトラフィックには見られないと付け加えています。



問題をさらに理解するには、このCVEの公開パッチを調べる必要があります。 このパッチは、DNS応答の処理を担当するモジュールの1つで数行のコードのみを修正します。



--- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -6984,15 +6984,19 @@ answer_response(fetchctx_t *fctx) { * a CNAME or DNAME). */ INSIST(!external); - if ((rdataset->type != - dns_rdatatype_cname) || - !found_dname || - (aflag == - DNS_RDATASETATTR_ANSWER)) + /* + * Don't use found_cname here + * as we have just set it + * above. + */ + if (cname == NULL && + !found_dname && + aflag == + DNS_RDATASETATTR_ANSWER) { have_answer = ISC_TRUE; - if (rdataset->type == - dns_rdatatype_cname) + if (found_cname && + cname == NULL) cname = name; name->attributes |= DNS_NAMEATTR_ANSWER;
      
      





ご覧のように、パッチは条件の論理エラーを修正します



 if ((rdataset->type != dns_rdatatype_cname) || !found_dname || (aflag == DNS_RDATASETATTR_ANSWER))  if (cname == NULL && !found_dname && aflag == DNS_RDATASETATTR_ANSWER)
      
      





have_answer



変数をtrueに変更するには、3つの式すべてが必要です。 これは、パッケージにリクエストへの応答が含まれているかどうかを判断するために必要です。







したがって、パッチからの条件が不完全に満たされると、脆弱性が悪用されることが明らかになります。 パッケージ内のどのレコードの組み合わせが操作に必要かを理解してみましょう。



エクスプロイトを作成します



次の短い条件により、脆弱なコードを使用してブランチにアクセスできます



 6968 if (found) {
      
      





found



変数は、 CNAME



またはDNAME



レコードを使用した名前のリダイレクト、タイプANY



を使用した要求への応答など、さまざまな種類の応答を処理する同じ関数の5つのコードブロックで設定されます。




 6891 if (rdataset->type == type && !found_cname) { 6892 /* 6893 * We've found an ordinary answer. 6894 */
      
      








 6899 } else if (type == dns_rdatatype_any) { 6900 /* 6901 * We've found an answer matching 6902 * an ANY query. There may be 6903 * more. 6904 */
      
      








 6907 } else if (rdataset->type == dns_rdatatype_rrsig 6908 && rdataset->covers == type 6909 && !found_cname) { 6910 /* 6911 * We've found a signature that 6912 * covers the type we're looking for. 6913 */
      
      








 6917 } else if (rdataset->type == 6918 dns_rdatatype_cname 6919 && !found_type) { 6920 /* 6921 * We're looking for something else, 6922 * but we found a CNAME. 6923 *
      
      








 6955 } else if (rdataset->type == dns_rdatatype_rrsig 6956 && rdataset->covers == 6957 dns_rdatatype_cname 6958 && !found_type) { 6959 /* 6960 * We're looking for something else, 6961 * but we found a SIG CNAME. 6962 */
      
      








パッチの説明の小さなヒントを思い出してください。



「名前付きは、要求されたデータがアサーション障害を引き起こすことなく、RRSIGレコードをカバーするいくつかの応答を誤って処理しました。 (CVE-2016-9147)」



これは、レコードの1つがRRSIG



なければならないことをRRSIG



ます。 RRSIG



は、応答内のDNSデータの整合性を保証するDNSSEC



メカニズムの1つです。 任意のタイプのレコード(A、AAAA、NS、DNAME、CNAMEなど)の場合、デジタル署名を含む対応するRRSIG



が応答で送信されます。 どのタイプのRRSIG



に署名が含まれているかを理解するために、 RRSIG



にはType Covered



フィールドがRRSIG



ます。







DNS応答でのRRSIGの検出には、5つの条件のうち2つだけが関連付けられています。



 6907 } else if (rdataset->type == dns_rdatatype_rrsig 6908 && rdataset->covers == type 6909 && !found_cname) { 6910 /* 6911 * We've found a signature that 6912 * covers the type we're looking for. 6913 */ 6914 found = ISC_TRUE; 6915 found_type = ISC_TRUE; 6916 aflag = DNS_RDATASETATTR_ANSWERSIG;
      
      





このチェックは、(リクエストを送信した)探しているレコードの署名を持つRRSIGを見つけるとトリガーされます。



 6955 } else if (rdataset->type == dns_rdatatype_rrsig 6956 && rdataset->covers == 6957 dns_rdatatype_cname 6958 && !found_type) { 6959 /* 6960 * We're looking for something else, 6961 * but we found a SIG CNAME. 6962 */ 6963 found = ISC_TRUE; 6964 found_cname = ISC_TRUE; 6965 aflag = DNS_RDATASETATTR_ANSWERSIG; 6966 }
      
      





この条件は最初の条件と似ています。RRNAMEレコードのみがCNAMEタイプをカバーする必要があります。



このエラーの操作には、ANSWER_SECTIONの単一のRRSIGエントリが必要であるとANSWER_SECTION



ます。 実際、この状況は通常のDNSトラフィックでは発生しません。なぜなら、 RRSIGを別のレコードに関連付けることはできません。



再帰DNSサーバーを使用してトポロジを再現し、単一のRRSIGレコードから再帰クエリに応答を送信しようとしています。再帰クエリは、CNAMEまたはDNSクエリのタイプを対象としています。







予想どおり、Namedデーモンの緊急シャットダウンが表示されます。







結果は何ですか



考慮される脆弱性は、操作するのに難しい条件を必要としないため、非常に単純で危険です。 BIND開発者は、その動作を妨害する可能性のある深刻なDNSサーバーの脆弱性を常に修正しています。



Positive Technologiesの専門家は、開発者によって排除されたすべての脆弱性を慎重に調査し、それらを実際の状態で再現し、IDSシグネチャを開発して悪用を検出しました。







攻撃検知手法研究グループスペシャリスト、キリル・シピュリンによる投稿

ポジティブテクノロジー



All Articles