# 第四章无线测试 无线连接时代带来了灵活性和移动性,但也带来了许多安全问题。通过有线连接,攻击者需要物理访问才能进行连接和攻击。在无线连接的情况下,攻击者只需要信号的可用性就可以发起攻击。在继续之前,您应该了解所使用的术语: * **接入点****AP**:用于将无线设备与有线网络连接。 * **业务集标识符**(**SSID**):无线局域网的 0-32 字母数字唯一标识符;它是人类可读的,简单地说,它是网络名称。 * **基本业务集标识****BSSID**:无线 AP 的 MAC 地址。 * **信道号**:此表示 AP 用于传输的射频范围。 ### 注 由于 AP 的自动设置,频道号可能会更改。因此,在本章中,不要感到困惑。如果在不同的时间运行相同的程序,则频道号可能会更改。 在本章中,我们将学习许多概念,例如: * 查找无线 SSID * 分析无线通信量 * 检测 AP 的客户端 * 无线 deauth 攻击 * MAC 泛洪攻击 802.11 和 802.11x 被 IEEE 定义为一系列无线局域网技术。以下是基于频率和带宽的 802.11 规范: * **802.11**:提供高达 1-2Mbps 的带宽,频带为 2.4GHz * **802.11.a**:提供高达 54 Mbps 的带宽,频率为 5 GHz * **802.11.b**:提供高达 11Mbps 的带宽和 2.4GHz 的频带 * **802.11g**:提供高达 54 Mbps 的带宽,频带为 2.4 GHz * **802.11n**:该在两个频段提供高达 300 Mbps 的带宽 802.11 的所有组件都属于**媒体访问控制****MAC**或物理层。MAC 层是数据链路层的子类。您已经了解了数据链路层的协议数据单元(**PDU**),称为帧。 但是,首先,让我们了解 802.11 帧格式。802.11 中存在的三种主要帧类型是: * 数据帧 * 控制框架 * 管理框架 这些帧由 MAC 层辅助。下图描述了 MAC 层的格式: ![Wireless Pentesting](graphics/8583OT_04_01.jpg) 在上图中,显示了三种类型的地址。**地址 1**、**地址 2**和**地址 3**分别是目的地、AP 和源的 MAC 地址。表示**地址 2**为 AP 的 BSSID。在本章中,我们的重点将放在管理框架上,因为我们对管理框架的子类型感兴趣。一些常见类型的管理帧包括身份验证帧、取消身份验证帧、关联请求帧、解除关联帧、探测请求帧和探测响应帧。客户端和 AP 之间的连接是通过交换各种帧建立的,如下图所示: ![Wireless Pentesting](graphics/8583OT_04_02.jpg) 帧交换 上图显示了帧的交换。这些框架是: * **信标帧**:AP 周期性发送一个信标帧来通告其存在。信标帧包含 SSID、通道号、BSSID 等信息。 * **探测请求**:无线设备(客户端)发出探测请求,确定哪些 AP 在范围内。探测请求包含 AP 的 SSID、支持的费率、供应商特定信息等元素。客户端发送探测请求并等待探测响应一段时间。 * **探测响应**:在探测请求的响应中,对应的 AP 会响应一个探测响应帧,其中包含能力信息、支持的数据速率等。 * **认证请求**:客户端发送包含其身份的认证请求帧。 * **认证响应**:AP 响应认证,表示接受或拒绝。如果存在共享密钥身份验证,例如 WEP,则 AP 以身份验证响应的形式发送质询文本。客户端必须将身份验证帧中被质询文本的加密形式发送回 AP。 * **关联请求**:认证成功后,客户端发送包含其特征的关联请求,如支持的数据速率、AP 的 SSID 等。 * **关联响应**:AP 发送包含接受或拒绝的关联响应。在接受的情况下,AP 将为客户端创建关联 ID。 我们即将进行的攻击将基于这些框架。 现在是时候进行一次实际的讨论了。在下一节中,我们将介绍该理论的其余部分。 # 利用 Python 进行无线 SSID 查找和无线流量分析 如果您已经通过 Back Track 或 Kali Linux 进行了无线测试,那么您将熟悉`airmon-ng`套装。`airmon-ng`脚本用于启用无线接口上的监控模式。监控模式允许无线设备捕获帧,而无需与 AP 关联。我们将在 Kali Linux 上运行所有的程序。下面的屏幕截图显示了如何设置**mon0**: ![Wireless SSID finding and wireless traffic analysis by Python](graphics/8583OT_04_03_new.jpg) 设置 mon0 当您运行`airmon-ng`脚本时,它会给无线网卡一个名称,如**wlan0**,如前一个屏幕截图所示。`airmon-ng start wlan0`命令将在监视器模式下启动**wlan0**,并且**mon0**捕获无线数据包。 现在,让我们编写第一个程序,给出三个值:SSID、BSSID 和通道号。不要担心因为我们将逐行讨论: ``` import socket sniff = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, 3) sniff.bind(("mon0", 0x0003)) ap_list =[] while True : fm1 = sniff.recvfrom(6000) fm= fm1[0] if fm[26] == "\x80" : if fm[36:42] not in ap_list: ap_list.append(fm[36:42]) a = ord(fm[63]) print "SSID -> ",fm[64:64 +a],"-- BSSID -> ", \ fm[36:42].encode('hex'),"-- Channel -> ", ord(fm[64 +a+12]) ``` 第一行和往常一样`import socket`。下一行是`sniff = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, 3)`。我希望您已经仔细阅读了[第三章](13.html "Chapter 3. Sniffing and Penetration Testing")*嗅探和渗透测试*。唯一的新事物是`3`。参数`3`表示协议编号,表示`ETH_P_ALL`。这意味着我们对每一包都感兴趣。下一行`sniff.bind(("mon0", 0x0003))`绑定**mon0**模式和协议编号 3。在下一行中,我们声明了一个空的`ap_list =[]`列表**,**,它将存储 AP 的 MAC 地址(SSID)。我们使用一个列表来避免 AP 的任何冗余。对于持续的嗅探,我们使用了无限`while`循环。下一个`fm1 = sniff.recvfrom(6000)`语句向`fm1`提供数据,下一个`fm= fm1[0]`语句只取帧的第一部分,其中包含长的十六进制数字序列;也就是说,十六进制转储包含帧的所有元素,如下面的屏幕截图所示。下一条`if fm[26] == "\x80":`语句告诉`if`帧子类型为 8 位,表示信标帧,如下图所示: ![Wireless SSID finding and wireless traffic analysis by Python](graphics/8583OT_04_04.jpg) 信标帧的 Wireshark 表示 你可能想知道为什么。这意味着第 27 个字节包含一个子类型,因为`fm[0:25]`意味着前 26 个字节由 Radiotap 头采用。在前面的屏幕截图中,您可以看到**Radiotap 标头,长度为 26**,这意味着 Radiotap 标头已经获取了前 26 个字节。下一条`if fm[36:42] not in ap_list:`语句是一个过滤器,它检查`fm[36:42]`值,即 BSSID,是否存在于`ap_list`中。如果不是,下一个`ap_list.append(fm[36:42])`语句将在`ap_list`中添加 BSSID。下一个`a = ord(fm[63])`语句给出了 SSID 的长度。在下一行中,`fm[64:64 +a]`表示 AP 的 SSID 位于 64 到 64 加上 SSID 的长度;`fm[36:42].encode('hex')`语句将十六进制值转换为可读的十六进制值;`ord(fm[64 +a+12])`语句提供了通道号,它位于 SSID 前面 12 个数字。 第一个 _ssid_sniffer.py 程序的输出如以下屏幕截图所示: ![Wireless SSID finding and wireless traffic analysis by Python](graphics/8583OT_04_05.jpg) 美联社详情 现在,让我们编写代码,使用 scapy 查找 AP 的 SSID 和 MAC 地址。您一定认为我们在原始数据包分析中执行了相同的任务;实际上,出于研究目的,您应该了解关于原始数据包分析的内容。如果您想要一些 scapy 不知道的信息,原始数据包分析可以让您自由创建所需的嗅探器: ``` from scapy.all import * interface = 'mon0' ap_list = [] def info(fm): if fm.haslayer(Dot11): if ((fm.type == 0) & (fm.subtype==8)): if fm.addr2 not in ap_list: ap_list.append(fm.addr2) print "SSID--> ",fm.info,"-- BSSID --> ",fm.addr2 sniff(iface=interface,prn=info) ``` 让我们从头开始看代码。`scapy.all import *`语句导入 scapy 库的所有模块。变量接口设置为**mon0**。声明了一个名为`ap_list`的空列表。在下一行中,定义了`info`函数,并传递了`fm`参数。 `if fm.haslayer(Dot11):`语句就像一个过滤器,只通过`Dot11`流量;`Dot11`表示 802.11 流量。下一个`if((fm.type == 0) & (fm.subtype==8)):` 语句是另一个过滤器,它传递帧类型为`0`且帧子类型为`8`的流量;类型`0`表示管理帧,子类型`8`表示信标帧。在下一行中,使用`if fm.addr2 not in ap_list:`语句删除冗余;如果 AP 的 MAC 地址不在`ap_list`中,则会追加列表,将地址添加到列表中,如下一行所述。下一行打印输出。最后一行`sniff(iface=interface,prn=info)`使用接口**mon0**嗅探数据,并调用`info()` 函数。 以下屏幕截图显示了`ssid.py`程序的输出: ![Wireless SSID finding and wireless traffic analysis by Python](graphics/8583OT_04_06.jpg) 我希望你已经理解了`ssid.py`程序。现在,让我们试着算出 AP 的频道号。我们必须对守则作一些修改。新的修改代码如下: ``` from scapy.all import * import struct interface = 'mon0' ap_list = [] def info(fm): if fm.haslayer(Dot11): if ((fm.type == 0) & (fm.subtype==8)): if fm.addr2 not in ap_list: ap_list.append(fm.addr2) print "SSID--> ",fm.info,"-- BSSID --> ",fm.addr2, \"-- Channel--> ", ord(fm[Dot11Elt:3].info) sniff(iface=interface,prn=info) ``` 您会注意到,我们在这里添加了一个东西,即`ord(fm[Dot11Elt:3].info)`。 你可能想知道是什么?如果您在 scapy 中打开`Dot11Elt`,您将得到三样东西,`ID`、`len`和`info`,如下输出所示: ``` root@Mohit|Raj:~# scapy INFO: Can't import python gnuplot wrapper . Won't be able to plot. WARNING: No route found for IPv6 destination :: (no default route?) lWelcome to Scapy (2.2.0) >>> ls(Dot11Elt) ID : ByteEnumField = (0) len : FieldLenField = (None) info : StrLenField = ('') >>> ``` 参见以下类代码: ``` class Dot11Elt(Packet): name = "802.11 Information Element" fields_desc = [ ByteEnumField("ID", 0, {0:"SSID", 1:"Rates", 2: "FHset", 3:"DSset", 4:"CFset", 5:"TIM", 6:"IBSSset", 16:"challenge", 42:"ERPinfo", 46:"QoS Capability", 47:"ERPinfo", 48:"RSNinfo", 50:"ESRates",221:"vendor",68:"reserved"}), FieldLenField("len", None, "info", "B"), StrLenField("info", "", length_from=lambda x:x.len) ] ``` 在前面的类码中,`DSset`给出了通道号的信息,所以`DSset` 号为`3`。 让我们不要让它变得复杂,让我们简单地使用 scapy 捕获一个数据包: ``` >>> conf.iface="mon0" >>> frames = sniff(count=7) >>> frames >>> frames.summary() RadioTap / 802.11 Management 8L 84:1b:5e:50:c8:6e > ff:ff:ff:ff:ff:ff / Dot11Beacon / SSID='CITY PG3' / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt RadioTap / 802.11 Data 8L 84:1b:5e:50:c8:6e > 88:53:2e:0a:75:3f / Dot11QoS / Dot11WEP 84:1b:5e:50:c8:6e > 88:53:2e:0a:75:3f (0x5f4) / Raw RadioTap / 802.11 Control 13L None > 84:1b:5e:50:c8:6e / Raw RadioTap / 802.11 Control 11L 64:09:80:cb:3b:f9 > 84:1b:5e:50:c8:6e / Raw RadioTap / 802.11 Control 12L None > 64:09:80:cb:3b:f9 / Raw RadioTap / 802.11 Control 9L None > 64:09:80:cb:3b:f9 / Raw ``` 在下面的屏幕截图中,您可以看到第 0 帧中有大量的 Dot11Elt。让我们详细检查第 0 帧。 ![Wireless SSID finding and wireless traffic analysis by Python](graphics/8583OT_04_07.jpg) 他在镜框里 现在,您可以看到有几个**