はじめに
Androidアプリケーションは主にJava言語で記述され、DEX形式のファイルにコンパイルされたコードを、DalvikというJava互換VM上で実行します。DEXおよびAPKファイルの仕様は公開されており、DEXにはクラスやメソッド等のシンボル名も含まれているため、リバースエンジニアリングが容易であると言われています。このため、Android SDKには標準でProGuardという難読化ツールが添付されています。それでは、難読化の目的はそもそも何で、難読化でその目的は達成されるのでしょうか。
難読化の目的
Webアプリケーションの場合は、重要なロジックは主にサーバー側に存在するため、ソースコードを外部から取得することはできません。これに対して、スマートフォンアプリケーションの場合は、実行プログラムが手元の端末上にあるため、リバースエンジニアリングにより、(手間の大小はともかく)ソースコードを再現させることが可能です。リバースエンジニアリングに対抗するために、プログラムを解析しにくくする行為を難読化と呼びます。
難読化の典型的な目的を以下に示します。
- アプリケーションロジックの流出防止
- 内部の隠れた脆弱性の発見防止
- 課金コードの改変による不正利用の防止
- アプリケーションの不正流用の防止
- 暗号鍵など秘密情報の漏洩防止
ProGuardとは
ProGuardとは、Android SDKに標準で添付される難読化ツールです。ProGuardには複数の機能がありますか、難読化に寄与するものとしては、クラスやメソッドの名前の付け替え(連番のような形になる)があります。クラス名やメソッド名から意味がわからなくなるため、リバースエンジニアリングがしにくくなることを期待しての機能でしょう。
ProGuardで十分なのか
セキュリティの専門家の立場から見ると、ProGuardの提供する機能は中途半端です。一般的に、リバースエンジニアリングというと、機械語のバイナリからの解析を指します。職業的にリバースエンジニアリングをしている人たち、例えばウイルス対策ソフトのマルウェア解析担当者は、なんのヒントもないマルウェアのバイナリを解析して、マルウェアの挙動を把握し、パターンファイルを作成しているわけです。最近のマルウェアは、単純な機械語ではなく、加えて難読化が施されていて解析が難しくなっていると言われています。これに対して、ProGuardの「難読化」の結果は、機械語に比べるとはるかにリバースエンジニアリングが易しいと言えます。シンボルが除去されるとは言え、アプリケーションが利用するライブラリのシンボル名などは除去できないためです。
すなわち、ProGuardの効果は、「very easyをeasyにする」程度のものと言えます。このあたりの感覚については、杉山俊春氏の寄稿記事も参考になります。
商用難読化ツールはどうか
ProGuardはどうももの足りないということであれば、商用難読化ツールというものもあります。以下に、Android向けの商用難読化ツールを紹介します。※いずれの製品も私自身は評価しておらず、推奨というわけではありません。
一例として、DashOの機能を見てみると、以下のような難読化機能が提供されています。
- 改ざん検出と通知
- 名前の変更
- 制御フローの難読化
- 文字列の暗号化
- バイトコードの最適化
- ウォーターマーク(出所を追跡可能に)
このうち、名前の変更とバイトーコードの最適化はProGuardにもある機能ですが、これら以外はProGuardにはない機能です。
難読化というからには、この程度はやって欲しい気がしますが、商用難読化ツールは高価(DashOは最小構成で79万円)なため、手軽に導入するわけにはいきません。
ではどうするのがよいか
ProGuardでは頼りない、商用難読化ツールは高価だとすると、どうすればよいのでしょうか。その答えは、先に紹介した杉山氏の記事タイトル『見せたくないなら「持たせない」が鉄則』だと思います。具体的には、見せたくないリソースやロジックは極力サーバー側に持たせ、スマートフォン側には、入力や表示など最低限の機能に絞ることです。
それでも、なんらかの事情により難読化したい場合はあるでしょうが、以下のように考えればよいでしょう。
- リバースエンジニアリングによる想定被害金額を見積もる
- 想定被害金額が商用難読化ツール購入費用よりも大幅に大きければ、商用難読化ツールにより難読化処理する
- 想定被害金額が大きくなく、費用対効果が見合わない場合は、ProGuard+手動難読化を施す
手動難読化とは私の造語ですが、プログラムロジックを故意に複雑にすることで、リバースエンジニアリングの邪魔をすることです。冗長なコードを挿入したり、文字列をエンコードあるいは暗号化した状態で保持して、アプリケーション内でデコードあるいは復号するなどです(面倒です)。
手動難読化も、あまり期待しない方がよいとは思いますが、ソースコード診断をしていると「まるで難読化されたような」読むのが嫌になるソースコードに出くわすこともしばしばですので、プログラムの下手な人に依頼すると思わぬ効果があるかもしれません(冗談です)。
また、そもそも難読化はリバースエンジニアリングを難しくするものであり、不可能にするものではないので、リバースエンジニアリングによる影響は受容可能にしなければなりません。例えば、リバースエンジニアリングによって、大量の個人情報が漏洩するような設計はダメだと言うことです。
まとめ
以上をまとめると以下のようになります。- 難読化するか否かはアプリケーション要件である
- 難読化が破られリバースエンジニアリングされた場合でも、影響が受容可能であるように設計する
- 本当に難読化の必要な場合はProGuardでは機能不足であり商用難読化ツールを検討する必要がある
- 商用難読化ツールは高価なので、導入にあたっては費用対効果の検討が不可欠
ということで、表題の「難読化していないAndroidアプリケーションは脆弱性か」という問の答えは、「一般には脆弱性とは言えず、アプリケーション要件である」が答えだと考えます。
[PR]
3月2日、株式会社DNPデジタルコム主催の「スマートフォン向けセキュリティセミナー」(五反田、無料)で基調講演します。この中で、スマートフォンアプリケーションのセキュリティに関する責任範囲や対策などについて、基礎的なところから説明できればと思います。
スマートフォンアプリケーションのセキュリティ強化策についての相談は、HASHコンサルティング株式会社まで。
「安全なWebアプリケーションの作り方」DRMフリーのPDFによる電子版もあります。