Wednesday, October 25, 2017

Writing Custom IDS Signatures for Cisco WLCs

The recent discovery of flaws of WPA/WPA2, network operators are paying more attention the the security monitoring capabilities of their wireless infrastructure. Although the severity of KRACK is debatable, paying attention to threats to your wireless network is still a wise practice.

Cisco wireless controllers provide two methods of security monitoring with no licensing requirements other than AP adoption licenses: rogue AP scanning and IDS signature monitoring. The risk of rogue APs are well known. This blog will focus on IDS signature monitoring.

IDS signature monitoring works by listening for common attacks against wireless networks including deauthentication and EAPOL floods. It does this by looking for specific patterns in individual 802.11 frames and analyzing the frequency with which those packets are heard. If enough matching frames are received within a defined window of time, an alert is triggered and (optionally) a trap is sent to a NMS. Cisco WLCs come with a set of pre-defined signatures.

Standard IDS Signatures
Clicking on the signature precedence number will load a page that allows you to edit some parameters of the signature (more details later), but you will not be able to edit the patterns that the IDS signature will look for in frames. It will list them, but you can't edit them. If you want to make your own signatures, you will need to upload a signature file with the signature definitions in them in plain text.

To get an idea of how to create your own signatures, you can upload the standard signature file from a controller to a TFTP server. The signature file is in plain text, and extraordinarily well notated. Go to Commands -> Upload file. Select Signature File from the from the File Type drop-down, and enter your details for how to transfer the file.

Uploading the Standard Signatures
The standard signature file is very well documented, and describes the syntax required to make a signature. Rather than duplicating the information in the standard signature file, I will focus on the most important aspect of a signature: patterns. A pattern specifies a section of the 802.11 frame to extract and inspect. The section extracted can be one or more bytes, and it is selected by specifying an offset value in bytes (starting at zero), and where to start the offset from; the header or the frame body. The extracted bytes are compared to a user supplied bitmask with a binary AND operation. The result of the AND is compared to a user-defined value, and if they are equal, the pattern is a match. Signatures can contain one or more patterns, and each pattern must evaluate to true (be a match) for the whole signature to match a frame. The format of each pattern is


The start parameter is a bit the defines where you start the offset from; 0 for the frame header and 1 for the frame body.

You might be asking "Why the AND operation?" Why not just specify exactly what to match? The answer to that question is: sometimes it's not important that a whole byte matches, but that a specific bit matches. The bitmask with AND operation allows the user to specify exactly which bits are important. If a bit in the mask is set to 0, whether or not that bit matches is not important. If the bit in the mask is set to 1, it is required for the pattern to result in a match.

Here's an example. Suppose you wanted to write a signature that matched all frames transmitted by a locally administered MAC address. The IEEE defines locally administered (non-unique) MAC addresses as having the 2nd least-significant bit in the first octet as having a value of 1. To determine if a transmitting address is locally administered, we only need to look at the 2nd LSB in the first octet of the address. A pattern to match this would be 0:10:0x02:0x02. This pattern reads "Start at the frame header and go to the 10th byte (starting from 0), extract 1 byte from that position (implied by the length of the mask), AND it with 0x02, and if the result is 0x02, there is a match." Since locally administered MAC addresses will have the 2nd LSB equal to 1, a mask of 0x02 is all that needed. None of the other bits matter in making the determination.

Before we go any further, I should point out that it's very helpful to have a packet analyzer like Wireshark or Omnipeek handy while writing IDS signatures. If you have pcaps of the kinds of frames that you want to catch with an IDS filter, it makes it much easier to write the patterns.

There was was something that confused me though, and it was how patterns that inspected the frame control field were written. Below is a screen grab of an authentication frame from Wireshark.

Authentication Frame
Wireshark shows the Frame Control field as 0xB000; the first byte is the type/subtype, and the second byte represents the flags. When you look at the standard signature file for the "Auth Flood" signature however, the pattern looks like this:

It appears that the order of the flags and type/subtype bytes are reversed in the pattern, at least as compared to Wireshark. Other fields like addresses do not appear to have the same reversal. I'm going to take it on faith that Cisco wrote the signatures correctly, and use the same format when writing signatures that have to match a pattern in the frame control field.

Each signature requires at least one pattern and other parameters. You can read about them in the standard signature file, but I will outline them here too.

  • Version: The version of signature syntax. There is only one allowed value: 0. 
  • FrmType: The type of frame you want to inspect. The two options are data and mgmt (for management frames).
  • Interval: The amount of time in seconds that frames are collected and attempted to match to the signature. 
  • Freq: The number of frames that must match the signature within the interval before an action is taken. This essentially defines a rate for matching packets.
  • Action: What to do when a signature matches frequency frames in interval time. There are only two options: none (do nothing) and report. 
  • Quiet: The amount of time that must pass since the last frame that matched the signature in order for the alert to be cleared. 
  • Track: Defines how to track the alarm event when the signature is matched. Option are tracking by signature, tracking by offending MAC, or both. 
  • MacFreq: Optional parameter that sets the frequency of matched frames required to trigger the alert action if tracking the signature by MAC address.
Now let's take a look at writing some useful signatures. Shortly after the announcement of the KRACK vulnerabilities, a sample script for the 802.11r FT attack was published. The attack script came with a sample pcap, which showed the malicious FT reassociation request frames.

Malicious FT Reassociation Request
Curiously, the FT attack script sets the "More data buffered at AP" bit int he flags section. This isn't normal; the transmitting station is usually a client. If the attack script is not modified from its original form, a pattern to detect this frame would be 0:0:0x2020:0x20FF. The 0x00FF part of the mask will ensure that only reassociation requests are matched, and the 0x2000 part of the mask will match any frame with the "more data" flag set. Together, the 0x20FF mask will only match reassociation request frames with the "more data" flag set. The signature can be made very sensitive by setting the Freq or MacFreq values to 1, so a single frame will trigger the alert.

Another recent vulnerability is CVE-2017-11120, which can crash devices using certain chipsets by sending them 802.11k Neighbor Report Response messages with out-of-bounds operating class and channel values. The published exploit for this flaw sends a series of 11k Neighbor reports with operating class and channel values starting from 225 (0xE1) and ending at 240 (0xF0). These high values for channel number would never normally be seen in a Neighbor Report response frame. For the United States regulatory domain, you would likely never see anything over 165, but 0xE0 is the maximum allowed value. Let's take a look at a Neighbor Report Response frame.

802.11k Neighbor Report Response
I highlighted portions in the frame that correspond to sections an IDS signature will need to match. We will need at least three pattern definitions to match the three segments of the frame to uniquely identify it.

  • The frame control field of 0x00D0 (not shown above). 
  • The category and action code fields, 0x0505, in red above. 
  • The channel field in the neighbor report, in blue above. 
The pattern to match the frame control field can be cloned from the standard signatures. It will be 0:0:0x00D0:0x00FF. To match the category and action codes, a pattern of 1:0:0x0505:0xFFFF will work nicely. Since the action and category codes are seen immediately at the start of the frame body, I used a start of '1' and offset of 0. 

For the channel byte, I want to match anything greater than 0xE0. In binary, 0xE0 is 1110 0000, so anything greater than 0xE0 binary ANDed with 0xE0 will be 0xE0. A pattern of 1:16:E0x:0xE0 will match any channel value greater than or equal to 0xE0. How can I not match if the channel is equal to 0xE0? The pattern syntax allows a NOT operator, !. If I use a pattern of 1:!16:0xE0:0xFF, this will match as long as the channel value is NOT 0xE0. Combining all four patterns in a single signature will guarantee it only matches Neighbor Report responses that have channel values that are out of bounds. 

After you have defined your signatures, you will need to download them to your controller. I recommend just editing the standard signature file by deleting all of the pre-defined signatures, adding in your own signatures, and changing the line that has the keyword "Revision" to read "Revision = custom". If you don't put "custom" in, when you upload the signature file it will replace the standard signatures with your custom ones. After you download them, the new custom signatures will appear in the Custom Signatures section. Below is an example of my FT Reassociation attack signature after it was uploaded to the controller. 

Custom Signature Details
If you want traps to be sent for signature matches, make sure that it is enabled under Management -> SNMP -> Trap Controls. 

Trap Controls
Along with the technical details on custom signatures, here are some observations I have made while working on this blog: 
  • Signatures will match packets transmitted by other APs on the same controller. There is no logic to exclude frames transmitted from other authorized APs. 
  • Matching frames with variable length information elements, or IE that can appear in arbitrary order, is very difficult. 
  • If you are not using monitor mode APs, your detection is best done while the AP is on-channel. This could lead to you missing attacks happening on channels not served by your APs. You can make the filters more effective by setting the Freq or MacFreq parameters in custom signatures down to 1, so a single frame will trigger the alert. 
Finally, here is a link to a custom signature file containing the signatures that I discussed in this blog. If you wish, you can upload them to your lab controllers and try it out. 

1 comment:

  1. Dear GN,
    Thx for doing all the blogging. A very interesting article. I thought about the indeed strange order of the Pattern/Mask: maybe (again) some LSB/endian way to read incoming pkts? I remember the different ordering of the FC-bits as they are shown in OMNIPEEK compared to WIRESHARK? Just a guess: the whole FC-piece (16bit) is taken in, and then checked starting from the "end": lowest bit: Order/Protected/... per octet? Makes my brain hurting ...
    Michael Ruetz