diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2017-01-16 09:35:07 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2017-01-16 09:35:07 +0000 |
commit | 97ac971e60f365441722d613ac97db7e6f32ce9e (patch) | |
tree | 2e5d4257721115c1399066f29c0a7f85cac7d7f5 /sys/net80211/ieee80211_input.c | |
parent | 05eabe1ee5fa710c788b67fbd7ce511ddd55217b (diff) |
Prevent wireless frame injection attack described at 33C3 in the talk
titled "Predicting and Abusing WPA2/802.11 Group Keys" by Mathy Vanhoef.
https://media.ccc.de/v/33c3-8195-predicting_and_abusing_wpa2_802_11_group_keys
If an attacker knows the WPA group key the attacker could inject a unicast
frame by sending a group-encrypted frame to the AP with addresses set as:
addr1 (receiver): ff:ff:ff:ff:ff:ff
addr2 (source): MAC of attacker
addr3 (target): MAC of victim client
The AP would forward this frame as unicast, re-encrypted with the pair-wise
session key of the victim client. But an AP should not forward such frames.
Guessing a WPA group key used by an OpenBSD AP is hard because our random
numbers are actually random. So we are not vulnerable to this attack but
we are fixing the forwarding path anyway.
ok mpi@ tb@
Diffstat (limited to 'sys/net80211/ieee80211_input.c')
-rw-r--r-- | sys/net80211/ieee80211_input.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index 5ddd62d9e21..8fbd2c92fc5 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_input.c,v 1.183 2017/01/10 08:19:49 stsp Exp $ */ +/* $OpenBSD: ieee80211_input.c,v 1.184 2017/01/16 09:35:06 stsp Exp $ */ /*- * Copyright (c) 2001 Atsushi Onoe @@ -75,7 +75,7 @@ void ieee80211_decap(struct ieee80211com *, struct mbuf *, void ieee80211_amsdu_decap(struct ieee80211com *, struct mbuf *, struct ieee80211_node *, int); void ieee80211_deliver_data(struct ieee80211com *, struct mbuf *, - struct ieee80211_node *); + struct ieee80211_node *, int); int ieee80211_parse_edca_params_body(struct ieee80211com *, const u_int8_t *); int ieee80211_parse_edca_params(struct ieee80211com *, const u_int8_t *); @@ -892,7 +892,7 @@ ieee80211_ba_move_window(struct ieee80211com *ic, struct ieee80211_node *ni, void ieee80211_deliver_data(struct ieee80211com *ic, struct mbuf *m, - struct ieee80211_node *ni) + struct ieee80211_node *ni, int mcast) { struct ifnet *ifp = &ic->ic_if; struct ether_header *eh; @@ -912,6 +912,7 @@ ieee80211_deliver_data(struct ieee80211com *ic, struct mbuf *m, /* * Perform as a bridge within the AP. Notice that we do not * bridge EAPOL frames as suggested in C.1.1 of IEEE Std 802.1X. + * And we do not forward unicast frames received on a multicast address. */ m1 = NULL; #ifndef IEEE80211_STA_ONLY @@ -926,7 +927,7 @@ ieee80211_deliver_data(struct ieee80211com *ic, struct mbuf *m, ifp->if_oerrors++; else m1->m_flags |= M_MCAST; - } else { + } else if (!mcast) { ni1 = ieee80211_find_node(ic, eh->ether_dhost); if (ni1 != NULL && ni1->ni_state == IEEE80211_STA_ASSOC) { @@ -968,6 +969,7 @@ ieee80211_decap(struct ieee80211com *ic, struct mbuf *m, struct ether_header eh; struct ieee80211_frame *wh; struct llc *llc; + int mcast; if (m->m_len < hdrlen + LLC_SNAPFRAMELEN && (m = m_pullup(m, hdrlen + LLC_SNAPFRAMELEN)) == NULL) { @@ -975,6 +977,7 @@ ieee80211_decap(struct ieee80211com *ic, struct mbuf *m, return; } wh = mtod(m, struct ieee80211_frame *); + mcast = IEEE80211_IS_MULTICAST(wh->i_addr1); switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { case IEEE80211_FC1_DIR_NODS: IEEE80211_ADDR_COPY(eh.ether_dhost, wh->i_addr1); @@ -1017,7 +1020,7 @@ ieee80211_decap(struct ieee80211com *ic, struct mbuf *m, return; } } - ieee80211_deliver_data(ic, m, ni); + ieee80211_deliver_data(ic, m, ni, mcast); } /* @@ -1030,7 +1033,11 @@ ieee80211_amsdu_decap(struct ieee80211com *ic, struct mbuf *m, struct mbuf *n; struct ether_header *eh; struct llc *llc; - int len, pad; + int len, pad, mcast; + struct ieee80211_frame *wh; + + wh = mtod(m, struct ieee80211_frame *); + mcast = IEEE80211_IS_MULTICAST(wh->i_addr1); /* strip 802.11 header */ m_adj(m, hdrlen); @@ -1087,7 +1094,7 @@ ieee80211_amsdu_decap(struct ieee80211com *ic, struct mbuf *m, m_freem(m); break; } - ieee80211_deliver_data(ic, m, ni); + ieee80211_deliver_data(ic, m, ni, mcast); if (n->m_len == 0) { m_freem(n); |