Wi-Fi新标准-WPA3蜻蜓(Dragonfly)密钥交换协议分析

阅读量    84386 | 评论 1

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

作者:阿里安全猎户座实验室高级安全工程师 青惟

背景

在2018年1月8日美国拉斯维加斯的国际消费电子展(CES)上,Wi-Fi联盟发布了最新的WPA3加密协议,作为WPA2技术的的后续版本,并在2018年6月26日,WiFi联盟宣布WPA3协议已最终完成。与WPA3相关的最核心的文档为RFC7664,其中描述的是WPA3中最大的改进,就是将原来的四次握手协议换成了新的“蜻蜓秘钥交换协议”(Dragonfly Key Exchange),该协议将认证和秘钥交换两个功能合成于一个协议。号称可以解决WPA2中未解决的几个安全问题:

  1. 离线密码破解。——获得WPA2的四次握手包即可进行离线字典攻击,破解无线密码。
  2. 转发安全(Forward Secracy)——已知4次握手和无线密码的情况下,可以解密目标的所有通信流量。
  3. KRACK等其他已知攻击方法。

由于WPA3还尚未普及,想来目前无论公众还是相关研究人员对WPA3的协议的实施细节所知应该并不多,所以笔者在仔细阅读RFC7664文档后,在此文中将做详细的分析讨论,以及指出可能的攻击方法,供其他相关研究人员参考。

 

WPA3简介

本节中我们简单介绍一下WPA3相关的基本知识,在WPA2的基础上讨论在WPA3协议中做了哪些关键改进以及改进后在安全方面会有哪些提升。

根据Wi-Fi联盟官方发布的文档,WPA3仍然分为WPA3个人级和WPA3企业级两种标准,其中,WPA3企业级认证与WPA2相比差别不大,仅仅将密钥长度增加到了192位(WPA2使用的是128位的加密密钥)仍然采用EAP-SSL,EAP-SIM/EAP-AKA之类的基于认证服务器的认证方法。

那么此次协议改进最大的地方在哪里呢?没错,改动最大的地方就是WPA3个人级相对于WPA2个人级的改进,根据官方的说法,WPA3个人级有如下几个提升:

  1. 更强的基于密码的认证安全(官方声称即使用户使用弱密码,仍然可以得到良好的保护。)
  2. 使用等量同步认证——一种更安全的设备间密钥交换协议,即蜻蜓协议,可以防止通通信流量被窃听,即使被攻击者获取了握手过程,也无法解密流量。
  3. 密钥长度扩展到192位。

其中官方宣称的第1点建立的基础就是因为引入了蜻蜓秘钥交换协议,该协议作者在该协议的说明中声称可以避免离线字典攻击,这一点应该就是以上第1所述的可保护弱密码的原理。至于3,其实128位的对称密钥已经足够,此处提升仅仅有理论上的安全提升。看来WPA3上最明显的改进就是替换了密钥交换算法,在接下来的章节中我们就着重分析一下这个蜻蜓算法。

 

WPA2-PSK回顾

在开始分析蜻蜓算法之前,为了更有效的对比WPA2和WPA3密钥交换算法的差异,这里先简单介绍一下WPA2协议中设备入网认证的过程,见下图。

http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/dfd655f5699e2900a259e6776cd1b427.png

事实上一次完整的WPA2入网过程中,在上图所述的密钥交换过程之前还需要3次交互,分别是客户端发送Probe Request,服务器回应Probe Response,客户端发送Authentication Request服务器回应Authentication Response,接着客户端发送Association Request,服务器回应Association Response,接着开始上图所示密钥交换过程。密钥交换过程分为如下几步:

  1. AP发送一个随机数AP Nonce给STA,STA通过AP的ESSID,以及自己的MAC地址,AP的MAC地址,PSK,AP发送的随机数以及自己生成的STA Nonce,这6个参数生成PMK和PTK。
  2. STA发送第1步生成的随机数STA Nonce给AP,并使用上一步生成的PTK生成该数据包的消息校验值MIC附在数据包后面发送给AP,AP通过包括STA Nonce在内的同样6个参数生成自己的PMK和PTK,并用PTK校验STA发送的数据包的MIC值是否匹配,如果匹配则说明PSK正确认证通过。
  3. AP将组密钥(即GTK用于加密广播以及组播包的密钥)用PMK加密并附上MIC发送给STA。
  4. STA校验MIC后装入GTK并回复ACK,密钥交换结束开始加密通信。

如果你觉得以上写的太纠结,为了照顾大家特此附上代码:

#!/usr/bin/env python

import hmac

from hashlib import pbkdf2_hmac,sha1,md5

def PRF(key,A,B):

         nByte = 48

         i = 0

         R = ''

         while ( i <= ((nByte*8 + 159)/160)):

                 hmacsha1 = hmac.new(key,A+"\x00" + B + chr(i),sha1)

                 R += hmacsha1.digest()

                 i += 1

         return R[0:nByte]

def MakeAB(aNonce,sNonce,apMac,cliMac):

         A = "Pairwise key expansion"

         B = min(apMac,cliMac) + max(apMac,cliMac) + min(aNonce, sNonce) + max(aNonce, sNonce)

         return (A,B)

def MakeMIC(pwd,ssid,A,B,data,wpa = False):

         pmk = pbkdf2_hmac('sha1',pwd,ssid,4096,32)

         ptk = PRF(pmk,A,B)

         hmacFunc = md5 if wpa else sha1

         mics = [hmac.new(ptk[0:16],i,hmacFunc).digest() for i in data]

         return (mics,ptk,pmk)

def calcKey(essid,psk,apMac,cliMac,data0,data1,data2,data3):

    ssid = essid

    #print ssid

    aNonce = data0[17:17+32]

    #print aNonce.encode('hex')

    sNonce = data1[17:17+32]

    #print sNonce.encode('hex')

    apMac = apMac.replace(':','').decode("hex")

    cliMac = cliMac.replace(':','').decode("hex")

    mic1 = data1[81:81+16]

    data1 = data1.replace(mic1,'\x00'*16)

    mic2 = data2[81:81+16]

    data2 = data2.replace(mic2,'\x00'*16)

    mic3 = data3[81:81+16]

    data3 = data3.replace(mic3,'\x00'*16)

    A,B = MakeAB(aNonce,sNonce,apMac,cliMac)

    mics,ptk,pmk = MakeMIC(psk,ssid,A,B,[data1,data2,data3])

    print "pmk:",pmk.encode('hex')

    print "ptk:",ptk.encode('hex'),"len:",len(ptk)*8

    print "desired mic1:",mic1.encode('hex')

    print "acture mic1:",mics[0].encode('hex')[:-8]

    if (mic1==mics[0][:-4]):

        print "MIC1 MATCHED"

    print "desired mic2:",mic2.encode('hex')

    print "acture mic2:",mics[1].encode('hex')[:-8]

    if (mic2==mics[1][:-4]):

        print "MIC2 MATCHED"

    print "desired mic3:",mic3.encode('hex')

    print "acture mic3:",mics[2].encode('hex')[:-8]

    if (mic3==mics[2][:-4]):

        print "MIC3 MATCHED"

    return ptk

从上面的过程可以看出,其中最重要的参数就是PTK,每个STA和AP之间通信的PTK是不同的,这也意味着一旦PTK被获知,就可以解密该STA和AP之间通信的所有流量。那么纵观整个交换过程,最重要的参数就是PSK,PSK参与了密钥的计算,且AP和STA对于PTK密钥的计算算法是对称的,这或许就是WPA2不提供转发安全的最重要原因,那就是,只要握手过程被获取,任何知道PSK的人都可以计算出PTK,从而解密所有通信流量。并且,由于算法是对称的,只要抓取握手包,就可以通过离线校验MIC的方式来验证PSK的正确性,这就是aircrack-ng抓取握手包跑包破解WIFI密码的原理。

好了,至此我们可以看出,对称的密钥生成算法或许是WPA2安全性的最大缺陷!因为这一点,导致WPA2可以被离线字典攻击,同时,在PSK公开的网络中,例如星巴克,酒店之类的场景,PSK被很多人都知道,且一旦密钥被攻击者获取,就无法保证用户的数据安全!

 

WPA3 Dragonfly(蜻蜓)密钥交换算法

 

(因数学公式原因以图片形式展现)

更直观的过程大家看下图:

http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/bcc8e7fdbc62c909df9ef1d6f46d2aa8.PNG

上面就是WPA3中蜻蜓密钥交换算法的主要内容了,由于WPA3尚未大规模商用,因此有很多实现细节还尚不清楚,要真正的实际使用还有很多工程方面的工作需要考虑,这些不是本文所关心的。因此后面我们仅做一个理论性的讨论,上面的过程是对RFC7664里面所述协议的简化模型,源文档写的非常冗长,但核心就在上面的过程里,如果对协议细节有兴趣可以参考原文档。

 

蜻蜓算法安全性分析

从上面的密钥交换过程可见,这个算法确实如之前介绍所说,将认证和密钥交换两个功能合二为一,首先进行PSK认证,认证通过了密钥才会生成,而对于WPA2,前两次握手已经计算出密钥了,后第3第4次握手是在对密钥是否一致进行校验,由此可见WPA3的新协议确实对于提高安全性有一定帮助。

关于转发安全的分析

(因数学公式原因以图片形式展现)

关于中间人攻击

从以上密钥交换算法的细节可以看出,对于同样知道PSK的攻击者来说,这种算法也存在D-H密钥交换算法的毛病,就是无法防止中间人攻击!不过考虑到无线信道想要完成中间人劫持并不容易,所以这样考虑也尚且合情合理,不过话说回来,WiFi网络里中间人攻击并不是完全不可能的,只是实施有一定条件而已,因此在这一点上,我认为仍然重蹈了WPA2中“只能保证PSK不泄露情况下安全”的覆辙。

关于离线字典攻击

(因数学公式原因以图片形式展现)

 

结论

本文详细分析了WPA3中的蜻蜓密钥交换算法,虽然对于工程化的实施细节尚不明确,本文从理论角度对于其安全性得出的结论总结如下:

  1. WPA3使用蜻蜓算法,可以防止被动的攻击者窃取数据,即可以提供转发安全。
  2. 因为WPA3个人级并不建立在公钥信任的基础上,因此对于同样知道PSK的攻击者来说,无法防止中间人攻击。
  3. 无法完全防止离线字典攻击,一定条件下字典攻击是可以实施的,不过相比WPA2,提高了攻击成本,但如果期待WPA3协议能很好的保护12345678这种弱密码,那还是想多了。
  4. 至于对KRACK之类的密钥重装攻击的防御,由于对握手过程的丢包处理机制细节还不明确,因此不确定能否防止此类攻击,但从中间人攻击的角度,此类攻击在WPA3中仍然存在可能性。

本人水平有限,若有疏漏,欢迎指正。

 

我们

阿里安全八大实验室之一的阿里安全猎户座实验室,聚焦通用漏洞,程序分析,IoT安全的研究,掌握业界领先的通用漏洞挖掘方法论,发现众多开源软件、操作系统及物联网设备的严重漏洞。

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多