///Getting Practical About Wireless Security, Part 1: Building a Wireless Sniffer with Perl

Getting Practical About Wireless Security, Part 1: Building a Wireless Sniffer with Perl

A Lightweight Program can Illustrate Wireless Security Issues and Techniques

This article, the first in a two-part report, reviews common issues of wireless security, and shows how to use open source software to suss out wireless networks, get information about them, and start recognizing common security problems.

One of the best ways to make sure information is kept secure is to broadcast it using a published standard, and to try to make sure the signal goes as far as possible. Right? Well, maybe that isn’t the best strategy after all. Unfortunately for us, the convenience of wireless access to a network means that a lot of people use a wireless network, and that means that a lot of data is being broadcast in the clear.

In this article, I’ll build a lightweight wireless sniffer that runs on open source software. You’ll see how simple it is to interact with wireless networks. The information the sniffer collects offers some insights on key wireless security issues.

It’s easy to underestimate the availability of wireless networks. During testing for this article, I had a recurring problem: my equipment kept accidentally picking up networks other than the ones I wanted to test. In fact, my laptop has found wireless networks to associate with while I’m traveling on the freeway! So, one obvious thing for a wireless network scanner to do is to identify the names and signal strengths of local wireless networks.

Rough Consensus and Running Code

The code used for this article is not particularly elegant. The focus is on building a simple front end to the standard utilities, producing data that is accessible as plain text for use from a serial console or remote login.

The target platform for the sample code is NetBSD running on a fairly small box, using a standard wireless card. The primary test platforms were a laptop using an Intersil Prism chipset, and a Soekris Systems Net4801 using an Atheros chipset. The bulk of the actual code is written in Perl, using the Curses module from CPAN to make a friendly interface.

If you plan to build a more serious or fully featured program, you would probably be better off using this code as a prototype rather than actually using any of the code directly. However, it does show how some of these tools go together. My use of threading was an experiment, and I leave it up to you to decide whether that experiment was a success.

This series describes the development of the sniffer from a fairly simple (and yet buggy) program into a more complete program with fewer bugs; the last version of the program is available for download from Resources.

Setting up the System

Flash prices continue to drop, and the test system was set up by installing NetBSD on a compact flash card. The only package installed from pkgsrc is perl58, and the only module added to it is the Curses module from CPAN. Because the application uses threading, Perl was built with the variable PERL5_USE_THREADS=yes set in /etc/mk.conf.

The goal of this application is to allow a user to connect, either over a serial console or over the network, to the system running the wireless code, and get updates on the current network status. Curses is a good way to get some of the flashiness of a graphical application without the overhead of using the X Window System or a Web server.

The program I’ll develop in this article is a small Perl script that uses system commands as a back end to access the wireless network. This program will run from the command line, and will read its configuration from a file. For now, the configuration file is just read from the current directory when the program starts. (Looking ahead, this might be useful on a machine with multiple network interfaces, with each interface watching a different wireless network.)

Scanning for Networks

On the first pass, I’ll simply build a program that scans for and lists wireless networks. This only shows networks that are broadcasting their identity to the world. The command for this, in NetBSD, is wiconfig interface -D. Because the interface might change from system to system, the application reads that information from a configuration file. The user is presented with a list of the names of found wireless networks, and selects one from the list; then the details of that network are displayed.

To do this, the program runs wiconfig, using the -D option, and parses the output. The results are stored in an array of references to hashes. Each member of the array holds the scan results for a single access point; each hash contains a list of name/value pairs, where the name is the heading. The output from wiconfig looks like Listing 1:

Listing 1. Network scan results



ap[0]:
ScanReason: [ Inquiry request from host ]
netname (SSID): [ testnet ]
BSSID: [ 00:02:dd:01:5a:44]
Channel: [ 3 ]
Quality/Signal/Noise [signal]: [ 57 / 59 / 2 ]
[dBm]: [ 57 / -90 / -147 ]
BSS Beacon Interval [msec]: [ 100 ]
Capinfo: [ ESS ]
DataRate [Mbps]: [ 1 ]

The code to parse this is fairly simple. Listing 2 illustrates the main components of the function; there’s a little setup work beforehand, but this is the interesting part.

Listing 2. Parsing network scan results

 

while (<WICONFIG>) {
chomp;
s/^[ ]*//;
goto found_ap if /^ap/;
($name, $value) = split(/:[ ]+/, $_, 2);
$value =~ s/^\[ *//;
$value =~ s/ *\]$//;
$x{$name} = $value;
print STDERR "$n: $name -> '$value'\n" if $debug > 1;
}
$nets[$n] = \%x;

In the resulting hash, the name netname (SSID) is associated with the value testnet. The long names are difficult to work with, but renaming them would just add another layer of confusion. (It would be worth doing, perhaps, given that the value named [dbm] makes no sense if you don’t recognize it as a subheading of Quality/Signal/Noise.)

Scans take a while, and monopolize the network interface, so it’s not reasonable to run them constantly. One solution to this problem is to run a network scan only when trying to pick a network, then look at the statistics for that individual network.

Because I am a somewhat lazy programmer, I use a status variable to keep track of the program state. The status variable tells the program what to do when it refreshes the display, and also what to do when it runs through the main loop. The program displays the current status at the top of the screen, general instructions at the bottom of the screen, and an error message (if there is one) one line above the general instructions.

The initial status, “About to probe network interfaces,” exists only to make sure something is displayed before the program starts doing interesting things. The first time it goes through the input loop, the program just changes its state to “Probing network interfaces.” (It doesn’t need any input to do this.) The next time it comes through, it displays that state, then runs the routine that actually reads the wiconfig output.

After that routine is finished scanning available access points, it changes status to “Found n networks,” where n is the number of interfaces found. Of course, that only happens if there actually are network interfaces found. If there are no networks, the status is changed to “No public networks in range.”

Looking at a Specific Network

To learn more about a network, you must associate with it. In fact, the wireless firmware, by default, looks for the best available access point; this assumption sounds great, but is likely to result in problems if the available access points are not all associated with the same network. To attach to a specific network under NetBSD, specify a nwid option to ifconfig.

After you’ve done that, you can rerun wiconfig without the -D option. This produces a fair amount of information; in fact, unless you’re using a very tall terminal, it won’t all fit on the display at one time. The simplest solution is to limit the number of lines displayed, letting the user scroll up and down through the list.

It might make sense to distinguish between card status (for instance, the MAC address field) and status specific to a network, but that takes up a lot more screen real estate. So, for now, the script just displays all the output from wiconfig. Listing 3 illustrates a partial sample output:

Listing 3. Network status

 

NIC serial number: [ 12420929J05J ]
Station name: [ ]
SSID for IBSS creation: [ ]
Current netname (SSID): [ testnet ]
Desired netname (SSID): [ ]
Current BSSID: [ 00:02:dd:01:5a:44 ]
Channel list: [ 1 2 3 4 5 6 7 8 9 10 11 ]
IBSS channel: [ 3 ]
Current channel: [ 3 ]
Comms quality/signal/noise: [ 92 154 2 ]

Thanks to the magic of threading, this data can be updated dynamically. In the sample code there’s a thread that reruns wiconfig regularly (about every second), repopulating the array with current data, which is displayed by the display thread.

Unfortunately, there’s more data than will fit on the screen at one time. To fix this, the code supports an offset value, which can be adjusted using the arrow keys, to let the user scroll through the items:

Listing 4. A window into a larger array



[...]
} elsif ($status =~ /^Showing/) {
$count = 0;
foreach $key (sort keys %network) {
++$count;
if ($count > $offset) {
printw("$key: $network{$key}\n");
}
last if (($count - $offset) > $LINES - 8);
}
if ($count == scalar keys %network) {
$max_offset = $offset;
}
} [...]

Broadcast SSID

One issue often brought up for wireless security is the broadcast of the SSID (Service Set Identifier), also known as the network name. Curiously, there is some debate about the benefits and tradeoffs of broadcasting your SSID. Many sites point out that disabling broadcast of the SSID makes it a little harder for potential intruders to detect or attach to your network. Some versions of Windows®, however, automatically prefer to find a network that is broadcasting its SSID. Apparently, current versions no longer do this; at least, not unless you set the “Automatically connect to non-preferred networks” option.

The ways in which you can disable SSID broadcast, and even whether this is possible, varies depending on your hardware. Most access points have a configuration program of some sort through which this setting is available. If you do use this, be sure you know what the SSID is that you are no longer broadcasting; you can’t join a network without knowing its SSID.

In general, disabling SSID broadcast is a defense against casual intruders, not against serious attempts to sniff your network. The one perhaps relevant case is that it will keep people from accidentally attaching to your network. You might think this is a ridiculous concern, but I’ve had it happen. One of the coffee shops I like to go to for free wireless access is in a building with some offices, which themselves contain wireless networking gear. On one occasion, I ended up inexplicably attached to the wrong network. Any private traffic on that company’s network is not only wide open to people looking for it; it’s wide open to people who sat at a table thirty feet too far from the coffee shop.

Entering an SSID by hand

On the other hand, you might want to look at a network without a broadcast SSID. That gives you an interesting user interface challenge: what’s a good way to let the user enter an SSID? The only case where the user is likely to need to enter an SSID is one in which the user already knows it — say, a fixed installation. Therefore, the SSID value can be added to the configuration file. If the configuration variable ssid is set, the program will start by associating with that network and displaying statistics about it.

At this point, the program is starting to serve a couple of divergent purposes. One is to sniff around for networks and report on them, another is to monitor a specific network. In general, the monitoring of a specific network implies that a lot more information is stored in the configuration file.

Access to the Program

It’d be nice to have a program like this associated with a user account so that someone could connect to the box (whether on console, over a serial port, or through the network) and just have this display up. One caveat is that the wiconfig program requires superuser privileges to scan for networks. Just scanning whatever network the card is associated with doesn’t require such privileges, but trying to probe for networks does.

However, making a user account with uid 0 and this program as a shell, while risky, is probably not quite as risky as giving everyone the root password to let them run it! Listing 5 shows the password file entry I used:

Listing 5. A password file entry.

probe:ZUOoIfQE48SZo:0:20::0:0:The probe thing:/home/probe:/home/probe/probe

All this code does is create an account with the user name probe that does nothing but run this little script. The account is accessible through ssh or by login from the console. All it does, for now, is run the script, giving status updates (however trivial) on the network.

Wrapping Things Up

At this point, the test program doesn’t do all that much. The main advantage it offers is that it’s a little friendlier than running programs on the command line. Wth the text-only access, you could run this program on a tiny little embedded box and check on its output remotely. Furthermore, the automatically-updating display lets you monitor a network over time. The display isn’t very useful, but you can at least have some of the most important data up and monitor the status of the network.

An obvious path for future development is support for WEP keys. Other network monitoring features might be nice; for instance, you might want it to recognize whether the base station that showed up is the one that should be there, so as to detect spoofed base stations. I’ll add some of this functionality in the next installment of this series.

Resources

• Download the final version of the code that accompanies this article.

• Try the Java-based Web Services (WS) Security with this free trial download .

• The WEP FAQ at Berkeley goes into more detail about why WEP isn’t good enough.

• Larry Loeb wrote an article for developerWorks on WEP security way back in April 2001; not all that much has changed since then.

• WPA is workable in OS X, Windows XP, and Linux, if you’ve got the right hardware and the right drivers; here’s some more information on setting it up WPA .

Wi-Fi Planet has an interesting article on wireless security issues: ” Understanding basic WLAN security issues , Eric Janszen (January 2002).

DWSA is a distributed wireless security auditor. It’s what you’d get if you had a research team working on a project like the one described in this series.

• Wi-Fi technology developments make wireless more pervasive as it becomes more useful to businesses, as this IBM e-Newsletter article discusses.

• Browse the bookstore on developerWorks for a good selection of titles on security issues.

2010-05-26T11:36:29+00:00 April 13th, 2005|Wireless|0 Comments

About the Author:

Peter Seebach has been sharing libraries ever since kindergarten, and continues to believe that the idea is basically sound, although the Recording Industry Association of America (RIAA) doesn't agree with him. You can contact Peter at developerworks at seebs.plethora.net.

Leave A Comment