我们或许都曾了解过有关 VLAN 双标签攻击的知识。尽管已经有了很多关于 VLAN 双标签攻击的参考文献,哪怕就连一个证明攻击思路的数据包都能算上一个,但是这些基本上都不能算是武器化攻击的体现。
Amish Patadiya 将会在这篇 blog 中利用 VLAN 双标签技术与真实案例来演示如何借助 Linux 上的原生工具去访问某一 VLAN 网络,并对位于其他 VLAN 中的服务器漏洞进行利用。首先就从基础知识讲起。
VLAN 是干什么的?
在我们深入讨论 VLAN(虚拟局域网)标记的概念之前,首先要理解 VLAN 的需求是什么。每当我们建立好一个网络时,这个网络中会充斥着大量相互通信的主机。
而 VLAN 支持灵活组网,即便是所有终端设备都连接在同一台交换机上,可以通过在交换机上进行多网配置来实现终端设备之间的相互隔离。对于规模较大的网络,通过划分 VLAN 还有助于减小广播域(广播域可以理解为所有节点都是在数据链路层上进行通信的这样一个网络)。
在一个 VLAN 网络内,所有的数据包都会被分配给这一个 VLAN id。除非交换机的端口被配置给了其他 VLAN,否则所有的端口都默认分配给交换机的本地 VLAN 。一般情况下交换机的本地 VLAN 就是 VLAN-1,并且在本地 VLAN 中的所有网络数据包都不会被打上 VLAN 标签,这样一来,这些流量就可以在本地 VLAN 中进行无标签的传输。
比方说如果我们想要去访问位于某一 VLAN 中的主机,这时在网络数据包中就会被打上该 VLAN 的标签(这里举例用到的VLAN ID为20),如图所示:
VLAN 的双重标记是什么?
在了解如何利用漏洞之前,让我们再来快速概述一下 VLAN 双重标记。下面是一张便于理解的网络拓扑:
这里需要注意的是,攻击机处在 VLAN-1 中,这也是 VLAN 双标签攻击必须具备的条件之一,即本地 VLAN。被攻击机位于 VLAN-20 ,被攻击服务器的本地 IP 地址为“10.0.20.11”,与处在 VLAN-1 中的攻击机“kali-internal”之间是不互通的,如图所示:
如图所示,攻击机上有两块网卡,其中“eth2”连接了 VLAN-1 网络。下面还显示了网卡“eth2”的一些网络配置信息:
Yersinia 是利用此 VLAN 漏洞的首选工具。Yersinia 通过 ICMP 包来构造 PoC。下图显示的是利用 Yersinia 发送 ICMP 包 PoC 的命令:
接下来让我们确认下网络中每条链路的 VLAN 双重标记。
下图为在连接了 VLAN-1 网络和路由器 “R1”的链路“1”上的捕获流量。该图中指出了带有双802.1Q VLAN 标签目标地址为“10.0.20.11”的 ICMP 数据包:
下图为在连接了路由器“R1”和路由器“R2”的“Trunk”链路上的捕获流量。当 VLAN 流量通过 Trunk 链路时,所有无标签的本地 VLAN 流量都会被传输,这也是为什么我们只能借助本地 VLAN 网络来实现该攻击。
在这种情况下,VLAN-1 的标签将会被删除而只会留下 VLAN-20 的标签。
下图为连接了路由器“R2”和被攻击服务器的链路“2”的捕获流量。如图所示,流量现在是来自 VLAN-20 网络的了,因此路由器“R2”也就把 VLAN-20 的标签给删除了:
接下来让我们借助 Linux 上的工具复现一遍这次攻击。
利用本地工具进行双重标记
我们将会使用在所有 Linux 机器上都适用的 vconfig(该工具包含在 vlan 软件包中)。利用该工具,我们可以创建一个允许我们自己向网络中发送双标签数据包的接口。如图所示,我们已经写好了一个脚本,以帮助配置你们的网络来对机器的实时流量进行双重标记:
这里我们利用 802.1 Q 的内核模块来允许带标签数据包的传输。使用 vconfig 创建虚拟接口“eth2.1”用来自动将数据包打上 VLAN id 为1的标签。在“eth2.1”的基础上创建另一个接口“eth2.1.20”用来给数据包打上 VLAN id 为20的标签,以此来实现对外传输带双标签的数据包。
下图为执行脚本的输出结果:
我们向被攻击服务器 ping 三个包来测试一下我们对实时流量双重标记的配置结果如何,如图:
如图所示,我们可以在链路“1”的捕获流量中发现,向被攻击服务器发送的 ICMP 数据包被打上了双重标记:
从链路“2”的捕获流量中也可以发现数据包确实到达了被攻击服务器。
上述步骤能够证明我们可以将实际流量传输到另一 VLAN 中。接下来让我们尝试将攻击进行武器化操作。
武器化双标签攻击
不过当我们从 TCP 流量作为出发点来对此进行武器化时却碰到了拦路虎,我们不得不再去重温一下基础知识,逐步了解解决问题的办法。如图所示,我们尝试在被攻击机上利用 nc 设置监听 8080 端口服务:
在攻击机上我们运行一个简单的“wget”命令去访问一下被攻击机上托管的 web 服务器内容:
可以发现 wget 无法找到 web 服务器。这并不是因为双重标记的配置错误,而是因为“HTTP”是基于 TCP 协议的,而 TCP 建立连接需要进行三次握手。当使用 wget 发送请求时,在建立连接之前它会先尝试建立完整的三次握手。如图所示,在链路“2”的捕获流量中发现了由攻击机发往被攻击机的“SYN”包:
由于被攻击机位于 VLAN-20 中,这样一来由被攻击机发送的响应包就会被打上 VLAN-20 的标签。而攻击机是位于 VLAN-1 里面的,两者处于不同的 VLAN,所以攻击机就不会收到来自被攻击机的响应。
这就说明了 VLAN 双标签攻击是一种单向通信的攻击,如图所示,攻击机在建立三次握手的过程中根本就不会收到“SYN-ACK”包:
我们再尝试通过 TCP 端口8080来与被攻击机通信,此时攻击机的网络状态为“SYN_SENT”:
而在被攻击机上对于请求数据包的网络状态为“SYN_RCV”:
这就意味着由被攻击机发送的“SYN-ACK”请求无法到达处于另一 VLAN 的攻击机。这也就给我们目前的结论提供了证明,即无法攻击位于另一 VLAN 中的 TCP 服务。
既然这样的话,那攻击 UDP 服务可以吗?UDP 端口上承载着多种服务,并且 UDP 端口的状态在参与过程中也不太会被注意到。
由于 UDP 协议是一种不需要进行握手的无连接协议,它可以直接发送数据,所以我们能够向位于另一 VLAN 中的任意 UDP 服务发送数据包。这里我们使用在 UDP 模式下具有漏洞CVE-2017-5645的“Log4j”服务器进行演示。
如图所示,被攻击机上的“Log4j”服务正在监听 UDP 端口“12345”:
为了验证攻击是否会成功,我们将尝试在被攻击机的“/tmp/”目录下创建一个名为“success”的文件。这是当前被攻击机“/tmp/”目录下的内容:
“Log4j”服务支持序列化格式的日志,我们利用 Ysoserial 生成序列化后的 payload。接着运行 payload 来对上述被攻击机的端口执行攻击:
如图所示,在分析 Wireshark 上的流量时,发现 UDP 的 payload 已到达 VLAN-20:
如图所示,payload 成功到达被攻击机并且在“/tmp/”目录下创建了名为“success”的文件:
但是当我们尝试拿 shell 的时候又一次陷入了一种通信限制的困境。好在我们可以通过利用公共托管服务器(这里举例用kali-Internet来表示)来摆脱这种限制。如图所示,我们在服务器“kali-internet”上对端口“32323”进行监听:
利用 ysoserial 创建一个序列化的 payload,将 shell 弹到“kali-Internet”。
如图所示,在被攻击机上执行 payload 后,我们就成功 getshell 了。使用 cat 命令查看一下当前服务器上的主机名“/etc/hostname”为“Victim__[eth0:_10.0.20.11/24]”:
以上就是如何利用 VLAN 双标签技术来攻击 UDP 服务的步骤。
重新探讨TCP攻击
我们既然都能够攻击 UDP 服务了,我们就想着再回头看看针对 TCP 服务是否也能够去为所欲为。接着我们做了一些测试,不过下面要说的部分有可能完全就是胡诌八扯。我们做了一些猜想,看看是否真的可以为所欲为。上面一开始我们遇到最大的拦路虎就是无法完成三次握手建立连接。我们就从握手原理切入,了解一下具体的瓶颈在哪。
我们打算这样做:
- 在被攻击机上设置监听
- 对被攻击机进行流量捕获
- 利用攻击机向被攻击机发送 wget 请求
我们可以在捕获流量中发现,被攻击机接收到了以“Seq=2678105924”的SYN包并且也发送了以“Ack=2082233419”的SYN-ACK包,然而如图所示,它却并没有到达攻击机那里。
我们可以通过查看在攻击机上的 netstat 输出来验证这一点(图中的连接状态为:SYN_SENT)
转念又想,如果我们可以模拟出 SYN ACK,服务器也许就会向被攻击机发送完整的请求了。我们用了一个叫 Hping3 的工具进行测试:
别说,好像还真能成功建立连接:
现在已经与攻击机建立起了连接,再用攻击机继续发送 HTTP 请求,并在被攻击机端适当接收及捕获请求。
这基本可以说明,如果我们可以获取到有效的“Seq”和“Ack”值,就可以成功的建立起 TCP 连接并且有可能实现对 TCP 服务的攻击。但是,要是不存在 RFC 6528(https://www.rfc-archive.org/getrfc.php?rfc=6528)的话,实现这种攻击就可能简单的多了(RFC 6528能够在协议层上实现随机化的 TCP 序列和 Ack 编号)。
尽管最后还是没能实现对 TCP 服务的攻击,但还是希望以后要是有其他师傅想尝试一下的时候可以将我们公开的这些内容作为参考。
局限性
要想进行 VLAN 双标签攻击,必须具备以下条件:
- 攻击机必须位于本地 VLAN 网络内
- 攻击者必须要知道被攻击机的以下信息:
- 目标服务器的 VLAN 信息
- 可被利用攻击的 UDP 服务与端口
防御方法
- 永远不要在任何网络内使用本地 VLAN。默认情况下本地 VLAN id 为 VLAN-1
- 如果认为有必要,可以将本地 VLAN 从 VLAN id 1 改为 VLAN id 2
- 在配置 VLAN 网络时,连接终端设备的端口应该配置为 access 端口
- 在 trunk 链路中始终只允许指定的 VLAN 通过,不要允许所有 VLAN 都可以通过 trunk 链路。
参考
https://cybersecurity.att.com/blogs/security-essentials/vlan-hopping-and-mitigation
https://packetlife.net/blog/2010/feb/22/experimenting-vlan-hopping/
https://tools.kali.org/vulnerability-analysis/yersinia
https://serverfault.com/questions/506488/linux-how-can-i-configure-dot1addouble-tag-on-a-interface
https://www.rfc-archive.org/getrfc.php?rfc=6528