書籍「Android Security」の暗号鍵生成方法には課題がある

書籍「Android Security  安全なアプリケーションを作成するために」は既に各方面で絶賛されているように、Androidアプリケーションの開発者には必携の書籍だと思いますが、新しい分野だけに、首をひねらざるを得ない箇所もありました。このエントリでは、同書第10章「暗号化手法」から共通鍵の生成方法について議論します。


はじめに

書籍「Android Security」(業界では「タオ本」と呼ばれているので、以下タオ本と記述)の10章では、端末内のファイルを暗号化して保存する手法について説明されています。その際に問題となるのが、鍵の生成と保管の方法です。スマートフォン端末、とくにAndroid端末は、アプリケーションのリバースエンジニアリングとルート化の可能性は常にあるため、あらゆる場合にも破られない暗号化というものはありません。このため、守るべき情報資産と、想定する脅威(言い換えれば受容する脅威)を定義しなければ、有効な実装方法は得られないと考えます。
このエントリでは、典型的な脅威を3パターン想定した上で、タオ本の説明の妥当性について検証します。

典型的脅威シナリオ3パターン

スマートフォンに格納されたデータが、アプリ提供者の意図しない形で漏洩するシナリオを以下に3種類示します。

  • 端末内のマルウェアが外部にデータを漏洩する(X)
  • 端末を拾得あるいは窃取した第三者が、利用者のデータを盗む(Y)
  • 端末の所有者自身が、アプリの著作権保護されるべきデータを盗む(Z)

最初のマルウェアからの漏洩シナリオ(X)では、マルウェアルート権限を得ていないと想定します。実際には、ルート権限を悪用するマルウェアもあり得ますが、端末のルート化は利用者の自己責任で行うべきという考え方は一般に浸透しており、アプリケーション側の対策としては、ルート権限を持つマルウェアに対しては免責されると考えて良いでしょう。
二番目(Y)と三番目(Z)については、保護される情報と登場人物こそ異なるものの、端末を操作できる人が(暗号化された)情報を盗み出すという行為については共通です。従って、(Y)と(Z)については、技術的には同じ課題があると考えられます。(Y)と(Z)については、操作者がルート権限を得る可能性は現実的な脅威であり、考慮しなければならないと想定します。
(X)、(Y)、(Z)共通の前提として、アプリケーションのAPKファイルは攻撃者にとって取得可能であり、リバースエンジニアリングされ得ると想定します。これは、スマートフォンのセキュリティでは常識な前提だと考えます。

タオ本で説明されている鍵生成方法

タオ本で説明されている鍵生成方法は以下の3種類です(タオ本P232)。

  • ソースコード内に定数として定義し、使用する(A)
  • アプリケーション実行時に乱数を発生させ、パスワードとして使用する(B)
  • 動作している環境からパスワードを生成し、使用する(C)

(A)は、ソースコードに暗号鍵(の元となるパスワード)をハードコードするものです。これについて、タオ本は以下のように批判しています(タオ本P232)。

この方法の場合、リバースエンジニアリングによってソースコードが取得されれば、簡単にパスワードが判明してしまいます。簡単に解析されないように2つの文字定数のANDを取ったり、シフト演算したりする例も見られますが、効果はほとんどないと言ってよいでしょう。【中略】この方法は非常に危険なので使用しないでください。

(B)については、以下のような注釈があります(タオ本P233)。

ただし、この方法では、アプリケーションは同じ値の乱数を再生成できないので、アプリケーションが暗号化したデータを復号化(原文ママ)するためには、生成したパスワードをどこかに保存しておく必要があります。ファイルにそのまま保存したのでは、パスワードを平文でファイルに書き込んだのと何ら変わりありません。したがって、この方法が有効となるのは、データをファイルに保存する必要がない場合になります。

暗号化データをファイルに保存する応用には使えないと説明しています。
ということで、タオ本では方法(C)が暗号鍵生成の本命として説明されています。

タオ本で推奨されている暗号鍵生成方法

それでは、タオ本で推奨されている暗号鍵生成方法(C)を検証してみましょう。同書P233以下には、暗号鍵生成の実装例として以下が紹介されています。

  • アプリケーションのインストール日時を取得(PackageInfo#firstInstallTime)
  • アプリケーションのパッケージ名を取得
  • インストール日時とパッケージ名を文字列として連結したものをパスワードとする

同書P233には、この方式のメリットとして以下のように説明されています。

パスワードを端末内に保存する必要がないため、パスワードを解析しにくくなります。また、端末固有の値を使用するため、端末ごとに異なるパスワードとなり、暗号化したデータが流出してパスワードが解析されても被害が最小限で済みます。

このように書いてありますが、本当でしょうか。

タオ本方式も結局リバースエンジニアリングには弱い

タオ本方式(C)でも、リバースエンジニアリングされると、パスワードの生成方式は攻撃者に解析されると考えるべきでしょう。定数なら解析されて、ロジックなら解析されないとは考えられません。となると、パッケージ名とインストール日時を攻撃者が知ることができるかどうかが問題になります。
まず、パッケージ名はリバースエンジニアリングの時点でAPKファイル内のAndroidManifest.xmlから読み取れます。
残りは、インストール日時ということになりますが、そもそもインストール日時を鍵の元とすることが好ましくありません。インストール日時は、アプリケーションが公表された日付などから推測できるからです。昔々、Netscapeブラウザの有名な脆弱性として、日時を元に暗号鍵の元を生成していたという事例がありました(論文のリンク)。
しかも、シナリオ(X)〜(Z)においては、攻撃者がインストール日時を正確に求めることができます。
シナリオ(X)では、マルウェアがPackageInfo#firstInstallTimeを参照して、攻撃対象アプリのインストール日時を正確に求めることができます。
シナリオ(Y)とシナリオ(Z)では、端末が攻撃者の手元にあるわけですから、やはりインストール日時を正確に求めることができます。
すなわち、タオ本推奨の方法(C)は、暗号鍵生成方式がリバースエンジニアリングで求められる脅威に脆弱であり、方法(A)と大差ないことが分かります。

方法(B)はマルウェアの脅威に対しては有効

ここで、方法(B)についてあらためて評価します。タオ本には「ファイルにそのまま保存したのでは、パスワードを平文でファイルに書き込んだのと何ら変わりありません」とありますが、マルウェアによる脅威シナリオ(X)に対しては、有効です。
Androidでは、アプリケーション毎にユーザIDが割り振られ、端末のファイルシステムもこのユーザIDによって権限管理されます。すなわち、元々、他のアプリケーションのデータを参照できないように設定することになっています。このため、マルウエアから他のアプリケーションのデータファイルを参照することは(権限設定の不備がない限り)できません。
例外はSDカード内のファイルであり、SDカードはユーザIDによる権限設定がありません。このため、SDカード内のファイルを保護するために、データを暗号化するニーズがあるわけです(タオ本P229)。
すなわち、暗号鍵を乱数で生成して、Androidのローカルファイルに(適切な権限設定をして)保存すれば、暗号鍵はマルウェアから参照できません。すなわち、マルウェアの脅威に対しては、暗号鍵をローカルファイルに保存する方法は有効です。

考察

Androidアプリケーションにとって鍵管理は困難なテーマです。あらゆる脅威を想定しなければならない想定では、ルート化された端末から、あらゆる情報が参照できるため、鍵の安全性は、アプリケーションの難読化の強度に依存します。この想定では、完全な暗号化は存在せず、商用の難読化ツールを使えばある程度の強度は期待できる、と言う程度でしょう。
しかしながら、脅威について現実的な線を引けば、話は変わってきます。多くのアプリケーションは、端末を紛失した場合のデータ保護を保証しません。また、暗号化してまで著作権保護すべきデータが実質なく、著作権法による保護で十分という場合も多いでしょう。
この想定下では、もっとも警戒すべき脅威はマルウェアによる情報漏洩であり、このケースでは「乱数により生成した鍵をローカルファイルに保存する」という鍵管理が有効です。
タオ本は、このあたりの脅威分析が詰められておらず、鍵管理方式の評価が大ざっぱな内容になったものと考えます。

どうするのがよいのか

では、Androidアプリケーションでは鍵の生成と保存をどうすればよいでしょうか。
一案として、方法(A)と方法(B)のハイブリッドが考えられます。アプリケーションの初期設定時に乱数で生成してファイルに保存した鍵と、アプリケーション内に埋め込んだ定数の鍵を連結して、暗号鍵の元とする方法です。
この場合、ローカルファイルを読める権限を持つ攻撃者には鍵がばれてしまいますが、その脅威に対してはアプリケーションの難読化でがんばるしかありません。例えば、商用の難読化ツールの使用が考えられます。それでも駄目な場合はあきらめる(受容する)ということです。
これでダメなケースの典型例は、利用者が端末を紛失あるいは盗まれた場合や、著作権保護されたデータが盗用されることです。前者は利用者の過失もあるので「最大限頑張るけど破られたら申し訳ない」ですし、後者は、権利者に対して適切に説明しておくしかないでしょう。

まとめ

  • スマートフォンアプリでは、全ての脅威に対して安全な鍵管理方法はない
  • スマートフォンアプリでは、マルウェアからの情報漏洩が現実的な脅威
  • マルウェア対策には、乱数による鍵生成と権限設定したファイルへの保存が有効
  • スマートフォンアプリでは以下を要件として明確にしよう
    • 保護すべき情報資産
    • 脅威毎の対処する・対処しないの整理


[PR]
3月2日、株式会社DNPデジタルコム主催の「スマートフォン向けセキュリティセミナー」(五反田、無料)で基調講演します。この中で、スマートフォンアプリケーションのセキュリティに関する責任範囲や対策などについて、基礎的なところから説明できればと思います。

スマートフォンアプリケーションのセキュリティ強化策についての相談は、HASHコンサルティング株式会社まで。
安全なWebアプリケーションの作り方DRMフリーのPDFによる電子版もあります。