Thursday, November 16, 2017


Working with Department13, Kismet now supports the DroneID UAV telemetry extensions!

What is DroneID?

Drone ID is a set of records created by DJI (the drone/UAV company) for identifying UAVs.
DJI intends to release drone ID as a public standard, but have preemptively enabled it across much of their hardware line. Through the efforts of several firmware reverse engineers (Freek van Tienen and Jan Dumon), we have the structure of the data being sent; more info is available in Freek's repository at github
A device with Drone ID enabled broadcasts the serial number, current location, height, horizontal and vertical speeds, pitch, roll, yaw, and the home location of the drone (where it took off from, and where it will return after a go-home command or loss of control.

Deep-diving into Drone ID

For more info about the Drone ID packet format and how it's used, check out the D13 white paper Anatomy of DJI Drone Identification Implementation.

Drone ID in Kismet

For Wi-Fi devices, the DroneID is attached to the beacon frame as a Vendor IE tag (tag 221); Kismet decodes this with a Kaitai parser and attaches it to the packet decoding records.
Kismet defines a new, generic phy, which it attaches to device records; A Wi-Fi device beaconing DroneID packets will contain both dot11.device and uav.device records:
"dot11.device": {
    "dot11.device.typeset": 1,
    "dot11.device.client_map": {},
    "dot11.device.advertised_ssid_map": {
        "447349704": {
            "dot11.advertisedssid.ssid": "Mavic-380000",
            "dot11.advertisedssid.ssidlen": 12,
            "dot11.advertisedssid.beacon": 1,
"uav.device": {
    "uav.manufacturer": "",
    "uav.serialnumber": "08RDE150010000",
    "uav.last_telemetry": {
        "uav.telemetry.location": {
            "": 40.000000,
            "kismet.common.location.lon": -83.00000,
            "kismet.common.location.alt": 273,
            "kismet.common.location.speed": 0,

Kismet tracks the serial number, home location, most recent telemetry location, and the past 128 telemetry locations.

Finding drones via the Kismet API

Devices which include DroneID records will have a 'UAV / Drone' category in the device details, but it's also possible to automate using the Kismet API.
The regex API in the Kismet REST interface allows for easy matching against drones, for example from the rest_examples/ script:
def per_device(d):
    print d['kismet.device.base.macaddr'],
    print d['dot11.device']['dot11.device.last_beaconed_ssid'],
    print d['uav.device']['uav.serialnumber'],
    print d['uav.device']['uav.last_telemetry']['uav.telemetry.location'][''],
    print d['uav.device']['uav.last_telemetry']['uav.telemetry.location']['kismet.common.location.lon']


kr = KismetRest.KismetConnector(uri)

regex = [
    [ "uav.device/uav.serialnumber", ".+" ]

kr.smart_device_list(callback = per_device, regex = regex)

Monday, October 16, 2017

WPA, the Krack Attack, and Kismet

The Krack Attack

[ Edited on 2017-10-17 to include definitive information about the ESP chip, additional commentary on TKIP mode, device scanning, and commentary on who it impacts]

[ Edited on 2017-10-19 to include additional info about Kismet alerts and clarification on what Krack is /not/ ]

Of course you've heard about the Krack attack by this point:

I strongly recommend reading the krackattack site, if not the full paper, too: They do an excellent job describing the attack and the real-world impacts. 

Definitely everyone should read the Q&A section first!

What it is

  • A collection of vulnerabilities that impact both access points and clients.
  • A method to decrypt some traffic, and on some specific clients, all traffic.
  • The largest vulnerability in the WPA suite to date, by a wide margin.
  • A very significant attack against Linux, Android, and OpenBSD clients.
  • Something to be concerned about and patch for.

What it isn't

  • A method to expose the WPA key.
  • A method to compromise encrypted communications (VPN, HTTPS, SSH, etc)
  • A method to compromise corporate credentials via EAP (assuming proper client configuration)
  • The end of the world.

How it works

There are many other breakdowns of the attack, including the excellent one on the Krack website itself, but at a 1000-foot-view:

WPA establishes a per-session key via 4-way handshake system which passes a public component of the unique session key (the Nonce).  By creating a fake access point and manipulating the handshakes, it is possible to fool a device into re-using a keystream; given two packets encrypted with the same keystream, it's possible to derive that keystream and decrypt them (but NOT the passphrase, remember).

Some devices have additional vulnerabilities (those using wpa_supplicant from Linux, including Android) which cause them to essentially disable encryption completely - resetting the key to all zeroes.

Detecting Krack with Kismet

The git-master version of Kismet is introducing alerts to attempt to detect a Krack-style attack underway.  To accomplish this, Kismet tracks several things used by the attack:
  1. Spoofed AP/Multichannel AP detection.  Kismet has had a long-standing alert for access points changing channels.  Currently, to manipulate the handshakes, the Krack vulnerabilities clone an access points MAC, but on a different channel.  Kismet will generate CHANCHANGE or BSSTIMESTAMP alerts for the two conflicting access points.  This is likely the most obvious indication that an attack is ongoing, however as the attack is refined in the future it may no longer be obvious.
  2. Key removal/degradation.  This variant of the attack is used against OpenBSD clients, and transmits a handshake with a zero-length key and zero nonce.  Kismet detects this by a fingerprint and raises the NONCEDEGRADE alert.
  3. Nonce retransmission.  Nearly all of the attacks in the Krack suite retransmit a previously used Nonce value, either as the 3rd handshake Nonce, or the first handshake ANonce value.  Kismet tracks the previous 128 Nonce and ANonce handshakes seen, and if a repeated Nonce is spotted, raises the NONCEREUSE alert.
Currently, most of the described Krack attacks - replaying a Nonce against a traditional supplicant - require spoofing the access point.  This should, in almost all cases, cause Kismet to be very noisy regarding the CHANCHANGE or BSSTIMESTAMP alerts.

In the future it may be possible to optimize these attacks so that there is no visible duplicate AP, but the current state of those attacks should be very obvious.

The 802.11r FT injection appears to be much more subtle - and much more difficult to detect, as different vendors implement the IV reset process differently.  Additional research will be needed to create an alert for those attacks.

Weaknesses in detecting Krack with Kismet

To detect the Nonce re-use, Kismet needs to actually observe the handshake packets.  Typically, Kismet channel hops across all channels supported by a card; this reduces the chance that Kismet will see the handshake.

Kismet supports multiple data sources simultaneously - this increases the chance of capturing the nonce, but also can introduce some false positives if two cards see the same packet.  Kismet now has packet de-duplication, which is turned on by default, which attempts to detect identical packets seen by multiple sources; in practice, this system still needs tuning.

The 802.11 protocol allows for automatic retransmit of data frames which are not acknowledged - and EAPOL exchanges are data frames.  This leads to multiple, different copies of the same EAPOL frame potentially being seen - this is exacerbated by the fact that Kismet may see the original, while the receiver may not!  To combat false-positives on EAPOL Nonce replays, Kismet now uses the timestamp of the packet - multiple Nonce or Anonce injects (Frame 1 or Frame 3 of the handshake), with the 'Retransmit' bit set in the dot11 frame control, in a very short period of time (0.1s) will be treated as valid.

Once the proof-of-concept code is release (or alternate proof-of-concept code is developed), the logic of the alerts will need to be tested.

How do I fix it

Generally speaking, the only fix is to upgrade your devices - you'll need upgrades for your access point firmware as well as upgrades to all of your client devices.

If you are using Linux or OpenBSD, fixes for wpa_supplicant should already be available.  Similar fixes are available for Windows 10 and OSX.

If your access point runs OpenWRT or LEDE there may be updated packages available, either through the package repository or by compiling new firmware.

Fixes for Android will depend on the security schedule for your device.  Typically, Google devices get patches monthly, devices from other manufacturers may take longer to get patched.

Kristopher Tate has created a Github repo tracking the update status of various vendors at

Can I just disable TKIP?

While parts of the Krack attack impact CCMP (WPA2), the worst impacts appear to be against TKIP (WPA1).  Many access points support WPA1 and WPA2 simultaneously, which leads to using TKIP as a group cipher (required for clients to send broadcast packets to other clients, regardless of WPA association type).  This has led some people to recommend disabling TKIP as a group cipher in your access point; it is unclear if this is actually successful.  From the FAQ of the Krack documentation:
I'm using WPA2 with only AES. That's also vulnerable?
Yes, that network configuration is also vulnerable. The attack works against both WPA1 and WPA2, against personal and enterprise networks, and against any cipher suite being used (WPA-TKIP, AES-CCMP, and GCMP). So everyone should update their devices to prevent the attack!
This would imply that simply disabling TKIP isn't a silver bullet against the attack, unfortunately.  It may also cause problems with large installations / corporate networks with multiple devices.

Should you care?

This is a significant breach of the WPA security model.  You should care - but only to a point.

If you are responsible for a financial, high-profile corporate, or government Wi-Fi install, you need to care, and be able to explain the risk.  Fortunately, in these situations, you'll also likely have vendors to talk to directly as well as management of the devices on your network.

If you're a home user - probably not.  The chances are, there won't be roving gangs of hooded youths cracking all the WPA networks in the neighborhood. 

In either case: patching is important, and should be done as soon as possible, but the chance that a new WPA vulnerability with no (currently) released code is the weakest point in your network is pretty slim.  Update immediately.  Update your users and customers immediately.  Pressure your vendors to update if they haven't already.  Find the devices on your network which have not gotten updates.

Scanning for vulnerable devices

At this time, there is no simple way to determine if devices are vulnerable, however there should be tools available in the future from the Krack developer which can perform some active probing to determine if a stack is vulnerable.

Currently, the Kismet detections only detect the replay of nonces, and cannot passively detect vulnerable devices; if a method to do so becomes available, it will be included in Kismet.

Detecting vulnerable devices will be a particular problem for anyone who has to manage a BYOD network, where users may continue to bring outdated, vulnerable devices onto the network for the foreseeable future (such as unpatched Android devices).

The risk in the future

When WEP was first shown to be vulnerable, it required the collection of millions of packets over the course of hours or days before it could be attacked.  Once the method was refined, the network could be cracked in a matter of minutes or even seconds.

There is always the chance that this attack, or ones derived from it, will be refined into a much more significant, automated, or wide-ranging attack.  Patching as soon as possible is the panacea against this.

The largest risk in the future is likely to be devices for which no patch is available:  abandoned mobile devices which no longer receive patches from the carrier or manufacturer, appliances and vehicles with Wi-Fi included, and embedded and IOT devices which use a Linux or Android Wi-Fi stack including wpa_supplicant.  As bad, fully embedded systems based on chips like the ESP8266 may also be vulnerable.

The inability to update many devices in the wireless ecosystem means these flaws will persist and remain as potential jumping-off points for more advanced attacks against networks for a long, long time.

Thursday, July 27, 2017

Remote Capture

Kismet once again supports remote capture in git-master!

Remote packet capture allows multiple systems to report packets back to a single, central Kismet server.  This makes it simple to use light-weight, and usually cheap, embedded devices as remote sensors to expand physical coverage or logical channel coverage.

Remote capture uses the same binaries Kismet uses locally to capture from data sources - for instance, 'kismet_cap_linux_wifi'.  These super-lightweight capture drivers can run on almost any openwrt/lede supported system; the latest version is a 64Kb package, making it plausible to install on almost any device, including limited devices with 4MB of flash.

Remote capture binaries use a fixed amount of RAM - buffers are allocated at the start and are not dynamically adjusted - which means each radio capture uses approximately 4MB of RAM.

Remote capture sources use the same protocol as local, traditional sources - instead of an IPC channel the communication is piped over a TCP socket.  Kismet is able to track what source saw a packet, per-source GPS, using per-source or centralized timestamps, and is able to distribute channels and control channel hopping and other behaviors of remote sources.

More info is in the README:

xx. Remote Packet Capture

    Kismet can capture from a remote source over a TCP connection.

    Kismet remote packet feeds are initiated by the same tools that Kismet uses to
    configure a local source; for example if Kismet is running on a host on IP, to capture from a Linux Wi-Fi device on another device you could

        $ /usr/local/bin/kismet_capture_tools/kismet_cap_linux_wifi \
            --connect --source=wlan1

    Specifically, this uses the kismet_cap_linux_wifi tool, which is by default 
    installed in `/usr/local/bin/kismet_capture_tools/`, to connect to the IP port 3501.

    The --source=... parameter is the same as you would use in a `source=' Kismet
    configuration file entry, or as `-c' to Kismet itself.

    By default, Kismet only allows remote packet connections from the localhost IP; 
    you must either:

    1.  Set up a tunnel, for example using SSH port forwarding, to connect the remote 
        device to the host Kismet is running on.  This is very simple to do, and adds
        security to the remote packet connection:

        $ ssh someuser@ -L 3501:localhost:3501

        Then in another terminal:

        $ /usr/local/bin/kismet_capture_tools/kismet_cap_linux_wifi \
            --connect localhost:3501 --source=wlan1

        The `ssh' command places SSH in the background (using `-f'), connects to 
        the host Kismet is running on, and tunnels port 3501.

        The kismet_cap_linux_wifi command is the same as the first example, but
        connects to localhost:3501 to use the SSH port forwarding.

        Other, more elegant solutions exist for building the SSH tunnel, such 
        as `autossh'.

    2.  Kismet can be configured to accept connections on a specific interface,
        or from all IP addresses, by changing the `remote_capture_listen=' line in


        would enable listening on all interfaces, while


        would enable listening only on the given IP (again using the above example 
        of Kismet running on

        Remote capture *should only be enabled on interfaces on a protected LAN*.

    Additional remote capture arguments

    Kismet capture tools supporting remote capture also support the following options:


        Connects to a remote Kismet server on [host] and port [port].  When using
        `--connect=...' you MUST specify a `--source=...' options

    --source=[source definition]

        Define a source; this is used only in remote connection mode.  The source
        definition is the same as defining a local source for Kismet via `-c' or
        the `source=' config file option.


        By default, a remote source will attempt to reconnect if the connection
        to the Kismet server is lost.


        Places the capture tool in the background and daemonizes it.

A huge thanks to all who support Kismet on Patreon - if you'd like to help, you can become a patron here!

Tuesday, June 6, 2017

Kismet Plugins - Web-only Plugins

The new Kismet plugin architecture is beginning to solidify, and as part of that, the ability to create plugins which only affect the Web UI is now in place.

If your plugin idea doesn't require any changes to how Kismet itself functions, and only modifies or adds to the Web UI, you can now do it as a runtime-loaded add-in with no C++ coding at all, and only minimal modification of the example Makefile.

The example code is in Kismet git under plugin-demo-webonly; you can browse it at .

All plugins, regardless of if they use C++ native code or only extend the web UI, have 2 files which must be present:
  1. Makefile, which tells the build system how to compile.  For web-only plugins this file is very simple, and the only change that needs to be made is changing the name of the plugin on the first line (PLUGIN_NAME ?= ...).  This plugin name is used to control the directory the plugin is installed into.
  2. manifest.conf, which tells Kismet about the plugin.  This is a simple config file that is very similar to the Kismet config files; it contains the name, description, author information, version information, and module information.
For a web-only plugin, the manifest only needs to define the name, version, description, and author fields.  To tell Kismet to load a JS object when the web UI is loaded, there also needs to be a 'js' parameter.

Plugins are automatically mapped into the Kismet webserver, serving content from [plugindir]/[pluginname]/httpd/ on the filesystem to the URL /plugin/[pluginname]/.  The plugin directory is automatically determined and mapped, regardless if it is installed system-wide or in a user directory; This means you can serve full content from your plugins httpd/ directory.

To dynamically load JS modules, Kismet expects a few standard conventions - the demo JS file in the example plugin shows the minimal basics, but for more information about how to automatically interface with the Kismet web UI framework, check out some of the developer docs:

  • explains how to use various endpoints in Kismet to get additional data
  • explains the format of Javascript modules and how to hook into existing functions in the Kismet UI, like adding settings panels, sidebar triggers, tabbed frames, etc
  • explains how to add additional details to the Kismet device details windows, which are shown when you click on a device.

A huge thanks to all who support Kismet on Patreon - if you'd like to help, you can become a patron here!

Monday, May 22, 2017

Eliminating default passwords from Kismet

Kismet no longer uses a default password distributed in the kismet_httpd.conf config file; it will now auto-generate a random password and store it in ~/.kismet/kismet_httpd.conf

As part of this process, there are some new onboarding screens for Kismet:

Kismet will now show a local-only text alert (not sent to the browser or other message bus clients) showing the new password which has been generated.

Kismet will also show an alert that a new password has been generated, and warning existing users of the git-master code that the old config option is no longer used.

The first time you visit Kismet with your browser (or the first time for a particular browser - the setting is stored in HTML5 local storage so it is specific per browser), you'll get a welcome screen asking to take you to the settings panel.

The settings panel now describes the need to change the login.

Subsequent visits to the Kismet page will warn you if the password is invalid, and offer to take you to the settings panel.  If you're a guest on a server, or don't want to log in for some reason, these alerts can be silenced with the "Don't warn again" option.

Finally, the new settings handler can confirm the validity of the login and warn if it is not valid.

While these add a few extra steps, the added security of not having default logins potentially exposed to the Internet definitely outweighs it.

Installation-time passwords can still be set by using the httpd_username= and httpd_password= options in /usr/local/etc/kismet_httpd.conf, or in the per-user ~/.kismet/kismet_httpd.conf, and the random generated password can be changed by editing ~/.kismet/kismet_httpd.conf as well.

A huge thanks to all who support Kismet on Patreon - if you'd like to help, you can become a patron here!

Monday, May 15, 2017

Fun with a new toy - Kismet on the Alftel Airbud

Alftel ( were very kind and sent me the production rev of their Airbud platform to get Kismet running on it.

Anyone who swung by the NOC at Shmoocon might have seen the pre-production Airbud running a demo there:

The final rev is a lot more elegant!

It's an Intel platform - which means it will happily run Ubuntu, Fedora, Pentoo, and so on - with an ungodly number of mpci-e slots for radios (8x on this model):

This one is stocked with Atheros 11n 2x2 which have been the most stable so far in testing - I've had nothing but misery with the ath10k reporting bogus packets in a HT data environment, and the Intel cards can get into monitor mode but seem to have firmware issues which cause the interface to reset during tuning.

Happily, Kismet's new datasource code handles the multiple interfaces just fine, and I think it's going to ultimately be a lot more stable than the older style code.  Previously, Kismet multiplexed all the sources into a single IPC channel and controlled them from a single process; under the new model, Kismet spawns a process per interface for capture.

Some interesting things happen with this many devices - even scanning both bands and all HT channels, the coverage graph stays pretty flat - we're able to cover enough channels simultaneously that Kismet can maintain a fairly constant view of the devices:

With an estimated coverage map (which is a lot more interesting when it's live and animated) of:

With the new data source REST API it should be possible in the future, with fairly minimal coding effort, to also assign a source to lock on to specific channels when a device is highlighted  - making sure to capture as much information as possible about a specific device or AP while the rest of the interfaces continue channel hopping.

If you're interested in the Airbud HW, check out the Alftel website at for more info.

A huge thanks to all who support Kismet on Patreon - if you'd like to help, you can become a patron here!

Wednesday, May 10, 2017

Pcap over HTTP and other fun

Pcap over HTTP!

Kismet git-master now supports fetching pcap logs over the HTTP REST interface!

$ curl -s  http://kismet:kismet@localhost:2501/datasource/pcap/all_sources.pcapng | tshark -r -
    1   0.000000              → ImpathNe_a2:76:f2 (00:03:d8:a2:76:f2) (RA) 802.11 50 Acknowledgement, Flags=...P....C
    2   0.133960 06:18:d6:9d:0d:ac → Broadcast    802.11 252 Beacon frame, SN=1654, FN=0, Flags=........C, BI=100, SSID=UESC
    3   0.184984 16:18:d6:9d:0d:ac → Broadcast    802.11 254 Beacon frame, SN=2266, FN=0, Flags=........C, BI=100, SSID=UESC-N
    4   0.236459 06:18:d6:9d:0d:ac → Broadcast    802.11 252 Beacon frame, SN=1655, FN=0, Flags=........C, BI=100, SSID=UESC
    5   0.273332 D&MHoldi_a0:8f:26 → Broadcast    802.11 142 Probe Request, SN=9, FN=0, Flags=........C, SSID=                                

Not only that, but Kismet now supports the pcap-ng file format; this new format allows for multiple interfaces in a single capture file, as well as conflicting linktypes in a single capture.

There are a few trade-offs:  Programs written using traditional libpcap (tcpdump, many other utilities, and Kismet itself) can handle pcap-ng files with a single link type, but cannot currently handle mixed link types in the same capture file - so for instance mixing Wi-Fi and future non-Wi-Fi packets may cause a problem.

No worries - you can also capture packets from a single specific interface, by UUID:

$ curl -s http://kismet:kismet@localhost:2501/datasource/pcap/by-uuid/5fe308bd-0000-0000-0000-a0f3c10cbf1c/packets.pcapng | tcpdump -r -
reading from file -, link-type IEEE802_11_RADIO (802.11 plus radiotap header)
13:55:38.239867 913824498us tsft 24.0 Mb/s 2437 MHz 11g -86dBm signal -86dBm signal antenna 0 Acknowledgment RA:00:03:d8:a2:76:f2 (oui Unknown) 
13:55:38.263293 913845355us tsft 24.0 Mb/s 2437 MHz 11g -86dBm signal -86dBm signal antenna 0 Acknowledgment RA:00:03:d8:a2:76:f2 (oui Unknown) 
13:55:38.265179 913847499us tsft 1.0 Mb/s 2437 MHz 11b -95dBm signal -93dBm signal antenna 0 Beacon (A276EC) [1.0* 2.0* 5.5* 11.0* 6.0* 9.0 12.0* 18.0 Mbit] ESS CH: 6, PRIVACY
13:55:38.303905 913886656us tsft 1.0 Mb/s 2437 MHz 11b -89dBm signal -89dBm signal antenna 0 Beacon (UESC) [1.0* 2.0* 5.5* 11.0* 18.0 24.0* 36.0 54.0 Mbit] ESS CH: 6, PRIVACY

Saving pcaps dynamically

Pcap logs are sent as a constant HTTP stream, streaming the live packet data out of Kismet.  If you have configured your Kismet instance to use HTTPS, they'll be encrypted of course.  They can be send directly to tools via pipes as in the above examples, or they can be sent to a file:

$ wget --auth-no-challenge http://kismet:kismet@localhost:2501/data/all_packets.pcapng -O packets.pcapng
--2017-05-10 13:58:28--  http://kismet:*password*@localhost:2501/data/all_packets.pcapng
Resolving localhost (localhost)...
Connecting to localhost (localhost)||:2501... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified
Saving to: ‘packets.pcapng’

packets.pcapng             [       <=>                 ]  15.41K  2.16KB/s

Better data!

Because pcap-ng allows us to retain the original link types, Kismet now logs the original radiotap data instead of converting it to PPI.  This preserves the entirety of the radiotap header - the MCS encoding data, the per-antenna signal data, everything held in the original record is now present in the output:

More coming soon...

Expect additional built-in pcap filtering endpoints coming soon - per-phy, per-bssid, and multi-bssid are on the list, as well as options in the UI to link to downloading pcaps directly.

As the new logging infrastructure evolves in Kismet pcapng will become the standard logging format for constant logging as well, with the option to split into multiple files recording a stream per source, or a single file combining all the sources.

A huge thanks to all who support Kismet on Patreon - if you'd like to help, you can become a patron here!

Wednesday, April 19, 2017

Data sources - new Kismet capture code!

I've just pushed a large change into the git-master branch for Kismet:  Data sources.

Data sources replace the Kismet packet capture system (previously internally called 'capsources', truly, the most original of names).  This reworks the whole privilege separation, IPC, capture, channel control, and source definition systems.

At a high level, datasources split the capture into an independent process per interface: this allows the capture process to be written in any language which can speak a simple IPC API, and opens the door for capturing using Python (specifically for support with GNU Radio and other tools).  High-CPU capture methods (like SDR capture) will no longer interfere with Kismet in general by taking too much time in capture loops, plugins can install suid-root capture tools to do proper privilege separation, and in general adding new capture code should become much much simpler.

As part of this rewrite, the 'kismet_capture' binary is now gone - previously, this was a C++ binary launched as root by Kismet which wrapped all the C++ capture code and fed packets to Kismet.  In it's place are independent binaries for each data source type; currently kismet_cap_pcapfile which handles replaying previously logged data, and kismet_cap_linux_wifi which implements the mac80211 and legacy wireless ioctl driver interfaces.

Splitting the capture binaries up allows each binary to enable root only as needed - pcapfile does not, linux wifi does - and minimizes the code running in the root binary.

The rewrite of the Linux Wi-Fi capture engine also solves a number of lurking problems:  the ability to tune to HT and VHT channels (HT40+/- 802.11n and 80 and 160MHz 802.11ac), the rfkill system preventing us from bringing up interfaces, very long interface names on some distributions breaking the monitor vif creation, and NetworkManager reconfiguring the interface out from under us.

The new channel tuning automatically detects HT40, 80, and 160MHz channels by comparing the list of supported frequencies and band capabilities reported by mac80211; doing proper tuning to these channels helps with data capture on 11n and 11ac devices.

All of these changes have required more modifications to the config file - before upgrading to the latest git-master code, check out the README at:

which, while being rewritten, includes directions on how to prep the install and the new configuration options for sources.

The internals of the new datasource protocol are being documented at:

and the pure-C capture framework at

both docs are under heavy dev so check back for more updates soon.

There will certainly be some bugs exposed in the new system, and the GUI is still being built which will allow picking interfaces, reconfiguring them, and adding new ones while Kismet is running - more on that to come!  In the meantime, swing by IRC (#kismet on, Discord (link to the right), or ping bugs to @kismetwireless on twitter!

Over the next few days missing features (re-opening sources in error, per-source channel lists and exclusions, and similar) will be restored in data sources.

If you're interested in helping bring Kismet support for a non-linux platform up to date (BSD and OSX come to mind!) please, ping via one of the above channels and we can talk about the new capture API; with each platform using its own binary for capture, maintaining platform ports should be much simpler.

A huge thanks to all who support Kismet on Patreon - if you'd like to help, you can become a patron here!

Friday, March 31, 2017

Scripting Against The Web Interface, Part 2

Different Ways To Get Devices

These examples should work with any language, but for now we'll look at using the Python class provided with Kismet; no particular reason, but I needed Python for some other tasks, it's used in GNURadio, and it's a just generally a popular language.

(If you'd like to implement a similar utility class in Ruby or any other language, please do, and consider sending it my way!)

JSON vs Msgpack

Nearly all the interfaces in Kismet support multiple types of output serialization - currently JSON and Msgpack, which is a binary packed format which can represent the same style of data.

The Python API favors the msgpack variants because pymsgpack is easy to use and quickly returns complete Python objects; there's no reason not to use JSON however.  Both will return identical data in identical structures, and can be turned into native language objects.

All of the example URLs should work on either - substitute ".json" as the extension instead of ".msgpack" if you're not using the Python KismetRest interface code.

Listing devices

There are several ways to get a list of devices from Kismet.  In general they all allow selecting specific fields, groups of fields, or simple matching.

The simplest method for fetching devices is to simply ask for a list of all of them; this will enumerate every device Kismet knows about and return a list:


for instance will return all devices in the system, formatted as JSON, with full objects for all devices.

The downside to the simple method is that it enumerates all devices in the system.  This works fine for dozens or hundreds of devices, but if you're querying a system with thousands or tens of thousands of devices, it can cause significant lag and visible issues - dropped packets, an unresponsive server, etc.  (Internally, this happens because Kismet needs to lock the device list while it processes all the devices, which means new packets can't update devices as they arrive).  In the worst case this can cause Kismet to abort if it takes more than 5 seconds to process the list; on a slow system with tens of thousands of devices it can take some time.

The simplest query

Using the KismetRest client, you can get a list of devices with the device_summary() function:

import KismetRest
import time

kr = KismetRest.KismetConnector("http://localhost:2501")
devices = kr.device_summary()
while 1:
    print devices

This will print all the devices Kismet knows about (as python objects, not the prettiest output in the world) once a second.

This method will ONLY work well for very small numbers of devices - tens to hundreds.  If your Kismet server can see thousands of devices or more, this will likely have a noticeable performance hit.

Making it better: Query by time

But how do we make this better?  The first, and easiest, way to reduce the impact is to reduce the number of devices we look at.  We can accomplish this with the device_summary_since(ts) function, which calls /devices/last-time/[ts]/devices.msgpack (or devices.json of course) endpoint with a timestamp; Kismet will only return devices which have been created or modified after the timestamp provided.

import KismetRest

kr = KismetRest.KismetConnector("http://localhost:2501")

# Initialize our timestamp to 0
ts = 0

while 1:
    summary = kr.device_summary_since(ts)

    # Get our timestamp from the response!
    ts = summary['kismet.devicelist.timestamp']

    print summary['kismet.device.list']


By starting with a timestamp of 0 we request every device Kismet knows about (since all have been modified since the start of time).  After that first request, we save the current server timestamp (from the 'kismet.devicelist.timestamp' field) and use it to make our queries in the future; from then on we'll only get devices which have changed since the last time we looked, no matter how long we sleep in between.

This approach still has some problems; the initial query can take a LOT of processing power if there are a huge number of devices, because it still has to look up every single device.

Make it better: Simplify what we're asking for

The next way to reduce the impact on the server is to apply a simplification of the fields: This returns only the fields specified, instead of every field (and sub-field) in the device object, which can reduce the load of serialization by a factor of hundreds.

If you're familiar with SQL, this is the difference between doing a select * and doing a select field1, field2, ... ; By excluding data you don't care about you can greatly reduce the impact.

Fields can be specified by name or by path:

  • "" would select the channel field from the device object
  • "kismet.device.base.signal" would select the entire signal object from the device object and include it.
  • "kismet.device.base.signal/kismet.common.signal.last_signal_dbm" would select the last signal record from the signal object.  Fields selected by path are always placed in the result as the final field in the path, so our object would contain kismet.common.signal.last_signal_dbm
Fields can also be specified as pairs, where a field is renamed - if you need two fields in different paths, of the same name, they can be specified as an array of 2 elements: ["kismet.device.base.signa/kismet.common.signal.last_signal_dbm", "last_base_signal"] would rename the last_signal_dbm field.

Field simplification is done by POSTing to /devices/summary/devices.json or to /devices/last-time/[ts]/devices.json (or, of course, .msgpack).

In the Kismet Rest API, you can use the smart_summary_since(...) function:

fields = [
        "", # Standard channel field
        "unknown_field", # Requesting an unknown field will return a field containing integer 0
        "dot11.device/dot11.device.last_beaconed_ssid", # Complex path specification
        ["kismet.device.base.key", "dev.key"], # Fields may be renamed
        "kismet.device.base.packets.rrd" # Fields can be complex objects

while 1:

    # Get summary of devices
    devices = kr.smart_summary_since(sincets, fields)

Installing the Kismet Rest code

The Python utility class used by all of the python examples is in rest_examples/KismetRest and operates like a normal Python module - to install it, install like you would any other module:

$ cd rest_examples/KismetRest
$ python2 ./ build
$ sudo python2 ./ install

While development is ongoing it's probably a good idea to keep an eye on the changelog for the Python KismetRest interface in git and upgrade it; I'll try to make any API-breaking changes pretty explicit in the commit logs.

Next time...

That should be enough to get started with some simple scripting interfaces; the next post will talk about how to filter results with regular expressions, get info about the general state of the system, and some other fun tricks.

A huge thanks to all who support Kismet on Patreon - if you'd like to help, you can become a patron here!

Thursday, March 23, 2017

Scripting Against The Web Interface, Part 1

New Server Model

Recently I've seen several questions about connecting to the Kismet server with scripting tools - while possible with the stable/old Kismet, it's so much easier under the git-master code that I strongly recommend anyone developing something new that draws from Kismet look at runnign the git-master version instead.

The new Kismet code uses an embedded webserver (libmicrohttpd) to serve data as a collection of REST-like endpoints.

Object Data

Data is now stored in Kismet in introspectable (meaning they can be processed by the code automatically without having to know what they contain beforehand) dictionary-like (meaning they're usually structured as a collection of "key" = "value" records) objects.

The upshot of this is that they can be converted into interchange formats like JSON and exported as complete objects; Unlike the old Kismet protocol which was line-based and generally operated like a relational database:  Nested data had to be represented with multiple different server sentences, with a common key to correlate them.

By exporting complete objects, we are able to use a single request to represent an entire complex, nested entity.  By using introspectable objects, we're able to add new data to it without having to change the export code, which means plugins (and future Kismet code itself) can easily expand the data tracked for a device (or add whole new types of data), and by using a REST-like interface we can organize it simply and use common, standard protocols to access it.

Basic Interfaces

Currently Kismet data can be exported as JSON or binary Msgpack.  The format and field names on both should be identical - you can pick which you prefer by requesting a '.json' or a '.msgpack' field.  In the future, XML export may be possible, but JSON solves nearly all the problems XML would, and has simpler parsers in most languages.

Kismet also has a few special interfaces which export other data - notably the /system/tracked_fields.html interface which shows a HTML-formatted table of every named field Kismet knows about & their descriptions (great for looking up how a field is used without digging into the code), and the /phy/phy80211/handshake/[device]/[device]-handshake.pcap interface, which allows downloading a dynamically-created PCAP file.

Available Interfaces

All the currently available interfaces are defined in the webui_rest document:

which documents how to reach them, what they do, and what parameters they take.

There is a python class for handling interacting with Kismet and a collection of code doing interesting things with it at:

Part 2

Part 2 will focus on some of the specifics and provide some examples for doing interesting things, stay tuned!

A huge thanks to all who support Kismet on Patreon - if you'd like to help, you can become a patron here!

Monday, March 20, 2017

Discord (the good kind)

I've brought up a Discord server for chatting about Kismet related things: Kismet Discord

We're also on in #kismet for those who prefer IRC!

Tuesday, March 14, 2017

WPA Handshake Collection (Kismet git-master)

Another new feature in Kismet git-master:  WPA handshake collection!

Thanks to the new data format Kismet uses, it's possible to add additional complex fields to network records, trivially.  One of the fields we can add:  WPA packets!

This lets Kismet collect WPA handshakes and provide them as pcap files directly over the web ui.

Let's look for a network with captured handshakes

Kismet will highlight networks with a complete WPA handshake (or what appears to be a complete handshake) automatically.

For fun, you can also change the color of the highlighted network in the settings...

Look at the network details

The network details will show the handshake and offer a PCAP download if there is a complete handshake.  To be crackable, the handshake needs at least packets 1 and 2 or 2 and 3, and preferably all four packets of the handshake.  If you have insufficient packets, Kismet will warn you:

Internally this is stored as a bitset (where packet sequences 1, 2, 3, and 4 are bits 0, 1, 2, and 3 respectively) so scripts can easily check to see which handshake components a network has; rest_examples/ shows a quick use of this:

        if ((d['dot11.device.wpa_present_handshake'] & 0x06) == 0x06 or
                (d['dot11.device.wpa_present_handshake'] & 0x0C) == 0x0C):
            pkts = []
            for i in range(1, 5):
                if d['dot11.device.wpa_present_handshake'] & i:

Download the pcap

Download the pcap file.  You'll be prompted for your username and password you configured in kismet_httpd.conf - you did change the default password, right?

Take a look in Wireshark

You can open the pcap in Wireshark to take a look - you'll see that Kismet saves the handshake packets only, making a very small pcap file.  This is similar to trimming a much larger pcap file, only the packets required by Aircrack (or similar tools) are included.

Run Aircrack-NG

Or whatever tool you like; for Aircrack the syntax would be:

aircrack-ng -w wordlist -e UESC-N -b 0E-18-D6-9D-0D-AC 0E-18-D6-9D-0D-AC-handshake.pcap

Note that we provide the wordlist (-w), the ESSID (-e), and the BSSID (-b), and the PCAP we downloaded from Kismet.  You need all these parameters for Aircrack to detect the handshakes properly from the PCAP Kismet generates.

Let the magic happen 

Obviously this (also obviously doctored) screenshot took no time because we populated the wordlist with only one entry:  The known PSK for this network. 

Where to get it

This is in the Kismet git-master code, located at or at the Github mirror at if you want to live on the edge, and it will show up in the next major Kismet release including the web-ui and all the other new code.

Monday, March 13, 2017

Lots of new code in Kismet

Updates have been going to Twitter (@KismetWireless) but there's been a lack of content here:  Lets try to fix that!

Lots of new stuff:

  1. New object storage model.  
    Kismet now uses which is basically an introspectable dictionary structure to store all it's data internally.  Basically this means that instead of storing the data and then having to write custom output code for every type of interaction (logging, kismet client, etc), there is now a common data "blob" which can be turned into different things.
    This makes it tremendously simpler to add new features, new tracked elements, and non Wi-Fi data to Kismet.
    Even better, all the fields are documented on creation - every field in the hierarchy has a description and a human-readable name.
  2. Embedded webserver and web-ui.  Kismet now uses microhttpd to provide a built-in webserver capable of serving static (ie JS/HTML/etc content for the webui) and dynamic (REST-style endpoints with JSON data) content.
    The web-ui will be exposed to plugins so that they will be able to provide their own content to render custom data.
  3. Easily scriptable REST-style data.Instead of a custom TCP network protocol, Kismet now provides all the data via a REST-style web interface.
    This means scripts can pull data like network lists, packet rate, GPS location, battery status, everything Kismet knows, as standard JSON.

  4. Much simpler interface for non Wi-Fi dataThere is initial support already in Kismet now for some simple non-dot11 devices; wireless thermometers, weather stations, and other devices detected by the rtl433 tool for the RTLSDR, and Z-Wave home automation devices detected by KillerZee and a RFCat compatible tool, such as the Yardstick One.
    The new data structure allows new phy-handling code to plug into the existing device record and append new, arbitrary data structures, such as weather records, Z-Wave identifiers, etc
    Low-data-rate sources can even use the REST interface to submit data, which is how the RTL433 and KillerZee interfaces currently work.

More on the Web UI

The new web-ui allows much more data to be presented, as well as a huge amount of flexibility for displaying the information.  The web-ui is built on top of jquery and common open source jquery and js modules.

Using the seamless paging interface in jquery-datatables lets Kismet handle tens of thousands of devices with server-side sorting, filtering, and searching, while still being able to display reasonably on low-power devices, including mobile.

More coming

Development is going quickly on a number of new features & restoring currently broken functionality; coming soon will be the new packet capture framework, etc.  Keep an eye out for future posts with more info about new features.

What's broken

The new code is under heavy development so there's a number of things which don't currently work:  Text logging (text/netxml) and GPS logging (gpsxml) currently are disabled, filtering doesn't work, most plugins are unlikely to be happy or even compile, and various other subsystems have issues and quirks.

All of these are being addressed, of course.

Jumping in

If you want to jump in on the latest dev code, it's available from the git-master branch at either or