MForever78 Code Blog

调皮的 WiFi 热点

网络安全课的大作业是一个对公共 WiFi 进行攻击的项目。这个听着就十分带感的项目做的过程也非常有趣,其中用到了一些网络攻击的常用手段和思路,很值得记录。

项目的要求是这样的:

Modify an open-source wireless access point to conduct a man-in-the-middle attack against users who connect through it.

  • Part 1: Disable other available wireless access points temporally;
  • Part 2: Locate the target WiFi user among multiple users;
  • Part 3: Whenever a binary is downloaded by the victim via HTTP, modify it on the fly to insert a Trojan horse.

项目要求其实给了很多提示。最终的要求是要完成中间人攻击,在目标用户下载可执行文件的时候向其中植入一个木马。但使用的方法是在 WiFi 热点(Access Point,以下简称 AP)上做手脚。这意味题目要求我们不能用 ARP 欺骗这样的手段,而是要对 AP 直接发起攻击。

借着题目的三个步骤,我们可以很快分析出大致的思路。首先让目标连接着的 AP 不能正常工作,接着让目标用户连接到我们创建的热点上来,这样我们就变成了网关,给中间人攻击创造了条件。

第一步 攻击区域中可用的 AP

对 AP 的攻击手段有两种。一种是 DoS ,另一种是欺骗。而 mdk3 这个工具对这两种攻击模式都有很好的支持。

DoS 拒绝服务攻击

DoS 的一般思路是利用攻守双方的资源消耗不对等,攻方使用少量资源消耗被攻击方大量资源。客户端加入 AP 一般有两个步骤,第一步是认证(Authentication),即客户端向 AP 证明自己的身份,第二步是关联(Association),即客户端正式在 AP 上注册,获得网络使用权限。其中第一步认证过程包含两个过程,第一次客户端先向 AP 报告自己的 MAC 地址,发起认证请求,称为 Open system authentication。等 AP 回应以后再进行第二步密码认证来获取会话共享密钥,称为 Shared key authentication。我们熟悉的 WEP/WPA/WPA2 就指的是获取共享密钥的几种协议。Open system authentication 存在的必要性在于 AP 需要 MAC 地址过滤功能,以黑名单或白名单的形式保护自己的网络。因此如果客户端向 AP 发起认证请求以后 AP 因为 MAC 地址非法而不回应或拒绝,那么就不会进行第二步密码认证了。这本来是一个保护措施。

上述连接过程用对话过程模仿一遍大致就是:

client:AP 你好,这是我的身份证(把印着 MAC 地址的身份证交给 AP)

(开启了白名单的 AP 在自己的本子上查了查,发现了这个 MAC 地址 / 开启了黑名单的 AP 在自己的本子上查了查,没有发现这个 MAC 地址 / 什么都没开的 AP 装作在自己的本子上查了查,其实什么都没有做)

(AP 在另一个本子上记下这个 MAC 地址和其他相关信息,以备后续密码认证需要)

AP:client 你好,我检查过你的身份证了,你是合法的公民。现在把密码告诉我吧。

client:好的,密码是 12345678。

AP:好的,认证通过了,我们以后用 87654321 作为密钥进行会话。

client:好的。现在我想要和你关联,以后请你接受我的网络请求。

AP:好的,已经注册了,你可以通过我来上网了。

client:GET https://github.com/

(其中获得共享密钥的过程根据不同协议应有不同的流程,这里作了简化)

问题的关键在于,第一步 MAC 认证通过以后,AP 需要保存关于这个客户端的一些信息以备第二步的密码认证过程。也就是说,AP 付出资源了。而反观客户端,它只是把自己的 MAC 发过去而已,并没有什么资源消耗。那么我们 DoS 的攻击思路也就非常明显了。由于我们要攻击的是公共 AP,它显然是没有开启 MAC 白名单的。这样我们只要让网卡虚拟出大量 MAC 地址给指定 AP 发过去,那么 AP 就会消耗资源存储信息,当我们发送的速度足够快,量足够大的时候,AP 就会因为资源不足(一般而言是内存耗尽)而不得不将之前保存的信息释放。这些信息通常包含了之前连接的合法客户端的必要信息。与此同时,AP 因为内存耗尽,无法完成合法客户端的请求,因此客户端就感知到了丢包或者直接掉线。

于是用对话过程再模仿一遍大致就是:

evilA:AP 你好,这是我的身份证(把印着 MAC 地址的身份证交给 AP)

(AP 装作在自己的本子上查了查,其实什么都没有做)

(AP 在另一个本子上记下这个 MAC 地址和其他相关信息,以备后续密码认证需要)

AP:evilA 你好,我检查过你的身份证了,你是合法的公民。现在把密码告诉我吧。

(evilA 不理 AP 了)

evilB:AP 你好,这是我的身份证(把印着 MAC 地址的身份证交给 AP)

(AP 装作在自己的本子上查了查,其实什么都没有做)

(AP 在另一个本子上记下这个 MAC 地址和其他相关信息,以备后续密码认证需要)

AP:evilB 你好,我检查过你的身份证了,你是合法的公民。现在把密码告诉我吧。

(evilB 不理 AP 了)

client:AP 我要上 GitHub

AP:忙着呢等会再来啊

evilN:AP 你好,这是我的身份证(把印着 MAC 地址的身份证交给 AP)

(AP 装作在自己的本子上查了查,其实什么都没有做)

AP:(诶我靠,本子用完了,这怎么办?算了把前面记着的擦掉再用吧)

client:AP 快点啊我要上 GitHub

AP:你谁啊,滚!

client:诶我靠,掉线了!

Deauthentication & Deassociation 欺骗攻击

当一个客户端退出 AP 创建的网络时,它会向 AP 发送一个 deauthentication 包,向 AP 报告自己的 MAC 地址,告诉 AP 说自己要离开网络了。AP 接收到这个包以后就会把对应的客户端的信息删除,释放空间。同理,AP 可以主动从网络中踢掉一个客户端,它会向被踢的客户端发送一个 deassociation 包,告诉客户端它被从网络中踢出了。

这里的问题在于,deauthentication 和 deassociation 包是明文发送的,没有加密也没有签名。这对攻击者简直太方便了,一面告诉 AP 连接它的客户端都离开网络了,另一面告诉客户端它们被踢出网络了。这时候两边的连接就都断开了。当我们在网络中不断地扫描并且发送这两种包的时候,客户端就表现为持续地无法连接 AP。

Demo

  1. airmon-ng start <wireless card> 开启指定无线网卡的监听模式 开启监听模式
  2. airodump-ng <monitor interface> 扫描并记录周围 AP 的 MAC 地址 扫描 AP
  3. mdk3 <monitor interface> d -b black 对黑名单中 MAC 地址的 AP 进行 deauthentication & deassociation 攻击 deauth 攻击
  4. mdk3 <monitor interface> a -i <MAC> -m 进行 authentication DoS 攻击 DoS 攻击

当做完以上几个步骤以后,目标 AP 受到了我们的 Deauthentication & Deassociation 和 DoS 双重攻击,客户端马上看到了这样的结果:

客户端掉线

在信号瞬间变成空条以后,接着就会自动掉线了。

第二步 让目标用户连接伪造的 AP

在大型的会议室或报告厅内,为了保证大量客户端连接的通畅,主办方往往会在场地内铺设很多 AP。而多个 AP 之间使用相同的 SSID,但运行在不同的频段上,这样它们之间互不干扰,又给用户提供了通畅的网络连接。而当用户在会场内走动时,他的设备会自动地在这些 AP 间切换,他甚至觉察不到任何网络异常。

一个典型的会场 AP 布置如下图所示:

AP 布置

为了保证用户在这些 AP 间无缝切换,很显然,它们的 SSID 和密码都是相同的。

换句话说,我们只要使用和被攻击的 AP 相同的 SSID 和密码,客户端在被目标 AP 踢下线时,就会自动连接到我们的 AP 上来。对,就是这么简单。

第三步 确定目标 MAC 地址

我们设想的场景是这样的:假如你是一个骇客,接到一个任务是要盗取某个重要人物的帐户信息。客户告诉你他今天会出现在某条街的某个咖啡厅里。你来到这个咖啡厅,目标就在你的眼前,你也成功地把所有人都诱骗连接到自己的 AP 上。

那么问题来了,这么多客户端,哪个是你的目标呢?

有人说,我能从 AP 上看到所有人现在正在浏览的网页。那我走到他身后偷偷看一眼他现在在上什么网站,这样和我的记录一比对,那 IP 和 MAC 不就获得了吗?

且不说这个办法实在不像一个骇客做出来的事情,这么重要的目标,防窥屏这点觉悟还是有的吧,攻击不成反而打草惊蛇就不好了。还有诸如看 Hostname、设备型号这样的方法,辅助确定还可以,真要完全信赖,着实不大靠谱。

这个时候我们终于要祭出硬件设备了。一般路由器上自带的天线都是全向天线,也就是说,它会以自身为圆心向周围发射信号。而市面上还有另一种天线,不太常见,但也算不得稀奇之物,叫做定向天线。故名思义,它可以仅仅加强某个很小角度的扇形区域内的信号强度。利用定向天线,我们想了这样的方法来确定目标。

定向天线

在以目标为圆心,适宜半径的圆上放置定向天线,对准目标。这个时候把连接在 AP 上的所有客户端的信号强度(RSSI)记录下来。然后在圆上移动定向天线,保持天线对准目标,再次测量所有客户端的信号强度。大约把 12 点,3 点,6 点,9 点这四个方向上的数据记录下来就可以了。当然数据越多,结果越精确。

信号强度算法示意图

拿到数据以后,计算每一个客户端信号强度的方差,找出方差比较小的几个,然后比较平均信号强度,信号最强的那一个就是我们要找的目标。这个原理也很好理解,由于我们每次都在相同的距离将定向天线对准目标,那么几次测量过程目标的信号强度变化量应该是不大的,而其他的大部分客户端强度则有时被放大,有时减弱,波动明显。而另一小部分客户端,由于距离我们的天线很远,表现出每次测量的信号强度都是很小的,因此波动也很小。所以我们在找出信号强度方差最小的几个客户端里,取信号强度较强的那一个视为目标。

在实际操作过程中,我们通过 iwinfo <wireless interface> assoclist 命令获取到连接 AP 的所有客户端当前的信号强度,然后用 python 写了一个小脚本实现上述思路。因为信号强度更新速度慢,延时比较高,所以我们在每个方向上均测 50 组数据取平均值。一般在测量上述四个方向后,就可以得出正确率非常高的结果了。

你问拿着个天线一直对着人家就不可疑吗?实际上整套系统非常小巧。如果用树莓派作 AP,用充电宝来供电,装在一个口袋里,把小型定向天线装在另一个口袋里,绕着咖啡厅转一圈,装作四处看风景,就已经成功取得目标 MAC 地址了。隐蔽性可以做得很好。

第四步 中间人攻击

拿到目标的 MAC 地址,我们就可以放心地把其他人从 AP 中踢掉了,专心服务这一个客户端。

接下来一步,是要在目标下载二进制文件的时候,我们向其中加入一段木马程序。这里为了方便,我们假定用户使用的是 Windows 平台,因此要感染的对象就是 exe 文件了。

路由器上一般是把无线和有线端口之间用网桥连接起来,这样用户就可以正常上网了。而我们不希望仅仅是转发客户端的数据包。我们想要让他所有的包都经过我们自己的服务,从而进行拦截、过滤和修改。

iptables 正好符合我们的要求。我们在 PREROUTING 链中加入以下规则:

iptables -t nat -A PREROUTING -s 192.168.1.0/24 -p tcp --dport 80 -j REDIRECT --to-ports 8080

把所有 AP 子网的通往 80 端口的 TCP 包都转发到我们自己的 8080 端口上。

为了让目标的基于其他端口的应用还能正常工作,我们在 POSTROUTING 链加入以下规则:

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j MASQUERADE

然后启动一个 nginx 服务器监听 8080 端口。当检查到以 exe 结尾的 URL,我们就转发到自己的 server 上,其他的请求仅作为透明代理正常转发。

server {
    listen 8080;

    location ~* \.exe$ {
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:3000;
    }   

    location / {
        proxy_pass http://$host$request_uri;
    }
}

接下来写一个简易的 Web server。我们已经拿到了 socket,要做的事情是先请求用户请求的资源,当 http response 返回以后,把其头部的 Content-Length 修改为原文件的长度加上我们的木马的长度。接着拼接这个 response,先把我们事先准备好的木马发给用户,再在后面接上用户请求的原程序。这样就做到了我们一边下载,一边给客户端传送的效果,客户端就很难察觉异常了。

目标在点击运行这个可执行文件后,木马先于原程序执行了。并且在木马退出时,还会调用原程序。这样目标下载的程序还是可以正常运行的,只不过这个时候他的电脑已经被我们的木马植入了。

值得一提的是,虽然这里只是劫持了 http 协议,但使用 ssl strip 的方法也可以劫持大部分 https 网站。

大成功

至此我们的项目就完全成功了。不知道对于一进入咖啡厅还有快餐店就急着要连 WiFi 的你有没有警醒。

防御措施

我们当然不是真的骇客,整个实验都是在可控的实验室环境中进行,但即使去实地攻击,最多也只是个 Script kiddo 罢了。所以实验的意义更在于学习如何防御和保护自己。从上面的攻击过程中,大概可以总结出以下几点:

不要连任何公共场所的 WiFi

注意,不是不要连没有密码的 WiFi,而是公共场所的任何 WiFi。由于 4G 通信的安全性较高,攻击还是十分困难的。

在任何不受信任的网络中上网,使用 VPN

VPN 从 IP 层加密了数据包,保证了通讯的安全性。如果使用 VPN,则上述攻击就完全没有效果。

使用基于 802.11w 的无线通讯协议

802.11w 保证了 Deauthentication 和 Deassociation 的包是经过签名的,无法伪造,从而杜绝了类似攻击。

从网络上下载的文件,比对指纹信息后再执行

负责任的软件方会在下载页面的醒目位置写出该文件的 Hash ,如果下载来的文件 Hash 值不同,那么不要执行。