本ブログは米国で2019年03月15日に公開されたUnit 42ブログ「DNS Tunneling: how DNS can be (ab)used by malicious actors」の日本語翻訳です。

 

悪意のある攻撃者は、ドメインネームサービス(DNS)をコマンド&コントロール(C2)用通信チャネルとして悪用してきました。またこのプロトコルはこのほかに、データを漏出させる目的でも悪用されてきました。DNS の悪用はC2に「ハートビート」接続のために通信するという用途からさらに広がっており、攻撃者はここ、悪意のあるデータやペイロードを被害者のシステムに侵入させる用途でもDNSを経由させています。Unit 42の研究でも、さまざまなタイプのDNS悪用についてこれまで明らかにしてきました。

DNSは、インターネットの重要かつ基本的なプロトコルで「インターネットの電話帳」とも呼ばれます。それはこのプロトコルがドメイン名をIPアドレスにマッピングする用途に使われていることが理由です。DNSにはこれ以外の用途も多数あり、その詳細は主要なRFC譲るものとしますが、DNSがどこででも利用されていること、多くの場合セキュリティが欠如していることが仇となって、プロトコルが当初想定していた用途を超えて、隠密にデータ通信・データ共有を行うための高度に洗練された手段を提供する結果になっています。

すでに述べたDNSの使用例のほかにも数々のツールが存在しています。そうしたツールを使えば、DNS上に隠れたチャネルを作成し、攻撃者が通信を隠したり、ネットワーク管理者が設定したポリシーを迂回したり、といったことが可能になります。よくある用途は、オープンにアクセス可能なDNSを使用して、ホテル、カフェなどのWi-Fi接続登録を回避することです。こうしたツールがGitHubなどの場所からオンラインで無料で入手でき、しかも使いやすいことは注目に値するでしょう。これらツールの詳細は本稿末尾の付録に記載します。

本稿では、DNSを悪用したデータ侵入・漏出の種類、方法、使用方法を紹介し、その防御メカニズムへの指針を示します。


DNS

DNSは、ポート53を使用します。ポート53は、システム、ファイアウォール、およびクライアントでほぼ常に開かれており、このポートを使ってDNSクエリを送信します。これらのクエリでは、一般的な伝送制御プロトコル(TCP)ではなくユーザーデータグラムプロトコル(UDP)を使用します。TCPで同等のクエリを行う場合と比較して、待ち時間、帯域幅、リソース使用量が少ないことがその理由です。UDPにはエラーやフロー制御機能はなく、データが完全に到着したことを確認するための整合性チェックもありません。

では、インターネットの利用(閲覧、アプリケーション、チャットなど)はどの程度信頼できるのでしょうか。UDP DNSクエリが最初に失敗すると(結局のところベストエフォート型プロトコルなので)、ほとんどのシステムでは何度か再試行します。その後複数回失敗すると、そこで初めてTCPにスイッチして再試行する場合があります。DNSクエリがUDPデータグラムのサイズ制限(通常DNSの場合は512バイトだがシステム設定によって異なる)を超えている場合にもTCPが使用されます。

以下の図1は、DNSがどのように機能するかの基本的なプロセスを示しています。クライアントは、特定のタイプ(通常はホストアドレスとしてA)を使用してクエリ文字列(この例ではmail.google[.]com)を送信します。なお、中間にあるDNSシステムが「google[.]com」の見つかる場所を特定する前に「.com」の場所を確認する必要があるかもしれませんが、その部分はこの説明では省略しています。

図1 単純化したDNSのプロセス図

名前がIPに解決された後はキャッシュを活用します。解決された名前からIPへの変換は、通常ローカルシステム(場合によっては中間DNSサーバー)に一定期間キャッシュされます。同じクライアントからの同じ名前に対する後続の問い合わせは、キャッシュが期限切れになるまでローカルシステムに残存します。もちろん、一度リモートサービスのIPアドレスが分かれば、アプリケーションはその情報を使用し、HTTPなどほかのTCPベースプロトコルを使っての実作業を行えるようになります。たとえばネットで拾った猫のGIFアニメを同僚と確実に共有できるようになるわけです。

したがって、ほとんどのケースでは、組織のネットワークからの数十ほど余分にUDP DNSクエリが出ていてもほとんど目立ちません。そのため、DNSクエリを使って悪意のあるペイロードが攻撃者に送信される可能性があります。さらに、アプリケーションからリクエストを出してコマンドを受け取らせ、処理させることもさほど難しくはありません。

DNSがどのように動作するかを詳しく知りたい方は、こちらの記事を参考にしてください。このサイトでは、キーを入力して閲覧したいドメイン名をつづるところから説明してくれています。


データの痕跡

検索エンジンの結果からアクセスするにせよ、WebサイトのURLを直接アドレスバーに入力するにせよ、インターネットを閲覧すると何かしらの痕跡が残ります。これは、DNSクエリについても同じです。どれだけ痕跡が残るかは、オペレーティングシステムからクエリが送信され、結果のIPアドレスを受信するまでの間にどのようなシステムやプロセスが介在するかに依存します。

そこで、サーバー側のみに焦点を当て、DNSサーバー、なかでも拡張ログやデバッグログを有効にしたDNSサーバーがどのようにしてリクエストとリクエストを出したクライアントについての情報を大量に収集しうるのかを、いくつかサンプルを通して見ていきましょう。

こちらのマイクロソフトの記事からも、DNSサーバーログから収集できる情報の種類についてのヒントが得られます。そのようなサーバーを運用している攻撃者は、リクエストを送信しているリモートIP、クエリ文字列そのもの、そして内容はなんであれサーバーからのレスポンスを受け取ることができます。ただしリモートIPについては、リクエストを出したクライアントのIPそのものではなく、ラストホップまたはDNSサーバーのIPの可能性もあります。


DNSトンネリング

これまでの説明で、DNSとは何か、DNSのネットワーク内での動作とはどんなものか、サーバー側でどのようにトレースが行えるかについて共通の理解が得られたものと思いますので、続けてトンネリング機能についてもう少し詳しく説明していきます。このセクションでは、DNSを経由したコマンド&コントロール(C2)ビーコンがどのように機能するかや、どのようにしてデータの侵入・漏出が行われうるかについて説明します。


C2

攻撃者はC2チャネルをよく2つの目的で使います。第1の目的は、ビーコンやハートビートとして機能させることで、リモートペイロードがまだ動作している、すなわちまだ生きてサーバーとのコミュニケーションが取れる状態であることを示すことです。

ハートビートの例としては、図1に示したDNSプロセス図があげられます。クライアントシステム上の悪意のあるコードがDNSを経由して攻撃者のサーバーに繰り返しクエリを送信すれば、攻撃者はログからマルウェアが実行中であると知ることができます。難しいのは、マルウェアに感染した複数の被害者を見分けることです。

下の図2に説明した別の例で考えてみましょう。このクライアントシステムに感染したマルウェアは、奇妙な見た目のクエリ文字列を組み立て、DNS経由で送信します。このようなクエリは、ペイロードがまだアクティブであることを攻撃者に示すハートビートとして機能すると同時に、被害者に関する基本的なメタデータを提供してくれます。これにくわえ、被害者を一意に識別する方法も提供している点は重要です。

図2 C2へのDNSクエリ発行サンプル

ユーザー名やホスト名は必ずしも一意ではない場合があります。ネットワークアドレス変換(NAT)が利用されていれば、複数のネットワークで同じIPが重複することもあります。ですがシステムにはほかにもユニバーサル一意識別子(UUID)などのプロパティがあるので、そうした情報と組み合わせれば、あるホストや被害者を一意に特定する識別子を生成することができます。

侵害ホストからのメタデータの一部はプレーンテキストとして送信される可能性がありますが、DNSクエリにそのような文字列があれば一見して不審だと判断されかねません。また多くの場合データにはDNSでサポートされていない文字が含まれていますので、その場合はエンコードが必要になります。図2では、メタデータをテキストと同じ内容になるようbase64でエンコードしています。このエンコードの際は、サーバー側で単純な解析とデコードを行えるよう、「-」を区切り文字として使っています(下の図3参照)。

図3 C2通信を追跡するサーバー側DNSログ

図3は、DNSサーバーアプリケーションからの生のDNSログがどのように見えるかを示すサンプルです。このケースでは、マルウェアのクエリとDNSサーバーのレスポンスである「NXDOMAIN(存在しないドメイン)」というエントリ行が確認できます。

このログや、ログをデコードしたレコードを含む小さなデータベースは、より洗練されたボットネットコントロールパネルとある意味で似た働きをします。ボットネットのハーダーは、こうしたコントロールパネルを使うことで、侵害されてゾンビ化したシステムを制御できるのです。


漏出

それでは、DNSクエリを使うとほかに何を送信できるのでしょうか。理論的には「何でも」です。正しくエンコードされていてUDPのサイズ制限を悪用しない限りはどんなものでも送信できます。後者の制約を回避する方法のひとつに、複数のAレコードメッセージを送信し、それらをどうにかしてサーバー側で継ぎ合わせる方法があります。ただしデータグラムがドロップされたり欠落したりすると、問題は複雑になります。

失敗したパケットの再送信を保証するTCPとは異なり、UDPにはそのようなメカニズムはありません。送信されるメッセージ数を把握して正しい数だけ到着したかどうか確認するアルゴリズムが必要です。くわえて、どうにかしてクライアントにデータの特定のセグメントが100%到着するまで再送するよう依頼せねばならず、そちらはさらに難しいでしょう。送信するデータ量によっては(たとえば「システム上の全PDF」など)漏出に時間がかかりすぎますし、ネットワーク管理者の目にもかなり不審に映る可能性があります。


侵入

これに比べれば、対象となるデータの種類がコード、コマンド、ディスクにドロップして実行するバイナリファイルなど何であっても、データを侵入させることはずっと容易です。とくに、ホストのレコードタイプAのクエリのかわりにDNSのタイプとしてTXTを使用すれば侵入は簡単になります。TXTタイプのレコードは、ドメイン名に対するTXT DNSクエリがあれば、レスポンスとして、サービスの詳細、連絡先、電話番号などの説明テキストを応答するよう設計されています。

では一見テキストのように見える文字列は実際には何でしょうか。これはBase64エンコードされた、非テキストデータです。下の図4は、図2と同じクエリが悪意のあるサイトに送信されている様子を示しています。ところが今回はリクエストとレスポンスの両方とも、タイプにはTXTが利用されています。レスポンスデータにはエンコードされたバイナリ実行ファイルの最初の300文字程度が含まれていて、クライアントのマルウェアは、これを実行することができます。ここでも、ログを使用して、攻撃者はどのクライアントがペイロードを要求したかや、ペイロードの送信が完了したかどうかを把握できます(ただしクライアントに本当に着信したかどうかは分かりません)。

図4 TXTタイプのレスポンスを利用したC2 DNSクエリのサンプル

ですが、悪意のあるコードは、どのようにしてタイプをTXTに変更し、「テキスト」データ内にあるものをリクエストするタイミングを判断しているのでしょうか。ペイロード実行中の特定時点や一定時間経過後にクエリを出すよう組み込んでおく場合もありますが、実際には、C2チャネルの第2の目的であるところの「コントロール」を利用する攻撃者の意図次第、ということになります。

先に説明したC2によるDNS通信のサンプルでは、DNSサーバーからのレスポンスが「NXDOMAIN」でした。もちろんこのメッセージはクライアントシステム(とマルウェア)に届き、ペイロードに対するメッセージまたは命令として使用される可能性があります。ただし、パラメータや詳細がないと用途に制約が生じます。そこでNOERRORを使うのです。

NOERRORは、その用語が示すように、すべてがうまくいったことを意味します。つまり、リクエストは処理され、答えが待っている、という意味です。NOERRORを使用すれば、処理可能なレスポンスが返ってきます。通常、この処理可能なレスポンスとは、IPv4(Aタイプの要求の場合)か、IPv6(AAAAタイプの要求の場合)か、上記の図4で示したTXTタイプです。ここでは、単純なIPv4アドレスのレスポンスを例にとって考えてみましょう。ブラウザが「google[.]comはどこにありますか?」尋ねるのとは異なり、 マルウェアは通信のために宛先IPアドレスを必要としていません。なぜなら、すでにこのマルウェアはDNS経由のC2を使って宛先と通信しているからです。

つまり、マルウェアは返されたIPレスポンスを4,294,967,296通り(2^32通り、IPv4アドレス空間の全アドレス数)のコマンドや命令のいずれかだと解釈して利用することができます。ここでまたごく単純な例をあげるなら、たとえば「IPアドレスの4オクテット目の値が特定の値(たとえば100)であれば、TXT DNSクエリを攻撃者のドメインに送信させ、ペイロードを取得して実行させる」などとマルウェアに指示することができます。このほかたとえば「IPアドレスの第1オクテットの値が10なら悪意のあるペイロードをオペレーティングシステムからアンインストールし、イベントログから痕跡を消去する」などに解釈させることもできるでしょう。文字通り、選択肢は無限にあり、それをどのように利用するかは攻撃者の技量次第です。

DNSサーバーが攻撃者の配下にあり、特定のDNSサーバーアプリケーションやデーモンで高度なカスタマイズが可能だとすれば、クライアントから送信されたリクエストに基づいて、侵害システム上のマルウェアに状況に合わせたレスポンスを返すことができます。

たとえば、着信したクエリにドメイン名の最初のサブドメインとして特定のフラグ(文字)が含まれている場合、サーバー上のDNSサービス内で実行されているプログラムでそれを読み取り、クライアントにカスタム化したレスポンスを返すことができます。さらに、そのレスポンスに基づいてマルウェアで一連のタスクを自動処理し、その結果を攻撃者に報告して、次のタスクを受け取ることもできます。


結論

DNSはほとんどどこででも使用されている非常に強力なサービスで、このサービスによってエンドのアプリケーションやシステム同士がリソースやサービスをルックアップできるようになっています。DNSは上位レイヤーのより強力なプロトコルを機能させるための通信基盤を提供してくれるプロトコルである一方で、電子メールプロトコル経由で配信されるマルウェアやHTTPプロトコル経由でWebからダウンロードされるマルウェアの数を考えれば、セキュリティの視点が欠落したプロトコルであるとも言えるでしょう。

こうした理由からDNSは攻撃者が侵害ホストとの通信に悪用するのに最適だと言えます。なぜなら攻撃者は、常時オープンになっていて、見落とされやすく、本来の能力より過小評価されているプロトコルを探しているからです。Unit 42は、本稿でも説明したように、マルウェアの複数のインスタンスと背後の攻撃者が、DNSを悪用して目的を達成している様子を確認しています。

防御側はさまざまな方法でDNSトンネリングから身を守ることができます。Palo Alto Networksのセキュリティオペレーティングプラットフォームを使用してもよいですし、オープンソーステクノロジを使用してもよいでしょう。防御には以下に述べたようなさまざまな方法があります(ここに記載した方法がすべてというわけではありません)。

  • 既知のレピュテーションや既知の危険性に基づいて、ドメイン名(またはIPまたは地理的地域)をブロックする。
  • 「見た目が奇妙な」DNSクエリ文字列に対応するルール/ポリシーを作成する。
  • 外部から内部に入ってくるDNSクエリ、内部から外部に出ていくDNSクエリの両方について、文字列の長さ、クエリのタイプ、サイズについてのルール/ポリシーを作成する。
  • クライアントオペレーティングシステムに全般的なハードニングを施し、それらクライアントシステムでの名前解決機能がどんなものであるかや、特定の検索がどのような順序で行われるかについて理解しておく。
  • 「登録から日の浅いドメインが異常な頻度や方法でアクセスされている」など、異常を自動的に発見するユーザーやシステムの行動分析を行う。
  • パロアルトネットワークスが最近導入した新しいDNSセキュリティサービスを利用する。このサービスは、悪意のあるドメイン名へのアクセスをブロックすることに焦点を当てています。

詳細情報は、MitreのWebサイトのATT&CKフレームワークドキュメントにも記載されています。具体的には、次の技法が本稿で説明した概念に関連しています。

ID 技法
T1048 代替プロトコルを経由した漏出
T1320 データ隠蔽
T1094 カスタムコマンド&コントロールプロトコル

 

本稿に関して意見を寄せてくれたYanhui Jia、Rongbo Shao、Yi Ren、Matt Tennis、Xin Ouyang、John Harrison、Jens Eggerに感謝します。


付録: ツールキットリスト

ツール名 説明
dns2tcp dns2tcpはOlivier DembourとNicolas Collignonによって作成されました。Cで書かれており、Linux上で動作します。クライアントはWindows上で実行できます。KEYとTXTリクエストタイプをサポートしています。[4]
tcp-over-dns tcp-over-dns (TCP-over-DNS) は2008年に公開されました。JavaベースのサーバーとJavaベースのクライアントを持っています。Windows、Linux、およびSolaris上で動作します。LZMA圧縮とTCPとUDPの両方のトラフィックトンネリングをサポートしています。[4]
OzymanDNS OzymanDNSは2004年にDan KaminskyによってPerlで書かれました。DNS経由のSSHトンネルの設定やファイル転送に使用されます。リクエストはbase32でエンコードされています。レスポンスはbase64でエンコードされたTXTレコードです。[4]
iodine iodineは、2006年に最初にリリースされたDNSトンネリングプログラムで、最近は2010年に更新されています。Bjorn AnderssonとErik Ekmanによって開発されました。iodineはC言語で書かれており、Linux、Mac OS X、Windowsなどで動作します。iodineはAndroidに移植されました。エンドポイントのTUNないしTAPインターフェイスを使用します。[4]
SplitBrain SplitBrainはOzymanDNSの亜種です。
DNScat-P / dnscat2 DNScat(DNScat-P)はもともと2004年にリリースされ、最新版は2005年にリリースされました。Tadeusz Pietraszekによって書かれました。DNScatは「スイスアーミーナイフ」ツールと評されており、DNS経由の双方向通信を含む多くの用途があります。DNScatはJavaベースで、Unixライクなシステム上で動作します。DNScatはAレコードとCNAMEレコードのリクエストをサポートしています(Pietraszek, 2004)。DNScatという名前のユーティリティは2つあるため、ほかのものと区別するために本稿ではDNScat-Pと呼びます。[4]
DNScapy DNScapyはPierre Bienaimeによって開発されました。パケット生成にScapyを使用します。DNScapyはSocksプロキシを含むDNS経由のSSHトンネリングをサポートします。CNAMEレコードまたはTXTレコード、あるいはその両方をランダムに使用するように設定できます。[4]
TUNS TUNS、IP over DNSトンネルは、Lucas Nussbaumによって開発され、Rubyで書かれています。実験的またはめったに使用されないレコードタイプは使用しません。CNAMEレコードのみを使用します。DNSリクエスト内のデータと一致するよう、使用されるMTUを140文字に調整します。TUNSは検出が困難な場合がありますが、その分パフォーマンスが犠牲になります。
PSUDP PSUDPはKenton Bornによって開発されました。IP/UDPの長さを変更し、既存のDNSリクエストにデータを挿入します。このツールは、隠匿されたネットワークに参加しているすべてのホストに対し、DNSリクエストをBrokerサービスに送信するよう要求します。このBrokerサービスは、特定ホストあてのメッセージを当該ホストからのDNSリクエストが着信するまでは返さないようにしておくことができます。その後、特定ホストからDNSリクエストを受け取れば、メッセージをレスポンスで送信します。
Your Freedom Windows、Mac OSX、Linux、Android用のHTTPS/UDP/FTP/DNS/ECHO VPNであり、トンネリング用のソリューションでもあります。プロキシをバイパスしてインターネットに匿名でアクセスします。
Hexify InfobloxがDNSトンネリングの侵入テストを行うためのツールとして開発しました。

付録: マルウェアリスト

マルウェア名 説明
DNS_TXT_Pwnage DNS TXTクエリからコマンドとPowerShellスクリプトを受け取ることができるバックドアです。
DNSMessenger DNSMessengerは、ハッカーが侵入先のマシンをリモートから制御できるようにバックドアを開くRemote Access Trojan(RAT)です。
OilRig – BONDUPDATER 中東政府に対するトロイの木馬で、DNSトンネリングプロトコル内でC2通信用にAレコードとTXTレコードを使用できます。