
DNSChef - ペネトレーションテスターとマルウェアアナリストのためのDNSプロキシ
| | version 0.4 | | / _|
| | __ ___ | | __| |
/ ` | ' / |/ | ' \ / _ \ |
| (| | | | _ \ (| | | | __/ |
_,|| ||/_|| ||___||
D O C U M E N T A T I O N
DNSChef は、ペネトレーションテスターやマルウェアアナリスト向けの、高度に設定可能な DNS プロキシです。DNS プロキシ(別名「Fake DNS」)は、アプリケーションネットワークトラフィックの分析などに使用されるツールです。例えば、DNS プロキシを使用して "badguy.com" へのリクエストを偽装し、インターネット上の実際のホストではなく、ローカルマシンに終端またはインターセプトのために転送することができます。
既存の DNS プロキシは多数ありますが、そのほとんどはすべての DNS クエリを単一の IP アドレスにポイントするか、ごく基本的なフィルタリングしか実装していません。DNSChef は、より設定可能なシステムが必要とされたペネトレーションテストの一環として開発されました。その結果、DNSChef はクロスプラットフォームアプリケーションであり、包含・除外ドメインリストに基づくレスポンスの偽装、複数の DNS レコードタイプのサポート、ワイルドカードによるドメインマッチング、非マッチングドメインに対する真のレスポンスのプロキシ、外部設定ファイルの定義、IPv6 など、多くの機能を備えています。各機能の詳細な説明と推奨される使用方法は以下にあります。
DNS プロキシの使用は、アプリケーションに他のプロキシサーバーを直接強制できない状況で推奨されます。例えば、一部のモバイルアプリケーションは OS の HTTP プロキシ設定を完全に無視します。このような場合、DNSChef のような DNS プロキシサーバーを使用することで、そのアプリケーションをだまして目的の宛先に接続を転送できます。
DNSChef の使用を開始する前に、ツールが実行されている DNS ネームサーバーを使用するようにマシンを設定する必要があります。使用する OS に応じていくつかのオプションがあります。
Linux - /etc/resolv.conf を編集し、先頭にトラフィック分析ホストを追加します(ローカルで実行している場合は "nameserver 127.0.0.1" を追加)。あるいは、Network Manager などのツールを使用して DNS サーバーアドレスを追加することもできます。Network Manager 内で IPv4 設定を開き、Method ドロップダウンボックスから Automatic (DHCP) addresses only または Manual を選択し、DNS Servers テキストボックスに DNSChef が実行されている IP アドレスを編集します。
Windows - コントロールパネル から ネットワーク接続 を選択します。次に、いずれかの接続(例:"ローカルエリア接続")を選択し、右クリックしてプロパティを選択します。新しいダイアログボックスで、インターネットプロトコル (TCP/IP) を選択し、プロパティをクリックします。最後に 次の DNS サーバーのアドレスを使う ラジオボタンを選択し、DNSChef が実行されている IP アドレスを入力します。例えば、ローカルで実行している場合は 127.0.0.1 を入力します。
OS X - システム環境設定 を開き、ネットワーク アイコンをクリックします。アクティブなインターフェースを選択し、DNS サーバ フィールドに入力します。Airport を使用している場合は、詳細... ボタンをクリックし、そこから DNS サーバーを編集する必要があります。あるいは、/etc/resolv.conf を編集し、先頭に偽のネームサーバー(例:"nameserver 127.0.0.1")を追加することもできます。
iOS - 設定 を開き、一般 を選択します。次に Wi-Fi を選択し、リストからアクティブなアクセスポイントの右側にある青色の矢印をクリックします。DNS エントリを編集して DNSChef が実行されているホストを指定します。セルラーインターフェースが利用可能な場合は無効にしてください。
Android - 設定 を開き、ワイヤレスとネットワーク を選択します。Wi-Fi 設定 をクリックし、電話の オプション ボタンを押した後、詳細設定 を選択します。静的 IP を使用 チェックボックスを有効にし、カスタム DNS サーバーを設定します。
デバイスの DNS 設定を手動で変更できない場合でも、ARP スプーフィング、不正 DHCP などの手法を使用するオプションがいくつかあります。
最後に、DNSChef がすべてのリクエストをポイントする偽のサービスを設定する必要があります。例えば、Web トラフィックをインターセプトする場合、ポート 80 で動作する別の Web サーバーを立ち上げるか、Web プロキシ(例:Burp)を設定してトラフィックをインターセプトします。DNSChef は、適切に設定されたサービスのあるプロキシ/サーバーホストにクエリをポイントします。
DNSChef は Python で開発されたクロスプラットフォームアプリケーションであり、Python インタプリタが動作するほとんどのプラットフォームで動作します。Windows ホストでは、Python インタプリタをインストールせずに実行できる付属の dnschef.exe 実行ファイルを使用できます。このガイドでは Unix 環境に焦点を当てますが、以下の例はすべて Windows でも動作することを確認しています。
DNSChef の最も基本的な監視機能を試してみましょう。以下のコマンドを root で実行します(ポート 53 でサーバーを起動するために必要)。
# ./dnschef.py
_ _ __
| | version 0.2 | | / _|
__| |_ __ ___ ___| |__ ___| |_
/ _` | '_ \/ __|/ __| '_ \ / _ \ _|
| (_| | | | \__ \ (__| | | | __/ |
\__,_|_| |_|___/\___|_| |_|\___|_|
[email protected]
[*] DNSChef started on interface: 127.0.0.1
[*] Using the following nameservers: 8.8.8.8
[*] No parameters were specified. Running in full proxy mode
パラメータを指定しない場合、DNSChef はフルプロキシモードで動作します。つまり、すべてのリクエストは単純にアップストリーム DNS サーバー(デフォルトでは 8.8.8.8)に転送され、クエリ元のホストに返されます。例えば、ドメインに対する "A" レコードをクエリして結果を確認してみましょう。
$ host -t A thesprawl.org
thesprawl.org has address 108.59.3.64
DNSChef は、時刻、送信元 IP アドレス、要求されたレコードのタイプ、そして最も重要なクエリされた名前を示すログ行を出力します。
[23:54:03] 127.0.0.1: proxying the response of type 'A' for thesprawl.org
このモードは、アプリケーションが通信に使用するドメインを特定する必要があるシンプルなアプリケーション監視に便利です。
DNSChef は IPv6 を完全にサポートしており、-6 または --ipv6 フラグを使用して有効にできます。デフォルトのリスニングインターフェースが ::1 に、デフォルトの DNS サーバーが 2001:4860:4860::8888 に切り替わる以外は IPv4 モードとまったく同じように動作します。以下はサンプル出力です。
# ./dnschef.py -6
_ _ __
| | version 0.2 | | / _|
__| |_ __ ___ ___| |__ ___| |_
/ _` | '_ \/ __|/ __| '_ \ / _ \ _|
| (_| | | | \__ \ (__| | | | __/ |
\__,_|_| |_|___/\___|_| |_|\___|_|
[email protected]
[*] Using IPv6 mode.
[*] DNSChef started on interface: ::1
[*] Using the following nameservers: 2001:4860:4860::8888
[*] No parameters were specified. Running in full proxy mode
[00:35:44] ::1: proxying the response of type 'A' for thesprawl.org
[00:35:44] ::1: proxying the response of type 'AAAA' for thesprawl.org
[00:35:44] ::1: proxying the response of type 'MX' for thesprawl.org
注:デフォルトでは、DNSChef は UDP リスナーを作成します。代わりに TCP を使用するには、後述の --tcp 引数を使用します。
DNSChef の起動方法がわかったところで、次に --fakeip パラメータを使用してすべての応答を 127.0.0.1 に向けるように設定しましょう。
# ./dnschef.py --fakeip 127.0.0.1 -q
[*] DNSChef started on interface: 127.0.0.1
[*] Using the following nameservers: 8.8.8.8
[*] Cooking all A replies to point to 127.0.0.1
[23:55:57] 127.0.0.1: cooking the response of type 'A' for google.com to 127.0.0.1
[23:55:57] 127.0.0.1: proxying the response of type 'AAAA' for google.com
[23:55:57] 127.0.0.1: proxying the response of type 'MX' for google.com
上記の出力では、DNSChef がすべてのリクエストを 127.0.0.1 にプロキシするように設定されていることがわかります。08:11:23 の最初のログ行は、"A" レコードの応答を 127.0.0.1 に "cook"(偽装)したことを示しています。しかし、'AAAA' および 'MX' レコードの後続のリクエストは、実際の DNS サーバーから単にプロキシされています。要求プログラムからの出力を見てみましょう。
$ host google.com localhost
google.com has address 127.0.0.1
google.com has IPv6 address 2001:4860:4001:803::1001
google.com mail is handled by 10 aspmx.l.google.com.
google.com mail is handled by 40 alt3.aspmx.l.google.com.
google.com mail is handled by 30 alt2.aspmx.l.google.com.
google.com mail is handled by 20 alt1.aspmx.l.google.com.
google.com mail is handled by 50 alt4.aspmx.l.google.com.
ご覧のとおり、プログラムは IPv4 アドレスに 127.0.0.1 を使用するよう騙されました。ただし、IPv6(AAAA)およびメール(MX)レコードから得られた情報は完全に正当に見えます。DNSChef の目標はプログラムの正しい動作への影響を最小限に抑えることです。そのため、アプリケーションが特定のメールサーバーに依存している場合、このプロキシリクエストを通じて正しく取得されます。
次に、複数のレコードを同時にターゲットにする方法を示すために、もう 1 つリクエストを偽装してみましょう。
# ./dnschef.py --fakeip 127.0.0.1 --fakeipv6 ::1 -q
[*] DNSChef started on interface: 127.0.0.1
[*] Using the following nameservers: 8.8.8.8
[*] Cooking all A replies to point to 127.0.0.1
[*] Cooking all AAAA replies to point to ::1
[00:02:14] 127.0.0.1: cooking the response of type 'A' for google.com to 127.0.0.1
[00:02:14] 127.0.0.1: cooking the response of type 'AAAA' for google.com to ::1
[00:02:14] 127.0.0.1: proxying the response of type 'MX' for google.com
--fakeip フラグに加えて、'AAAA' レコードクエリを偽装するための --fakeipv6 も指定しました。更新されたプログラム出力は以下のとおりです。
$ host google.com localhost
google.com has address 127.0.0.1
google.com has IPv6 address ::1
google.com mail is handled by 10 aspmx.l.google.com.
google.com mail is handled by 40 alt3.aspmx.l.google.com.
google.com mail is handled by 30 alt2.aspmx.l.google.com.
google.com mail is handled by 20 alt1.aspmx.l.google.com.
google.com mail is handled by 50 alt4.aspmx.l.google.com.
アプリケーションによって明示的に上書きされなかったレコードはすべてプロキシされ、実際の DNS サーバーから返されました。ただし、IPv4(A)と IPv6(AAAA)は両方ともローカルマシンを指すように偽装されました。
DNSChef は複数のレコードタイプをサポートしています。
+--------+--------------+-----------+--------------------------+
| レコード | 説明 |引数 | 例 |
+--------+--------------+-----------+--------------------------+
| A | IPv4 アドレス|--fakeip | --fakeip 192.0.2.1 |
| AAAA | IPv6 アドレス|--fakeipv6 | --fakeipv6 2001:db8::1 |
| MX | メールサーバー|--fakemail | --fakemail mail.fake.com |
| CNAME | CNAME レコード|--fakealias| --fakealias www.fake.com |
| NS | ネームサーバー|--fakens | --fakens ns.fake.com |
+--------+--------------+-----------+--------------------------+
注:使いやすさのため、すべての DNS レコードタイプがコマンドラインで公開されているわけではありません。PTR、TXT、SOA などの追加レコードは、--file フラグと適切なレコードヘッダーを使用して指定できます。詳細は、外部定義ファイル のセクションを参照してください。
最後に、アプリケーションが ANY タイプのクエリをどのように処理するかを見てみましょう。
# ./dnschef.py --fakeip 127.0.0.1 --fakeipv6 ::1 --fakemail mail.fake.com --fakealias www.fake.com --fakens ns.fake.com -q
[*] DNSChef started on interface: 127.0.0.1
[*] Using the following nameservers: 8.8.8.8
[*] Cooking all A replies to point to 127.0.0.1
[*] Cooking all AAAA replies to point to ::1
[*] Cooking all MX replies to point to mail.fake.com
[*] Cooking all CNAME replies to point to www.fake.com
[*] Cooking all NS replies to point to ns.fake.com
[00:17:29] 127.0.0.1: cooking the response of type 'ANY' for google.com with all known fake records.
DNS ANY レコードクエリでは、DNSChef は該当するドメインについて知っているすべての偽装レコードを返します。プログラムが表示する出力は次のとおりです。
$ host -t ANY google.com localhost
google.com has address 127.0.0.1
google.com has IPv6 address ::1
google.com mail is handled by 10 mail.fake.com.
google.com is an alias for www.fake.com.
google.com name server ns.fake.com.
上記の例で、thesprawl.org のリクエストのみをインターセプトし、webfaction.com などの他のドメインへのクエリは変更せずに残したい場合を考えます。以下に示すように --fakedomains パラメータを使用できます。
# ./dnschef.py --fakeip 127.0.0.1 --fakedomains thesprawl.org -q
[*] DNSChef started on interface: 127.0.0.1
[*] Using the following nameservers: 8.8.8.8
[*] Cooking replies to point to 127.0.0.1 matching: thesprawl.org
[00:23:37] 127.0.0.1: cooking the response of type 'A' for thesprawl.org to 127.0.0.1
[00:23:52] 127.0.0.1: proxying the response of type 'A' for mx9.webfaction.com
上記の例では、thesprawl.org へのリクエストは偽装されましたが、mx9.webfaction.com へのリクエストはそのまま残されました。ドメインのフィルタリングは、残りの部分を壊さずに単一のアプリケーションを隔離しようとする場合に非常に便利です。
注:DNSChef は、応答を偽装する前にそのドメインが存在するかどうかを検証しません。指定したドメインは、実際に存在するかどうかに関係なく、常に偽の値に解決されます。
別の状況では、定義されたリストのドメインを除くすべてのリクエストに対して応答を偽装する必要があるかもしれません。このタスクは、次のように --truedomains パラメータを使用して実行できます。
# ./dnschef.py --fakeip 127.0.0.1 --truedomains thesprawl.org,*.webfaction.com -q
[*] DNSChef started on interface: 127.0.0.1
[*] Using the following nameservers: 8.8.8.8
[*] Cooking replies to point to 127.0.0.1 not matching: *.webfaction.com, thesprawl.org
[00:27:57] 127.0.0.1: proxying the response of type 'A' for mx9.webfaction.com
[00:28:05] 127.0.0.1: cooking the response of type 'A' for google.com to 127.0.0.1
上記の例ではいくつかの点に注意してください。まず、ワイルドカード()の使用に注目してください。.webfaction.com に一致するすべてのドメインは逆マッチングされ、真の値に解決されます。'google.com' へのリクエストは除外ドメインのリストに含まれていなかったため、127.0.0.1 を返しました。
注:ワイルドカードは位置に依存します。.thesprawl.org のようなマスクは www.thesprawl.org に一致しますが、www.test.thesprawl.org には一致しません。ただし、.*.thesprawl.org のようなマスクは、thesprawl.org、www.thesprawl.org、および www.test.thesprawl.org に一致します。
すべての一致するドメインに対して単一の偽の DNS レコードを定義するだけでは不十分な場合があります。リクエストを正確にどこに送るかを定義する DOMAIN=RECORD ペアのコレクションを含む外部ファイルを使用できます。
たとえば、次の定義ファイルを作成し、dnschef.ini という名前を付けましょう。
[A]
*.google.com=192.0.2.1
thesprawl.org=192.0.2.2
*.wordpress.*=192.0.2.3
セクションヘッダー [A] に注目してください。これは DNSChef にレコードタイプを定義します。それでは、複数のクエリの出力を注意深く観察しましょう。
# ./dnschef.py --file dnschef.ini -q
[*] DNSChef started on interface: 127.0.0.1
[*] Using the following nameservers: 8.8.8.8
[+] Cooking A replies for domain *.google.com with '192.0.2.1'
[+] Cooking A replies for domain thesprawl.org with '192.0.2.2'
[+] Cooking A replies for domain *.wordpress.* with '192.0.2.3'
[00:43:54] 127.0.0.1: cooking the response of type 'A' for google.com to 192.0.2.1
[00:44:05] 127.0.0.1: cooking the response of type 'A' for www.google.com to 192.0.2.1
[00:44:19] 127.0.0.1: cooking the response of type 'A' for thesprawl.org to 192.0.2.2
[00:44:29] 127.0.0.1: proxying the response of type 'A' for www.thesprawl.org
[00:44:40] 127.0.0.1: cooking the response of type 'A' for www.wordpress.org to 192.0.2.3
[00:44:51] 127.0.0.1: cooking the response of type 'A' for wordpress.com to 192.0.2.3
[00:45:02] 127.0.0.1: proxying the response of type 'A' for slashdot.org
google.com と www.google.com の両方が *.google.com エントリに一致し、正しく 192.0.2.1 に解決されました。一方、www.thesprawl.org リクエストは変更されずに単にプロキシされました。最後に、wordpress.com、www.wordpress.org などのすべてのバリエーションが *.wordpress.* マスクに一致し、正しく 192.0.2.3 に解決されました。最後に、未定義の slashdot.org クエリは実際の応答でプロキシされました。
コマンドラインで明示的に公開されていないものを含め、サポートされている他のすべての DNS レコードタイプのセクションヘッダーを指定できます:[A]、[AAAA]、[MX]、[NS]、[CNAME]、[PTR]、[NAPTR]、[SOA]。たとえば、'dnschef.ini' ファイルに新しい [PTR] セクションを定義してみましょう。
[PTR]
*.2.0.192.in-addr.arpa=fake.com
この新しいレコードタイプでの DNSChef の動作を観察します。
./dnschef.py --file dnschef.ini -q
[sudo] password for iphelix:
[*] DNSChef started on interface: 127.0.0.1
[*] Using the following nameservers: 8.8.8.8
[+] Cooking PTR replies for domain *.2.0.192.in-addr.arpa with 'fake.com'
[00:11:34] 127.0.0.1: cooking the response of type 'PTR' for 1.2.0.192.in-addr.arpa to fake.com
逆 DNS クエリを実行するクライアントが表示する内容は次のとおりです。
$ host 192.0.2.1 localhost
1.2.0.192.in-addr.arpa domain name pointer fake.com.
一部のレコードは正確な書式が必要です。良い例として SOA と NAPTR があります。
[SOA]
*.thesprawl.org=ns.fake.com. hostmaster.fake.com. 1 10800 3600 604800 3600
[NAPTR]
*.thesprawl.org=100 10 U E2U+sip !^.*$!sip:[email protected]! .
追加の例については、サンプルの dnschef.ini ファイルを参照してください。
ファイルとコマンドラインからの入力を組み合わせることができます。たとえば、次のコマンドは --file パラメータと --fakedomains パラメータの両方を使用しています。
# ./dnschef.py --file dnschef.ini --fakeip 6.6.6.6 --fakedomains=thesprawl.org,slashdot.org -q
[*] DNSChef started on interface: 127.0.0.1
[*] Using the following nameservers: 8.8.8.8
[+] Cooking A replies for domain *.google.com with '192.0.2.1'
[+] Cooking A replies for domain thesprawl.org with '192.0.2.2'
[+] Cooking A replies for domain *.wordpress.* with '192.0.2.3'
[*] Cooking A replies to point to 6.6.6.6 matching: *.wordpress.*, *.google.com, thesprawl.org
[*] Cooking A replies to point to 6.6.6.6 matching: slashdot.org, *.wordpress.*, *.google.com, thesprawl.org
[00:49:05] 127.0.0.1: cooking the response of type 'A' for google.com to 192.0.2.1
[00:49:15] 127.0.0.1: cooking the response of type 'A' for slashdot.org to 6.6.6.6
[00:49:31] 127.0.0.1: cooking the response of type 'A' for thesprawl.org to 6.6.6.6
[00:50:08] 127.0.0.1: proxying the response of type 'A' for tor.com
コマンドラインパラメータの thesprawl.org の定義が dnschef.ini よりも優先されていることに注意してください。これは、設定ファイルの値を上書きしたい場合に便利です。slashdot.org は --fakedomains パラメータで指定されたため、依然として偽の IP アドレスに解決されます。tor.com のリクエストはコマンドラインでも設定ファイルでも指定されていないため、単にプロキシされます。
その他の設定 ====================セキュリティ上の理由から、DNSChef はデフォルトでローカルの 127.0.0.1(IPv6 の場合は ::1)インターフェースでリッスンします。--interface パラメータを使用して、別のインターフェースでリッスンさせることができます:
# ./dnschef.py --interface 0.0.0.0 -q
[*] DNSChef started on interface: 0.0.0.0
[*] Using the following nameservers: 8.8.8.8
[*] No parameters were specified. Running in full proxy mode
[00:50:53] 192.0.2.105: proxying the response of type 'A' for thesprawl.org
または IPv6 の場合:
# ./dnschef.py -6 --interface :: -q
[*] Using IPv6 mode.
[*] DNSChef started on interface: ::
[*] Using the following nameservers: 2001:4860:4860::8888
[*] No parameters were specified. Running in full proxy mode
[00:57:46] 2001:db8::105: proxying the response of type 'A' for thesprawl.org
デフォルトでは、DNSChef は Google のパブリック DNS サーバーを使用してプロキシリクエストを行います。ただし、--nameservers パラメータを使用してカスタムのネームサーバーリストを定義できます:
# ./dnschef.py --nameservers 4.2.2.1,4.2.2.2 -q
[*] DNSChef started on interface: 127.0.0.1
[*] Using the following nameservers: 4.2.2.1, 4.2.2.2
[*] No parameters were specified. Running in full proxy mode
[00:55:08] 127.0.0.1: proxying the response of type 'A' for thesprawl.org
IP#PORT 表記を使用して、非標準のネームサーバーポートを指定することができます:
# ./dnschef.py --nameservers 192.0.2.2#5353 -q
[*] DNSChef started on interface: 127.0.0.1
[*] Using the following nameservers: 192.0.2.2#5353
[*] No parameters were specified. Running in full proxy mode
[02:03:12] 127.0.0.1: proxying the response of type 'A' for thesprawl.org
同時に、-p port# パラメータを使用して DNSChef 自体を別のポートで起動することも可能です:
# ./dnschef.py -p 5353 -q
[*] Listening on an alternative port 5353
[*] DNSChef started on interface: 127.0.0.1
[*] Using the following nameservers: 8.8.8.8
[*] No parameters were specified. Running in full proxy mode
DNS プロトコルは UDP(デフォルト)または TCP で使用できます。DNSChef は --tcp フラグで有効化できる TCP モードを実装しています。
ツールをニーズに合わせて適応させる必要がある場合に備えて、内部構造に関する情報を以下に示します。DNSChef は SocketServer モジュールの上に構築されており、スレッディングを使用して複数のリクエストを同時に処理します。このツールは、TCP または UDP ポート(デフォルトではポート 53)で着信リクエストをリッスンし、必要に応じてそれらのリクエストを UDP 経由で実際の DNS サーバーに転送するように設計されています。
優れた dnslib ライブラリ が DNS パケットの解析と再構築に使用されています。これは、クエリに基づいて応答パケットを生成する際に特に便利です。
DNSChef は、"A"、"AAAA"、"MX"、"CNAME"、"NS"、"TXT"、"PTR"、"NAPTR"、"SOA"、"ANY" タイプのレコードに対するクエリを変更することができます。任意のレコードに対する動作を拡張または変更するのは非常に簡単です。別の if qtype == "RECORD TYPE") エントリを追加し、何を返信するかを指定するだけです。
このツールをお楽しみください。リクエストやコメントはすべて iphelix [at] thesprawl.org までお送りください。
ハッピーハッキング! -Peter