作者: evilpan
博客: PansLabyrinth

本文為作者投稿,Seebug Paper 期待你的分享,凡經采用即有禮品相送! 投稿郵箱:paper@seebug.org

本文主要分享WiFi相關的一些安全研究,以及分析幾個實際的攻擊案例,如PMKID、KARMA、Krack、Kr00k等。

WiFi起源

WiFi是一種無線局域網協議(WLAN),經過多年的發展,WLAN基本上也等同于WiFi。史前時代的LAN可以追溯到1971年ALOHAnet提出的多址接入思想。

但我們不看那么遠,直接跳到1985年,當時FCC(US Federal Communications Commission, 美國聯邦通信委員會)首次開放2.4GHz等頻段,允許節點在這些頻段以擴頻技術通信,為后續無線局域網的發展立下基礎。

擴頻(Spread Spectrum)通信的方法有很多,常見的是藍牙用的跳頻(Frequency Hopping)和WiFi用的直序擴頻(Direct Sequence)

隨后在1989年,第一個無線局域網產品WaveLAN出現;次年,IEEE 802.11委員會被正式成立,開始構建一個無線局域網的專用協議。期間WaveLAN經過了許多部署嘗試,在產業界沉淀了實踐基礎。

WiFi,正確寫法應該是Wi-Fi(Wireless-Fidelity),即無線-高保真。無線都能理解,高保真則是要求在無線網絡中可靠地傳輸數據。WiFi最初是一個獨立的完整協議,其主要內容在后來被IEEE 802.11委員會接受并成了802.11a的標準。

1999年,Wi-Fi聯盟成立,這多個廠商發起的非盈利聯盟,致力于解決工業界的兼容性和統一問題,填補學術界和工業界之間的實現差異。

還是1999年,IEEE頒布了802.11b協議,這是WiFi協議的里程碑,早期筆記本電腦和PS游戲機中的無線功能都是基于802.11b的。同年,蘋果也推出了基于WiFi原理的Airport技術。

一年后的2000年,802.11a才正式通過。但是因為當時5GHz開放的信道有限,802.11a并沒有推廣開來。

2003年,頒布802.11g協議標準,修改802.11a的不足,在2.4GHz頻段上使用OFDM技術。

2004年,802.11i頒布,關鍵詞是WiFi安全性。

2009年,802.11n,關鍵詞是MIMO(多輸入多輸出)。

2014年,802.11ac,關鍵詞是下行MU-MIMO。

...

2019年,802.11ax,WiFi6,關鍵詞是雙向MU-MIMO。

當然,這只是其中幾個關鍵的標準。我們可以在802.11_Timelines中看到所有802.11頒布的協議和時間線。按照演進的方向,也可以概要為下圖:

WPA/WPA2/WPA3

WiFi雖然廣為人知,但是其物理層和鏈路層的實現也是相當復雜,念完研究生的無線網絡課程也不敢說自己精通WiFi。因此,我們主要聚焦在協議安全性以及實現的安全性上。

WPA(Wi-Fi Protected Access),即無線保護訪問,是WiFi聯盟為應對WEP(Wired Equivalent Privacy)中存在的各種安全問題而推出的解決方案。其中WPA最初只是作為草稿發布,并為后續更完善的WPA2鋪路,二者都定義在802.11i(IEEE 802.11i-2004)的標準中。

我們目前廣泛使用的WiFi安全保護訪問就是WPA2的標準。在2018年1月,WiFi聯盟又推出WPA3,在WPA2的基礎上做了一些安全增強

WPA是標準,而我們常見的WPA-PSK TKIP/AES-CCMP則是具體的加密模式和加密方法。

拓展閱讀: what-is-the-difference-between-tkip-and-ccmp

4-Way Handshake

說到WiFi安全,就不能不說校驗過程中涉及到的四路握手。四路握手的目的是為了安全地驗證和交換秘鑰,驗證對端合法性,防止中間人攻擊。

四路握手中涉及到的一些名詞如下:

  • authenticator:即AP(Access Point),可以理解成路由器
  • supplicant:即想要接入AP的Client,簡寫為STA(Station)
  • MSK (Master Session Key)
  • PMK (Pairwise Master Key)
  • GMK (Group Master Key)
  • PTK (Pairwise Transit Key)
  • GTK (Group Temporal Key)
  • ANonce:Authenticator Nonce
  • SNonce:Supplicant Nonce
  • MIC:Message Integrity Check

是否有很多問號?不要緊,待會回頭再看就很清晰了。先放一張四路握手的大圖,記得時不時拉回來看看:)

接下來就圍繞著上圖的握手流程進行分析。

802.11幀

既然我們不關注物理層,那么就可以從接受并解碼后的數字信號說起。首先打開我們的WireShark抓一會兒包(monitor mode),挑選其中任意一個無線數據包查看,可以看到最頂層的包頭是IEEE 802.11 XXX frame,所以我們就從這個包說起。

實際上面還有一層radiotap,是抓包工具加的,提供額外信息,比如時間,信道等,這些內容不是標準中的一部分,詳情可見:http://wifinigel.blogspot.com/2013/11/what-are-radiotap-headers.html

一個802.11幀就是這么樸實無華,且枯燥。但是后面的介紹會用到里面的一些字段,所以就先放出來。注意前兩字節是幀控制(Frame Control)頭,每個bit有不同的意思,具體可以看虛線下的展開。

接下來我們通過實際抓包來看WiFi連接認證的完整過程。測試使用我們自己搭建的WiFi,AP的SSID為evilpan,BSSID為66x6,WPA2密碼為12345678,所連接的客戶端為蘋果手機。

Auth & Associate

一般情況下,AP會一直向周圍廣播宣告自己的存在,這樣STA才知道周圍有哪些熱點,并選其中的一個進行連接。廣播的數據稱為Beacon Frame其中包括了熱點的BSSID(即MAC地址)和ESSID(即熱點名)。

Beacon Frame并不是必須的,路由器可以配置不廣播,STA依然可以通過指定SSID和密碼進行連接,即所謂的隱藏熱點。

在WiFi握手前還可以看到兩大類型的幀,Authentication和Association,分別是認證和連接。注意這里的認證和安全性無關,只是認證雙方是和符合標準的802.11設備。而連接后則在鏈路層接入網絡,如果是Open WiFi,此時已經接入LAN,如果需要WPA認證,即我們所討論的情況,則正式開始四路握手。

回顧上面的四路握手大圖。注意在握手開始之前,雙方手上都有一個PMK,即配對主秘鑰。這個秘鑰是從哪來的呢?在IEEE 802.11i-2004標準中有定義,如果使用PSK(Pre-Shared Key)認證,那么PMK實際上就是PSK。而PSK則是通過WiFi密碼計算出來的:

PMK = PSK = key_derivation_func(wifi_passwd)

key_derivation_func是一個秘鑰推導函數(PBKDF1/2),內部以SHA-1為哈希函數。

還注意到,AP端不止有PMK,還有一個GMK。這是AP自己生成的,GMK用來為每個連接的STA生成GTK,并分享給STA。為了避免GMK被STA猜解,有的AP可以設置定時更換GMK,如思科的設備中broadcast key rotation選項。

拓展閱讀:Real 802.11 Security: Wi-Fi Protected Access and 802.11i

WPA中四路握手的協議也稱為EAPOL(Extensible authentication protocol over LAN),可以直接在wireshark等工具中使用eapol過濾出來。

握手1/4

握手第一階段,AP向客戶端發送隨機數ANonce

此時,客戶端中有PMK、ANonce、SNonce(客戶端自行生成的隨機數),以及雙方的MAC地址信息。通過這些信息,計算PTK:

PTK = func(PMK + Anonce + SNonce + Mac (AA)+ Mac (SA))

func是個偽函數,表示經過某種運算。函數的實現細節不展開,下面都使用func作為偽函數名。

PTK是Pairwise Transit Key,根據參與運算的參數可見,該秘鑰在每個客戶端每次握手中都是不同的。PTK也可以理解為一個臨時秘鑰,用來加密客戶端和AP之間的流量。

握手2/4

客戶端生成PTK后,帶著自己生成的SNonce發送給AP,目的是為了讓AP使用同樣的方法計算出PTK,從而確保雙方在后續加密中使用正確的秘鑰。

在這次發送的數據中,還包含MIC(Message Integrity Check)字段,AP用以校驗該條信息的完整性,確保沒有被篡改。

握手3/4

客戶端收到第二階段發送的SNonce之后,就可以算出PTK,并用PTK加密GTK后,發送給客戶端,同樣帶有MIC校驗。

發送的GTK是最初從GMK生成而來的,主要用來加密組播和廣播數據(實現上切分為GEK/GIK,在CCMP和TKIP作為不同字段使用)。

握手4/4

此時雙方都有了后續加密通信所需要的PTK和GTK,第四次握手僅僅是STA告訴AP秘鑰已經收到,并無額外數據:

小結

根據秘鑰的唯一性,可以分為兩種:

  • Parwise Key:一機一密,每個客戶端保存一個,AP端保存多個,用來加密單播數據
  • Group Key:一組一密,所有客戶端和AP都保存一個,用來加密組播或廣播數據

根據秘鑰的類型,也可以分為兩類:

  • Master Key:主秘鑰,預先安裝或者很久才更新一次
  • Temporal Key:臨時秘鑰,每次通過主秘鑰去生成

這樣,理解前面的各種Key也就更加直觀了。注意由于Group Key是所有客戶端共享的,所以當某個客戶端離開AP之后,AP會重新生成Group Key,并通知其他終端進行更新;此外,前面也說了,某些AP也可以配置定期更新Group Key。

握手也可以簡化描述為以下四步:

  1. AP發送ANonce給STA
  2. STA使用ANonce計算獲得單播秘鑰,發送SNonce給AP
  3. AP使用SNonce計算獲得單播秘鑰,并將加密的組播秘鑰發送給STA
  4. 完成握手,雙方都有PTK和GTK,加密后續對應報文

攻擊案例

對四路握手有個基本了解之后,再來看看一些經常聽說的WiFi安全問題是如何造成的。對于一些年代久遠的案例,比如WEP、WPS攻擊就不再介紹,因為它們已經退出歷史舞臺了。

暴力破解

既然WiFi密碼是PSK,使用預置共享的秘鑰,那么就不可避免面臨暴力破解的問題。當然這里說的暴力破解不是輸密碼連WiFi,提示密碼錯誤了再不斷嘗試,那樣效率太低了。

實際中的暴力破解要高效得多。暴力破解的本質是獲取PSK即PMK的明文,根據上面介紹握手的流程,作為一個未驗證終端,我們實際能獲取到的是ANonce、SNonce、Mac地址以及加密的內容和MIC,通過不斷變換PSK/PMK計算PTK并驗證MIC從而尋找真實密碼。

比如我曾經最喜歡玩的aircrack-ng,其內部實現就是:

EXPORT int ac_crypto_engine_wpa_crack(
    ac_crypto_engine_t * engine,
    const wpapsk_password key[MAX_KEYS_PER_CRYPT_SUPPORTED],
    const uint8_t eapol[256],
    const uint32_t eapol_size,
    uint8_t mic[MAX_KEYS_PER_CRYPT_SUPPORTED][20],
    const uint8_t keyver,
    const uint8_t cmpmic[20],
    const int nparallel,
    const int threadid)
{
    ac_crypto_engine_calc_pmk(engine, key, nparallel, threadid);

    for (int j = 0; j < nparallel; ++j)
    {
        /* compute the pairwise transient key and the frame MIC */

        ac_crypto_engine_calc_ptk(engine, keyver, j, threadid);

        ac_crypto_engine_calc_mic(
            engine, eapol, eapol_size, mic, keyver, j, threadid);

        /* did we successfully crack it? */
        if (memcmp(mic[j], cmpmic, 16) == 0) //-V512
        {
            return j;
        }
    }

    return -1;
}

在CPU/GPU足夠給力的情況下,上百GB的字典可以在十幾分鐘跑完。當然跑字典也有一些循序漸進的策略,比如:

  1. 當地的手機號
  2. 所有8-10位數字組合
  3. Top xxx 密碼字典
  4. 上述字典+變異
  5. 字典組合+變異
  6. ……

當然說這個不是教大家去暴力破解,而是根據上述策略去選取一個強度合適的WPA密碼,保護自己的隱私安全。

RSN PMKID

上面最常見的暴力破解需要獲取4路握手包,也就是說有個前提是需要有客戶端去連接。通過一些手段,比如偽造Deauth可以讓目標強制掉線重連從而獲取握手包,但不管怎樣都需要有客戶端在線才行。

PMKID攻擊是hashcat的作者在2018年提出的,他發現在一些AP的第一次握手數據包中,包含了額外的EAPOL字段RSN(Robust Security Network),其中包含PMKID:

這個PMKID的計算方法是:

PMKID = HMAC-SHA1-128(PMK, "PMK Name" | MAC_AP | MAC_STA)

因此,如果返回包含RSN PMKID,那么就可以在無需客戶端在線的情況下發起本地的暴力破解。事實上,非常多路由器在第一次握手的EAPOL包中都會包含這個字段。

KARMA & MANA

還記得前面介紹的Beacon Frame嗎?有的AP會定期像周圍廣播自己的存在,從而讓客戶端知道周圍有哪些熱點。但這只是其中一個方法,稱為被動掃描;客戶端還可以主動發送Probe Request探測周圍的WiFi,如果有WiFi響應則返回Probe Response,返回對應的AP屬性,從而讓客戶端發起連接,這稱為主動掃描,主動探測又分為直接探測(Direct Probe)和廣播探測(Broadcast Probe)。

KARMA攻擊的本質就是,監聽客戶端發送的Directed Probe Request,然后偽造對應的熱點信息,讓客戶端認為這是個之前連接過的熱點,從而進行接入。

802.11協議中規定AP只能響應發給自己的Probe Request,但KARMA并不準守這個規定,如果STA準守802.11,那么就會認為這是個合法的響應從而進行連接。

最初版本的KARMA攻擊在2004年提出(KARMA Attacks Radioed Machines Automatically ),但是在2014年時很多場景已經不再可用了,因此出現了更新的版本MANA。在更新的版本中,除了響應直接探測,還響應廣播探測。

這一類偽AP的根本問題是802.11協議中沒有清楚地定義客戶端如何選擇ESS以及如何在不同的ESS之間漫游,所以實現上就存在各種偏差。

一個使用MANA偽造AP和響應探測請求的例子如下:

下面的窗口是通過aireplay發送deauth包令客戶端掉線,從而連接上我們的惡意熱點。

Krack

Krack攻擊可能大家都在新聞上看到過,前兩年搞得沸沸揚揚,還做了官方網站和Logo,……Anyway,Krack就是Key Reinstallation Attacks,即秘鑰重裝攻擊。

在我們前面介紹WiFi握手的時候見過了雙方更新秘鑰的過程,秘鑰的更新也稱為安裝(Key Installation)。Krack攻擊的原理就是通過重放握手信息,令客戶端重新安裝相同的秘鑰。

當重裝秘鑰的時候,相關聯的參數比如遞增的發送包個數(即nonce)以及接收包數(即replay counter)會恢復到初始值。WPA協議中沒有明確規定這種情況下如何處理,因此很多實現就是正常安裝,即重置這兩個值。

重置之后就可以歸類到nonce重用的密碼學問題,感興趣的可以參考krack-paper中的2.4節如何通過重置nonce和counter實現解密。

總之,重置秘鑰之后就可以讓攻擊者解密本該加密的WPA數據,從而讀取受害者的網絡流量。這個漏洞還根據重置的是PTK、GTK以及其他內容申請了多個CVE,大部分是影響STA的握手應用,在Linux中是wpa_supplicant,但對于GTK其實也影響了內核,這個是對應內核upstream的patch信息:

commit fdf7cb4185b60c68e1a75e61691c4afdc15dea0e
Author: Johannes Berg <johannes.berg@intel.com>
Date:   Tue Sep 5 14:54:54 2017 +0200

    mac80211: accept key reinstall without changing anything

    When a key is reinstalled we can reset the replay counters
    etc. which can lead to nonce reuse and/or replay detection
    being impossible, breaking security properties, as described
    in the "KRACK attacks".

    In particular, CVE-2017-13080 applies to GTK rekeying that
    happened in firmware while the host is in D3, with the second
    part of the attack being done after the host wakes up. In
    this case, the wpa_supplicant mitigation isn't sufficient
    since wpa_supplicant doesn't know the GTK material.

    In case this happens, simply silently accept the new key
    coming from userspace but don't take any action on it since
    it's the same key; this keeps the PN replay counters intact.

    Signed-off-by: Johannes Berg <johannes.berg@intel.com>

要說危害性,我感覺危害還是挺大的,好在目前的STA應用和內核大多已經修復了該問題。如果說存在密碼學后門,這就是一個典型:利用理論和實現中的未定義行為造成偏差。

深入了解可參考下面的資料:

Kr00k

這是2020年2月份RSA大會上披露的一個漏洞(KR00K - CVE-2019-15126 SERIOUS VULNERABILITY DEEP INSIDE YOUR WI-FI ENCRYPTION ),新鮮出爐。這是個芯片驅動實現的問題,主要影響Broadcom和Cypress網卡。

其核心漏洞點是在解除客戶端關聯后,其PTK會被置零,但是WiFi芯片會繼續用置零的PTK發送緩沖中剩余的無線數據,攻擊者收到這些數據后使用全零的PTK即可解密。

實際攻擊中,攻擊者需要不斷令客戶端關聯/解除關聯,即可不斷地獲得客戶端發送的數據進行解密;同時由于部分路由器也受影響,因此可以獲得下行的數據。

我個人的解讀是這個漏洞可以泄露一些關鍵信息,但是不像Krack那樣可以做到穩定的泄露,因此利用場景相對受限。比起后門般的Krack,Kr00t更像是一個漏洞。

漏洞詳情以及PoC可以參考以下文章:

后記

本來這篇文章是想寫如何偷WiFi密碼的,但是寫著寫著就裂開展開了,因此順便把之前放在Todo-List中的那些漏洞也一并拿出來進行研究分析。當然WiFi的安全問題不止這些,但是影響最大的還是協議設計中留下的坑。比如漫游的定義不清楚導致了KARMA,秘鑰重裝的不明確導致了Krack。這些坑還有多少誰也說不準,協議的更新到工業界的產品推出也需要時間,但我相信未來的無線安全性會越來越好——在眾多學者、開發者以及安全研究人員的共同努力下。

參考資料


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.jmbmsq.com/1159/