こんにちは!セキュリティの世界へようこそ。
日々の開発やインフラの管理、本当にお疲れ様です。「なんだかサーバーの調子がおかしいな」「見慣れない通信がたくさんあるな」と感じたことはありませんよね?
今回は、サイバー攻撃者が忍び込んできたときに使う、ちょっとズルくて巧妙な手口――「DGA(ドメイン生成アルゴリズム)」と、それを見つけ出すための「DNSクエリログの解析」について、身近な例えを交えながら優しく紐解いていきたいと思います。
難しい言葉が出てきても、「一歩ずつ対策を学んでいきましょう!」という気持ちで進めていきますので、どうぞリラックスして読んでくださいね。
—
1. 家の鍵と「泥棒の合言葉」に例えるサイバー攻撃
まずは、私たちの身近な防犯に例えて考えてみましょう。
皆さんの家には、頑丈な玄関の鍵がありますよね。泥棒が家に侵入するとき、まずはその鍵をこじ開けようとします。セキュリティの世界で言えば、これは「ファイアウォール」や「サーバーへの不正アクセス」にあたります。
しかし、最近の泥棒はとても頭が良いのです。たとえ家に侵入できなくても、「家の中の誰かと外の仲間(悪い親分)がこっそり連絡を取り合えるようにする」という裏口を作ろうとします。これが、サイバー攻撃でよく聞く「C2(Command and Control)サーバーとの通信」です。
通常、警察(セキュリティソフト)は、泥棒が連絡を取り合っている「アジトの住所(特定のウェブサイトのURLやIPアドレス)」をあらかじめ把握していて、「この住所宛ての郵便や電話はすべてブロック!」と見張っています。
ここで、泥棒が使うのが「DGA(Domain Generation Algorithm:ドメイン生成アルゴリズム)」というずる賢い仕組みです。
- 泥棒の作戦:
毎日、あるいは数分おきに「今日連絡するアジトの住所」を、あらかじめ決めたルール(計算式)に従って自動でガラリと変えてしまうのです。
- 警察の悩み:
「昨日まで『 abc.com 』だったアジトが、今日は『 xqz789.net 』に変わり、明日は誰も聞いたことがない『 mnp456.org 』に変わる……! 住所が毎回変わるから、張り込みが追いつかない!」
この「コロコロと変わる怪しい住所(ドメイン名)」を、マルウェアはインターネットの電話帳である「DNS」に対して、大量に問い合せ(クエリを送信)続けます。この不自然なやり取りを見破るのが、今回の主役である「DNSクエリログの異常検知」なんです。
—
2. 現場で何が起きている? DNSクエリログの「不自然なざわざわ」
では、実際に企業のネットワークやサーバーの裏側で何が起きているのか、もう少し詳しく見ていきましょう。
パソコンやサーバーが「ねえ、example.comってどこにあるの?」とDNSサーバーに尋ねることを「DNSクエリ」と呼びます。通常、私たちが日常的にアクセスするドメインは、人間にも読みやすい意味のある名前(google.comやgithub.comなど)をしていますよね。
しかし、先ほどお話ししたDGAが作り出すドメインは、人間が見ると「猫がキーボードの上を歩いて作ったような、意味不明な文字列」になります。例えばこんな感じです。
k9s8d7f6g5h4j3k2.comqazxswedcvfrtgbnh.netxypq-98123746-zz.org
これらは、人間だけでなく、通常のシステムにとっても「そんな名前のウェブサイト、聞いたことないよ!」というものばかりです。
「NXDOMAIN(そんな名前ないよ!)」の嵐に注目せよ
DGAに感染したマルウェアは、今日のアジトの住所がどこにあるか分からないため、手当たり次第に数百、数千という「架空のドメイン名」を作っては、DNSサーバーに「この住所知ってる?」と聞きまくります。
DNSサーバーは当然、「そんなドメインは存在しませんよ」と答えを返します。このエラー応答のことを、専門用語で「NXDOMAIN(Non-Existent Domain)」と呼びます。
インシデントレスポンスの現場では、この「NXDOMAINの応答が、特定の端末から異常なほど大量に発生しているログ」を見つけることが、DGAやマルウェア感染を発見する最大の手がかりになるのです。
—
3. 実践! PythonでDNSクエリログ(NXDOMAIN)を解析してみよう
「理屈は分かったけれど、実際にどうやって見つければいいの?」という声にお応えして、シンプルなログ解析のスクリプトを用意しました。
実際の現場では、数万行もある巨大なDNSのアクセスログ(テキスト形式やJSON形式)から、「おや、このパソコン、変な問い合わせをたくさんしていないか?」と探すことになります。
以下のPythonコードは、DNSのログから「NXDOMAIN(存在しないドメインへの問い合わせ)」を抽出し、特定の端末が怪しい動きをしていない集計するサンプルです。コメントを丁寧に書いたので、ぜひ雰囲気を掴んでみてくださいね。
from collections import Counter
# 模擬的なDNSクエリログのリスト
# 実際には、SyslogやDNSサーバー(BINDやWindows DNSなど)のログファイルから読み込みます
dns_query_logs = [
{"client_ip": "192.168.1.50", "query_domain": "google.com", "response_code": "NOERROR"},
{"client_ip": "192.168.1.105", "query_domain": "k9s8d7f6g5h4j3k2.com", "response_code": "NXDOMAIN"},
{"client_ip": "192.168.1.105", "query_domain": "qazxswedcvfrtgbnh.net", "response_code": "NXDOMAIN"},
{"client_ip": "192.168.1.50", "query_domain": "github.com", "response_code": "NOERROR"},
{"client_ip": "192.168.1.105", "query_domain": "xypq98123746zz.org", "response_code": "NXDOMAIN"},
{"client_ip": "192.168.1.105", "query_domain": "randomstring12345.biz", "response_code": "NXDOMAIN"},
{"client_ip": "192.168.1.105", "query_domain": "anotherfake.info", "response_code": "NXDOMAIN"},
]
def detect_suspicious_dns_activity(logs, threshold=3):
"""
DNSログからNXDOMAIN(存在しないドメイン)への問い合わせが多い端末を検知する関数
:param logs: DNSログのリスト
:param threshold: 異常とみなすNXDOMAINの閾値(今回は簡単のため3回以上に設定)
"""
print("[*] DNSクエリログの解析を開始します...\n")
# NXDOMAINを発生させているクライアントIPごとにカウントするための辞書
nxdomain_counter = Counter()
for log in logs:
# 応答コードが NXDOMAIN(ドメインが存在しない)の場合のみ集計対象にする
if log["response_code"] == "NXDOMAIN":
client_ip = log["client_ip"]
nxdomain_counter[client_ip] += 1
print(f"[警告] 存在しないドメインへの問い合わせを検知: IP = {client_ip}, ドメイン = {log['query_domain']}")
print("\n--- 解析結果サマリー ---")
# 閾値を超えて怪しい動きをしている端末をチェック
for ip, count in nxdomain_counter.items():
if count >= threshold:
print(f"[!] 🚨 危険: クライアントIP [{ip}] から異常な数のNXDOMAIN({count}回)を検知しました!")
print(f" -> この端末はマルウェア(DGA)に感染している可能性があります。すぐにネットワークから隔離を検討してください。\n")
else:
print(f"[-] クライアントIP [{ip}] のエラー回数は許容範囲内です({count}回)。")
# スクリプトの実行
if __name__ == "__main__":
detect_suspicious_dns_activity(dns_query_logs)
このコードのポイント
response_code == "NXDOMAIN"という条件で、泥棒が適当に作り出した「ハズレの住所」への問い合わせだけを綺麗にフィルタリングしています。- 特定のパソコン(今回の例では
192.168.1.105)だけが何度もエラーを出している場合、その端末のユーザーが偶然タイポ(入力ミス)を頻発している可能性もありますが、インシデントレスポンスの現場では「マルウェアによるC2通信の試行(DGA)」を強く疑ってかかります。
—
4. 新人のIT担当者・開発者が今日からできる現実的な防犯対策
「ログの解析ってなんだか難しそう……」と思った方もいらっしゃるかもしれません。でも、いきなり高度なツールを使いこなす必要はありません。身近なところから、一歩ずつ対策を学んでいきましょう!
1. DNSログを「捨てずに残す」設定にする
会社のルーターや社内DNSサーバー(Windows ServerのDNSやBINDなど)のログ機能が、デフォルトでオフになっていないか確認してみましょう。ログがなければ、後から泥棒の足跡を追うことができません。「ログを残すこと」がすべての第一歩です。
2. 不審なドメイン名の特徴(エントロピー)を知る
人間が考えたドメイン名(例: corporate-portal.com)と、機械がランダムに作った文字列(例: x8k2j9s1d7f6g.com)は、文字のバラエティ度合い(情報エントロピー)が異なります。「妙にランダムで長いドメインへのアクセスが多いな」と気づける直感を、日頃のニュースや技術記事読みを通じて養っていきましょう。
3. 信頼できるセキュリティ製品やクラウドDNSを活用する
企業でインフラを管理する場合、社内のPCが直接インターネットのよく分からないDNSサーバーを見に行くのではなく、セキュリティ機能付きのDNSサービス(Cisco UmbrellaやCloudflare Gatewayなど、既知の悪意あるドメインやDGAを自動でブロックしてくれるサービス)を通すように設定するのが、最も確実で効果的な防犯対策になります。
—
おわりに
サイバー攻撃の手口は日々進化していますが、攻撃者が通信を行う以上、必ずどこかに「不自然な足跡(ログ)」が残ります。
最初はチンプンカンプンに見えたログの羅列も、「あ、これは泥棒が合い言葉を探している時のざわざわだな」とストーリーとして理解できるようになると、インシデントレスポンスの仕事がぐっと面白くなります。
焦らず、一歩ずつ、あなたの守るシステムを強固なものに育てていきましょう。それでは、また次回のセキュリティ解説でお会いしましょう!
コメント