
首选网络列表嗅探器(PNLS)是一款红队 Wi-Fi 审计工具,提供简单的 Web 界面,能够从设备的首选网络列表(PNL)1中截获 SSID2。这是通过嗅探附近区域的探测请求实现的,随后解析这些请求以提取 SSID 及其他信息,并最终将信息传递到 Web 界面。该项目的主要动机是研究 802.11 探测请求及其传输的数据所带来的隐私风险。
图 1:PNLS 系统概述
[!WARNING] 本项目中的所有内容仅供安全研究使用。
[!NOTE]
要复制并部署本项目,您需要以下硬件和软件组件。准备好工作环境后,请前往设置部分。
sudo airmon-ng start wlan0 [2]。[!NOTE]
Kali 镜像使用 Re4son 的内核,该内核包含外部 Wi-Fi 卡的驱动程序以及 RPi 3 和 4 内置无线网卡的 Nexmon 固件 [3]。
图 2: 使用外接天线和移动电源运行的 PNLS(RPi 4)
图 3: 使用外壳与 AWUS036ACS 天线运行的 PNLS(RPi 4)
图 4: 使用 AWUS036ACM 天线运行的 PNLS(RPi 4)
如果您不想使用 Docker,请前往不使用 Docker 的设置。
快速搭建开发实例:
# 首先克隆此仓库。
git clone https://github.com/AleksaMCode/Preferred-Network-List-Sniffer.git
# 进入项目根目录。
cd Preferred-Network-List-Sniffer
# 构建后端和前端镜像。
docker compose build
# 同时启动后端和前端服务器。
docker compose up
# 进入 sniffer 文件夹。
cd sniffer
# 运行嗅探器服务。
sudo python3 sniffer.py
目前尚未提供多平台镜像,本项目仅支持 ARM64v8 架构。从 GitHub 容器注册表下载最新的预构建镜像并在本地运行。
# 首先克隆此仓库。
git clone https://github.com/AleksaMCode/Preferred-Network-List-Sniffer.git
# 进入项目根目录。
cd Preferred-Network-List-Sniffer
# 下载预构建镜像。
docker pull ghcr.io/aleksamcode/pnls-backend-ghcr:latest
docker pull ghcr.io/aleksamcode/pnls-frontend-ghcr:latest
# 同时启动后端和前端服务器。
docker compose up
# 进入 sniffer 文件夹。
cd sniffer
# 运行嗅探器服务。
sudo python3 sniffer.py
以下是“手动”运行所有组件时的截图:
图 5:PNLS 截图
探测请求是一种 802.11 管理帧,用于将设备连接到之前关联过的无线接入点(AP)。每当设备启用 Wi-Fi 但未连接网络时,它会定期发送包含其 PNL 中 SSID 的探测请求突发。这些帧以未加密方式发送,任何进行射频(RF)监控的人都可以捕获并读取它们。探测请求发送到广播 DA 地址(ff:ff:ff:ff:ff:ff)。发送后,设备启动探测计时器。计时器结束时,设备处理接收到的应答。如果设备未收到应答,它将切换到下一个信道并重复该过程。探测请求分为两种类型:
定向探测请求:使用设备 PNL 中的特定 SSID
空探测请求:使用通配符 SSID(空 SSID)
发送空探测请求是为了获取范围内所有可用 AP 的响应。
除了从捕获的所有数据包中过滤出 802.11 探测请求帧外,嗅探器还会过滤掉通配符 SSID。
当在拥有大量 Wi-Fi 客户端的大型本地网络区域捕获探测请求时,PNLS 将不可避免地捕获到大量包含该网络 SSID 的探测请求。过滤此类 SSID 可能是有利的,因为它们对我们没有价值,并且可能导致套接字负载增加。过滤掉这些 SSID 不仅会减少套接字连接上的负载,还会防止这些 SSID 在 Web 界面上造成刷屏。
使用此功能时,您需要对源代码进行细微调整。具体来说,您需要更新 settings.py 文件中的 SSID_FILTER 列表,添加您希望 嗅探器 忽略的值。更新后,重新构建项目并启动 PNLS。
本项目采用事件驱动架构(EDA),该架构基于消息驱动架构设计。虽然本项目使用集中式解决方案(所有组件均在 RPi 上运行),但由于使用了 EDA 导致的松散耦合组件,如有必要,可以创建去中心化解决方案。PNLS 由一个事件发布者(嗅探器)、一个事件消费者(Web 应用程序)和一个事件通道组成。在这里,事件通道被实现为面向消息的中间件(MOM)。
图 6:PNLS 系统部署图
异步服务器网关接口(ASGI)为支持异步的 Python Web 服务器和服务提供标准化接口 [4]。选择 ASGI 是因为本项目需要长时间运行的 WebSocket 连接,以促进不同客户端之间的异步通信。此外,它还允许在 API 调用期间使用后台协程。PNLS 使用 Python 的 uvicorn 实现来使用 ASGI Web 服务器。
通过使用 WebSocket 通信协议,我们能够实现全双工的、双向的通信。虽然本项目不需要双向通信,但确实需要系统组件之间的实时交互。这样,捕获的数据可以在捕获后立即提供给最终用户。
本项目的 MOM 通过使用 Redis 的消息代理实现。在发布-订阅(pub-sub)模型中,嗅探器 负责生成消息,而 Web 应用程序(订阅者)注册到特定的主题(Redis 频道)。当 嗅探器 向某个主题发送消息时,消息会分发给所有已订阅的消费者,从而实现异步和可扩展的通信。PNLS 使用轻量级消息协议 Redis Pub/Sub 进行消息广播,以低延迟和高吞吐量传播短生命周期消息 [5][6]。这样,就避免了将数据结构编码为可以写入磁盘的形式所带来的开销。因此,此解决方案可能具有更好的性能 [7]。下图通过事件驱动工作流展示了简化的系统活动。
图 7:PNLS 发布-订阅模型序列图
[!NOTE] 实现的 MOM 不提供持久化存储或用于数据累积的消息队列,这意味着如果在没有订阅者的情况下向主题发布消息,消息将会丢失。
下面是 Web 界面显示测试 SSID 的示例。
图 8:PNLS Web - 测试 SSID 示例
首选网络列表是一组已保存的 SSID 及其附加设置,这些设置是在您首次将设备连接到那些网络时创建的。 ↩
服务集标识符(SSID)是一种 802.11 标识符,用于为 Wi-Fi 网络命名,由最多 32 个字符组成,可以包含大小写字母、数字和特殊字符,长度不超过 32 个字符。 ↩
基于 C 语言的 Broadcom/Cypress Wi-Fi 芯片固件补丁框架,支持监控模式、帧注入等功能。 ↩
Broadcom 从未正式支持监控模式,这限制了树莓派设备中无线网卡的实用性 [8]。Nexmon 项目是对 RPi 设备中使用的 Broadcom 芯片的固件补丁 [1]。此补丁允许您在 RPi 设备上使用监控模式。 ↩
| PNL | 首选网络列表 |
| PNLS | 首选网络列表嗅探器 |
| SSID | 服务集标识符 |
| UI | 用户界面 |
| RPi | 树莓派 |
| OS | 操作系统 |
| AP | 接入点 |
| RF | 射频 |
| EDA | 事件驱动架构 |
| MOM | 面向消息的中间件 |
| ASGI | 异步服务器网关接口 |
| pub-sub | 发布-订阅 |