Uninformed: Informative Information for the Uninformed

Vol 6» 2007.Jan



Vulnerability Discovery

One of the fastest ways to find new flaws is through the use of a fuzzer. In general terms, a fuzzer is a program that forces an application to process highly variant data that is typically malformed in the hopes that one of the attempts will yield a crash. Fuzzing a wireless device driver depends on the device being in a state where specific frames are processed and a tool that can send frames likely to cause a crash. In the first part of this chapter, the authors described the default state of a wireless client and what types of management frames are processed in this state.

The two types of frames that this paper will focus on are Beacons and Probe Responses. These frames have the following structure:

Size Description
1Frame Type
1Frame Flags
2Duration
6Destination
6Source
6BSSID
2Sequence
8Timestamp
2Beacon Interval
2Capability Flags
VariableInformation Elements
2Frame 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.