3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-11-21 22:09:23 +01:00

auto-t: Add frame fuzzing test

Add a test to validate a crash found by Alex Radocea when sending
a fuzzed beacon frame.

Co-authored-by: Alex Radocea <alex@supernetworks.org>
This commit is contained in:
James Prestwood 2024-02-29 09:07:31 -08:00 committed by Denis Kenzior
parent 5067654a6d
commit 816d258cab
3 changed files with 116 additions and 0 deletions

View File

@ -0,0 +1,72 @@
import unittest
import sys
import sys
import os
from scapy.layers.dot11 import *
from scapy.arch import str2mac, get_if_raw_hwaddr
from time import time, sleep
from threading import Thread
def if_hwaddr(iff):
return str2mac(get_if_raw_hwaddr(iff)[1])
def config_mon(iface, channel):
"""set the interface in monitor mode and then change channel using iw"""
os.system("ip link set dev %s down" % iface)
os.system("iw dev %s set type monitor" % iface)
os.system("ip link set dev %s up" % iface)
os.system("iw dev %s set channel %d" % (iface, channel))
class AP:
def __init__(self, ssid, psk, mac=None, mode="stdio", iface="wlan0", channel=1):
self.channel = channel
self.iface = iface
self.mode = mode
if self.mode == "iface":
if not mac:
mac = if_hwaddr(iface)
config_mon(iface, channel)
if not mac:
raise Exception("Need a mac")
else:
self.mac = mac
self.boottime = time()
def get_radiotap_header(self):
return RadioTap()
def dot11_beacon(self, contents):
evil_packet = (
self.get_radiotap_header()
/ Dot11(
subtype=8, addr1="ff:ff:ff:ff:ff:ff", addr2=self.mac, addr3=self.mac
)
/ Dot11Beacon(cap=0x3101)
/ contents
)
self.sendp(evil_packet)
def run(self, contents):
interval = 0.05
num_beacons = 100
while num_beacons:
self.dot11_beacon(contents)
sleep(interval)
num_beacons -= 1
def start(self, contents):
self.thread = Thread(target=self.run, args=(contents,))
self.thread.start()
def stop(self):
self.thread.join()
def sendp(self, packet, verbose=False):
if self.mode == "stdio":
x = packet.build()
sys.stdout.buffer.write(struct.pack("<L", len(x)) + x)
sys.stdout.buffer.flush()
return
assert self.mode == "iface"
sendp(packet, iface=self.iface, verbose=False)

View File

@ -0,0 +1,7 @@
[SETUP]
num_radios=2
start_iwd=0
hwsim_medium=yes
[rad1]
reserve=true

View File

@ -0,0 +1,37 @@
#! /usr/bin/python3
import unittest
import sys
import sys
import os
from fake_ap import AP
sys.path.append('../util')
from iwd import IWD
# Probe frame that causes IWD to crash
beacon=b'\xdd\nPo\x9a\t\x0e\x00\x00\x19\x10\x00\xdd/Po\x9a\t\x0c\x02\x00\x00\xdd\x05\x03\x03\x03Po\x9a\x10\x00\x0b\x05\x0e\x00\x00\x00\x00\x0b\x05\x00\x00\x00\xdd\x05\x00\x03\x03\x03\x03\x00\x00\x00\xdd\x05\x03\x03\x03\x03\x03'
class Test(unittest.TestCase):
def test_beacon_crash(self):
wd = IWD(True)
devs = wd.list_devices()
self.assertEqual(len(devs), 1)
devs[0].autoconnect = True
os.system("iw phy rad1 interface add wlan1 type managed")
ap = AP("evilAP", "password1234", mode="iface", iface="wlan1", channel=4)
ap.start(beacon)
condition = "obj.scanning == True"
wd.wait_for_object_condition(devs[0], condition)
condition = "obj.scanning == False"
wd.wait_for_object_condition(devs[0], condition)
if __name__ == '__main__':
unittest.main(exit=True)