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