Part1でも説明したように、以前は無線LANのセキュリティプロトコルとしてWEPが使われていた。しかし、2001年頃からWEPが脆弱だと指摘されるようになり、次々に致命的な脆弱性が見つかった。このため、より安全性が高いWPA▼やWPA2が使われるようになったという経緯がある。
WPAとWPA2の違いは、使う暗号化方式である。WPAではTKIP▼が標準でCCMP▼がオプションなのに対し、WPA2ではTKIPがオプションでCCMPが標準になっている。CCMPのほうが安全性が高いため、現在はWPA2が主流であり、WPAはあまり使われていない。
WEPを使うのが危険な理由はいくつかある。まず、WEPで暗号化したパケットを解析すると、暗号化のための共通鍵が簡単にわかってしまうことだ。そうした解析のためのツールもインターネットで公開されており、誰でも利用できる。
さらに、WEPはすべての端末の通信を同じ鍵を使って暗号化しているという問題もある(図3-1)。このため、いったん鍵がわかってしまうと、アクセスポイント(AP)とやり取りしているすべての端末の暗号データを解読できてしまう。
これに対し、WPA2ではWEPよりも鍵の解析が難しくなっている。それに加え、端末ごとに異なる鍵で暗号化している。WPA2で使うこうした「端末ごとに異なる鍵」を「PTK▼」と呼ぶ。
たとえある端末のPTKを解読できても、他の端末では異なるPTKが使われている。このため他の端末の暗号通信は解読できない。一カ所のセキュリティが破られても影響が及ぶ範囲が少なくなるように設計されているのだ。
安全なはずのWPA2に脆弱性
このようにWPA2は安全性が高いと思われていた。だから、そうしたWPA2にKRACKsという脆弱性が発見されたという事実は衝撃的だった。
ただし、KRACKsはWEPの脆弱性に比べれば危険度は低い。WEPのようにすぐに共通鍵がわかってしまうわけではなく、攻撃者に「共通鍵を解析するヒント」を与えるだけだからだ。また、前述したように、ある端末の共通鍵であるPTKが漏れても、他の端末の暗号通信は解読できない。
では、KRACKsとは何かを具体的に見ていこう。通常のWPA2の通信ではPTKによる暗号化▼の際に、パケットごとに異なる「ナンス」と呼ばれるランダムな数値を使用する(図3-2)。これにより、暗号を解読しにくくなるよう工夫している▼。
ところがKRACKsを悪用すると、異なるパケットで同じナンスを使わせることができる。攻撃者がこうしたパケットを大量に集めると、暗号化のパターンがわかり、PTKを解析しやすくなる。
KRACKsは、実際には10個の脆弱性の総称である(表3-1)。それぞれが「鍵再インストール攻撃」(KRACK:Key Reinstallation Attack)であるため、その複数形であるKRACKsと呼ばれているのだ。いずれの脆弱性でも、特定の条件下で鍵が再インストールされ、その結果ナンスがリセットされる。これにより、攻撃者は鍵を解析するためのヒントを得られる。
図3-2に示したのは、実際には表3-1のCVE-2017-13077「4ウェイハンドシェイクにおけるPTKの再インストール」の例だ。WPA2の実装によって、KRACKsのどの脆弱性が該当するのかは異なる。例えば、WindowsやiOSのWPA2の実装にはPTKの再インストールの脆弱性はない。代わりにGTK▼の再インストールの脆弱性がある。
このような脆弱性が生じたのは、WPA2の仕様では鍵をいつインストールするかが明示されていないためだ。これにより「鍵が1回しかインストールされていない」ことが保証されず、攻撃に悪用された。
端末とAPで鍵を共有する
Part2で述べたように、WPA2ではハンドシェイクの手順に問題があり、これを悪用する攻撃がKRACKsである。ここからはWPA2のハンドシェイクを具体的に見ていく。
その前提知識として、WPA2の二つの方式を説明しておこう(図3-3)。WPA2はユーザー認証を行うかどうかで「WPA2パーソナル」と「WPA2エンタープライズ」に分かれる。
WPA2パーソナルでは、端末とAPに同じパスフレーズを設定する。そのパスフレーズからマスター鍵であるPMK▼が生成される。このようにあらかじめ同じ鍵を設定しておく認証方法をPSK▼認証と呼ぶ。
これに対し、WPA2エンタープライズでは有線/無線LANの認証規格であるIEEE 802.1Xに基づいてユーザー認証を実施する。パスフレーズさえ知っていれば誰でも無線LANに接続できてしまうWPA2パーソナルとは異なり、あらかじめ認証サーバーに登録したユーザーしか接続できない。
IEEE 802.1Xの認証手順には鍵の配送も含まれている。そこで、認証サーバーが作成したPMKが端末に配送される。認証サーバーはAPに対してはRADIUS▼プロトコルでPMKを配送する。これらにより、APと端末に共通のPMKを持たせる。
マスター鍵であるPMKからは一時鍵に相当するPTKが生成される。4ウェイハンドシェイクによって端末とAPの間でPTKを共有する(図3-4)。
4ウェイハンドシェイクは、端末とAPがPMKを既に共有しているのが前提になっている。前述したように、PMKはWPA2パーソナルでは事前設定、WPA2エンタープライズではIEEE 802.1Xで共有されている。
4ウェイハンドシェイクの最初の「メッセージ1」では、APが生成した「Aナンス」というランダムな数値を端末に送る。端末側では「Sナンス」というランダムな数値を生成し、PMK、Aナンス、Sナンス、APのMACアドレス、端末のMACアドレスからPTKを生成する。なお、AナンスやSナンスは、PTKによる暗号化の際に使うナンスとは異なるものだ。
「メッセージ2」では端末がSナンスをAPに送る。AP側でもPMK、Aナンス、Sナンス、APのMACアドレス、端末のMACアドレスからPTKを生成する。
次にAPはマルチキャスト/ブロードキャスト通信の暗号化に使うGTKを生成。これを「メッセージ3」で端末に送る。
端末側では、4ウェイハンドシェイクの完了を知らせるACK▼を含む「メッセージ4」をAPに送信する。この時点で端末はPTKとGTKをインストールする。APはメッセージ4を受け取った時点でPTKをインストールする。これにより端末とAPの間でPTKを共有できるようになる。
エリア内に攻撃用APを設置
KRACKsでは、攻撃者がハンドシェイクに割り込む形で攻撃を行う。そのため、無線LANのエリア内に攻撃用のAPを設置する必要がある(図3-5)。そのAPのMACアドレスとして正規のAPと同じものを設定しなればならない。攻撃者は、正規のAPのMACアドレスを何らかの方法で調べておく必要がある。
しかも、それだけではKRACKsによる攻撃は成功しない。端末と正規APの間は必ず攻撃用APを介して通信するようにする必要がある。KRACKsでは、端末からAPへのメッセージをブロックしたり、あらかじめ保存しておいたAPから端末へのメッセージを、一定時間後に端末に送ったりする必要があるためだ。実際には、攻撃を成功させるためのハードルはかなり高い。
では、KRACKsを悪用する攻撃の例を見ていこう(図3-6)。
攻撃の起点は、端末が4ウェイハンドシェイクの完了をAPに伝えるためのメッセージ4だ。攻撃者のAPは、まずこのメッセージをブロックする。ところが、メッセージ4をブロックしたことは端末にはわからないので、4ウェイハンドシェイクが完了したと解釈する。そこで端末は、パケットごとに異なるナンスを使いながら、攻撃用APに向けて暗号通信を始めてしまう。
一方、正規のAP側はメッセージ4が届かないため、端末にメッセージ3が届いていないと判断し、再びメッセージ3を端末に向けて送信する。つまり、正規のAPでは4ウェイハンドシェイクはまだ完了していないことになる。
攻撃者のAPは、この2回目のメッセージ3をいったんブロックして取っておく。そして、任意のタイミングでこのメッセージを端末に送る。
すると、端末は4ウェイハンドシェイクをメッセージ3からやり直すことになり、再びACKのメッセージ4をAPに返す。次にPTKを再インストールする。
このとき、端末は前と同じ条件で通信しようとしてナンスをリセットしてしまう。このため、同じナンスを使って暗号化したパケットを再び送る。これにより、攻撃者は、同じナンスを使って暗号化した2種類のパケットを入手できることになる。
攻撃者が再びメッセージ4をブロックすれば、同じ手順で攻撃を何度も繰り返せる。つまり、同じナンスを使って暗号化した大量のパケットを集められる。こうしたパケットのパターンを解析することで、攻撃者はPTKの手掛かりを得る。
鍵の再インストールを禁止
このようにKRACKsによる攻撃のハードルは高く、攻撃者が得られる情報も限られている。そのため、それほど危険性は高くないようにも思える。
ところが、WPA2の実装によってはKRACKsが深刻な脆弱性になる例がある。端末のOSが「Android 6.0」の場合である(図3-7)。
Android 6.0ではPTKの再インストールの際に、暗号化に使う鍵▼として「すべてのビットが0になっている鍵」がインストールされる。つまり、攻撃者にナンスと鍵の両方がわかるのだ。これにより、攻撃者が簡単に暗号を解読できてしまう。
では、KRACKsにはどのような対策を行えばいいのだろうか。KRACKsでは「鍵の再インストール」が問題になっていた。そこで、端末のファームウエアを変更して、鍵の再インストールを許さないような実装にすればいい(図3-8)。実際に端末ベンダーはこのようにファームウエアを書き換えてKRACKsへの対策を行ったと考えられる。
メッセージ3が再送された場合、PTKを既にインストールしているかどうかをチェックし、インストールされている場合は再インストールしないようにする。これによりナンスがリセットされなくなり、攻撃が失敗する。
KRACKsの発見者であるMathy Vanhoef氏は、こうした実装の例としてブール変数▼の導入を挙げている。このブール変数を偽(false)に初期化しておく。PTKを生成するときにブール変数を真(true)にする。PTKをインストールするときには、フラグが真であればインストールしてブール変数を偽にする。インストールするときにブール変数が偽であればインストールをスキップする。
これによりPTKの再インストールを防げる。
WPAはWi-Fi Protected Accessの略。
Temporal Key Integrity Protocolの略。
Counter mode with CBC(Cipher Block Chaining)-MAC(Message Authentication Code) Protocolの略。
Pairwise Transient Keyの略。
実際にはPTKは複数の鍵で構成されており、そのうち暗号化はTK(Temporary Key)という鍵で行う。
ナンスをどのように利用するかは暗号方式によって異なる。WPA2の暗号方式であるCCMPではナンスは初期化ベクターとして使われる。
Group Temporal Keyの略。PTKはユニキャスト通信の暗号化に使うのに対し、GTKはマルチキャスト/ブロードキャスト通信の暗号化に使う。
Pairwise Master Keyの略。
Pre-Shared Keyの略。事前共有鍵。
Remote Authentication Dial In User Serviceの略。
ACKnowledgementの略。
「PTKによる暗号化」の欄外注に示したTKを指す。
値に真(true)か偽(false)だけを取る変数。