大家好,好久不见,这里是某昨。这是一篇从 2021
年春节一直咕到现在的文章,因此文中的「今天」等指代时间的词语均代表当时的时间,请各位在阅读时自行转换(笑)
ToC
开始
今天无意在 OSChina
的公众号看到一篇讲解 Chrome
将一些端口加入黑名单以防止 NAT Slipstreaming
攻击的新闻。原文是这样描述的:
这个新型
NAT Slipstreaming
漏洞使网站可以托管恶意脚本,这些恶意脚本发送经过特殊设计的响应,从而绕过网站访问者的NAT
防火墙并能够访问用户内部网络上的任何TCP
/UDP
端口。
这个漏洞的结果令我产生了强烈的好奇:这个洞到底是怎么打出来的?!这篇文章就是在明白了其原理之后诞生的。
值得注意的是,这篇文章中描述的是 NAT Slipstreaming
的 v1
版本。上述新闻中描述的是 v2
。v1
能做到的是能连通内网的 5060
端口,而 v2
则可以支持任意的端口。v2
和 v1
的主要区别在于选取的协议不同,但很多原理都是共通的。因此这里只介绍 v1
的原理。
NAT
在之前的一篇文章,我详细介绍了 NAT
的几种类型。但无论是哪种 NAT
,都无法解决这样的问题:协议选择使用多条连接时,外部连接无法穿过 NAT
。
以 FTP
协议为例,当使用主动模式时,FTP
客户端主动选择了端口 n
向 FTP
服务器建立连接,并打开端口 n+1
接收 FTP
服务器传来的数据。此时,端口 n
由于内网机器主动穿过 NAT
,建立了 NAT
映射;但对于端口 n+1
,由于传输层并没有任何迹象表明这个端口会被使用,因此 FTP
服务器对这个端口的访问就会被 block
,由此导致 FTP
主动模式无法使用。
尽管 FTP
提供了被动模式,但被动模式会受到服务端端口数量的限制,从而限制了同时使用的用户数量。并且,如果配置了防火墙策略,服务端还需要放行一部分被动模式使用的端口。
FTP
只是许多这样协议中的一种。它工作在应用层,其预期行为由于 NAT
的存在而无法正常进行。由此,应用层网关应运而生。
应用层网关(ALG
)
应用层网关,顾名思义,就是工作在应用层的网关。我们来看一看 ALG
是如何解决上述问题的。
还是以 FTP
协议为例。我们知道,当 FTP
客户端建立主动连接时,其自身选择了一个端口 n
。对于 ALG
,其可以通过各种方式判断当前连接的协议为 FTP
。当主动连接时,ALG
透明地增加一条与目标机器端口的映射。这样,FTP
协议就可以正常使用了。
简单总结一下,就是 ALG
通过识别某些特殊的协议报文,自动判断并建立需要建立的端口映射,从而使得应用层协议能够正常运行。
问题所在
乍一看这样的流程好像没什么问题,那究竟是什么导致了危险呢?
我们知道,数据在传输的过程中,IP
数据报由于 MTU
的限制,必须进行分片;TCP
数据包由于 MSS
的限制,必须进行分段。而网关作为需要处理大量数据报的设备,其效率永远是第一位的。这也就意味着 ALG
的对报文的识别通常是无状态的。当 ALG
接收到报文,通过协议特征判断出其对应的应用层协议,下一步就是建立 NAT
映射。
于是利用方式就出现了。当我们知道了网络的 MTU
、MSS
、IP
头长度、TCP
头长度,我们就可以通过巧妙构造 HTTP
请求,通过 POST
的 body
产生 TCP
报文分段。如果分段后的报文恰好是合法的 FTP
主动模式连接建立报文,那么 ALG
就会被欺骗并创建端口 n+1
与被攻击者之间的 NAT
映射。
因此问题就恰巧出现在了上图的第二步:识别 FTP
协议。当 ALG
识别到了这样的协议,就会自动放行对应的流量;而当流量得到放行,攻击者就可以访问对应内网机器的其他端口了。
SIP
协议
上文中为了方便理解,我们一直举了 FTP
协议作为例子。而在实际的攻击行为中,SIP
协议才是被选取的受害者。
简单来说,SIP
协议的 INVITE
和 REGISTER
需要构造类似 FTP
协议中 n+1
端口的开放才能正常工作,因此只要能够构造数据包,带有 SIP
的注册信息,就可以对内网的任意主机的 5060
端口进行打洞了。
TURN
协议
有的 ALG
实现 SIP
协议实现只允许 TCP
打 TCP
的,UDP
打 UDP
的,因此我们需要一个突破 UDP
的手段。TURN
就是被选中的受害者了。TURN
协议中有认证的环节,其中的 username
是以明文传输的,并且没有任何限制,这就是利用点了。
我们知道,UDP
协议是没有 MSS
的,其分片只会受 MTU
的影响。而当 IP
包被分片时,第二片报文中就不存在 UDP
报头了。也就是说,除了这个报文是 UDP
协议的报文之外,其他的一切 ALG
都一无所知。由此,我们就可以构造任意的 UDP
报文内容了,自然也包括 SIP
协议。
内网主机探测
现在我们有了能够打通 NAT
的能力,那被打的人在哪儿呢?原文给出了两种手段。
一种是通过 ICE
协议,还是 WebRTC
那一套探测内网;而另一种则是通过诸如 <img>
的 onsuccess
、onerror
和 timeout
实现,当成功探测到 Web
服务器时是 success
,其他 TCP
服务发送 RST
则为 onerror
,IP
不存在则会产生一秒以上的耗时,可以通过计时器判断。
结语
有了打洞方式、探测手段和受害者,NAT Slipstreaming v1
的使命就完成了。利用 ALG
的合理行为,IP
协议的合理行为,TURN
协议的合理行为,以及 ICE
协议和 <img>
的合理行为,挡在我们面前的 NAT
被层层剥开,暴露出了其中一无所知的被害主机。
这也就是 NAT Slipstreaming
的暴露出来的核心问题:当所有协议都以其正确的方式运行时,却产生了足以致命的安全问题。而这,也对后续的协议设计有着巨大的启示意义。