読者です 読者をやめる 読者になる 読者になる

Log.i53

Themidaのアンパックを目指すブログ改め使い物になるえんじにゃを目指すブログ

A Machine-learning Approach for Classifying and Categorizing Android Sources and Sinks を読みました

Android 英論

 FlowDroidというAndroidにおける静的テイント解析の中ではおそらく最先端の論文を読んでいたら,「FlowDroidはそのソースとシンクにSuSiプロジェクトで推測されたソースとシンクを用いている」との記載があったので読みました.自分の研究でも静的解析の際にソースとシンクのリストが必要だったのでとてもありがたいです.
 
 機械学習についてはまったく詳しくないどころかあまり興味もない分野なのですが,どのようにソースコードからソースとシンクを分類したのかが純粋に気になりました.なんとも優しいことに,教師あり学習の分かりやすい例について第4章のA項で丁寧に説明してくれるありがたい論文でした.分類器の訓練にはソース/シンクであるかどうかがアノテーションされた訓練データを使用する教師あり学習を使用しています.その分類には意味的・構文的な特徴とデータフロー特徴(粗い近似の静的テイント解析でソースからシンクへのデータフローがあったかどうか)が組み合わせて使用されます.評価の中で一番気になっていた,マルウェアで最も利用されているソースとシンクですが,そのうちの多くが研究当時の分析ツールにおいて検出できていないことが分かります(評価の項の図を参照).

 評価や機械学習の項は大分アバウトに纏めているので詳細については原文をお読み下さい.また,ソースとシンクのリストについてはGitHubで公開されています.
github.com

あらまし

 スマートフォンユーザがインストールする多くのアプリケーションは,センシティブな情報へのアクセスを行っており,開発者によって言及されていたとしても,その信頼性を判断するのは困難である.この問題に対して,研究者はより洗練された静的および動的解析ツールを研究開発することによってこの問題に対処してきた.しかしながら,これらのツールは信頼できないオブザーバにデータを漏洩する可能性のあるシンク,および,センシティブなデータのソースのリストを手動で構成しなければならなかった.ソースおよびシンクとなる可能性のある全てのAPIを手動で網羅することは現実的ではない.
 そこで,著者らは機械学習アプローチによってAndroidにおけるSourceとSinkを特定するSuSiを提案している.ソースおよびシンクであるかどうかが手動で注釈付けされたトレーニングセットを与えることで,SuSiはAPI全体のソースとシンクを自動的に特定する.また,SuSiはさらにソースとシンクを特定のカテゴリに分類している.
 Android4.2においてSuSiは数百ものソースとシンクを92%以上の精度で特定し,その多くが既存のテイント解析ツールでは見落とされているものであった.約11,000のマルウェア検体の評価により,これらのソースとシンクの多くが実際に使用されていることを確認している.また,SuSiがGoogle GlassやChromecast APIにおける未知のソースとシンクをも確実に分類できることを示している.

モチベーション

 ソースとシンクの包括的なリストを用意するのは難しく,既存研究ではソースやシンクとして非常によく知られているAndroid APIメソッドのみが含まれていると言うのが現状である.悪質なアプリケーション開発者は,そのような既存の分析ツールを回避するために,一般的によく知られていないソースやシンクを選択することが可能である.以下に,一般的ではないソースとシンクを利用してデータ漏洩を偽装しようとする例を示す.

void onCreate() {
  TelephonyManager tm; 
  GsmCellLocation loc;
  // 位置情報の取得
  tm = (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
  loc = (GsmCellLocation) tm.getCellLocation();
  
  // ソース: セルID
  int cellID = loc.getCid();
  // ソース: エリアコード
  int lac = loc.getLac();
  boolean berlin = (lac == 20228 && cellID == 62253);

  String taint = "Berlin: " + berlin + " (" + cellID + " | " + lac + ")";
  String f = this.getFilesDir() + "/mytaintedFile.txt";

  // シンク
  FileUtils.stringToFile(f, taint);
  // ファイルを誰でもリード可能にする
  Runtime.getRuntime().exec("chmod 666 "+f);
}

 このシナリオでは,2つのソースメソッドが利用される.まず,getCid()を呼び出してセルIDを取得している.次に,getLac()を呼び出して,エリアコードを取得している.両方のピースを組み合わせることで,現在のGSMセルにサービスを提供する放送塔を特定することができる.これは,正確な場所ではないものの,ユーザのおおよその居場所を提供する.上記のコードでは,ドイツのベルリンでよく知られているセルタワーIDをチェックしている.実際の悪質なアプリは,より包括的なリストで位置検索を実行する.

 最後に,取得したデータを攻撃者が利用できるようにする必要がある.上記コードでは,パーミッションなしで他のアプリケーションからアクセスすることができるファイルを携帯端末の内部ストレージに作成する.Javaの通常のファイル書き込み関数を使用する代わりに,このコードは通常SDKから隠されているあまり知られていないAndroidシステムの関数を使用している.

 上記の攻撃は,著者らが実際に検査したマルウェアの代表的な例である.Fortify SCAやSCanDroid,IBM AppScanやTaintDroidなどの公に利用可能な静的および動的テイント解析ツールでこの攻撃例をテストしたところ,これらのツールのいずれも漏洩を検出しないことを確認している.これは,悪質な動作を検出するためのソースおよびシンクの包括的なリストを生成することが,いかに重要であるかを示している.SuSiはこの例で使用されるすべてのソースとシンクを発見して,適切に分類することが可能である.

ソースとシンクの定義

 ソースとシンクを推測する前に,まず「ソース」と「シンク」という用語の正確な定義が必要となる.いくつかのテイント/情報フロー解析の分野ではソースとシンクが議論されているが,これらの用語の正確な定義については開示されていない.トレーニングデータをより良いものにするためには正しい用語の定義が欠かせない.テイント解析ではプログラムを介してデータの流れを追跡する.ソースは,プログラムのどこで追跡するデータの入力が行われたかであり,シンクはデータがどこでプログラムから離れたかを示している.以下に,各用語の厳密な定義を示す.

データ

 データは値であるか,または値を参照するものである.

リソースメソッド

 リソースメソッドは,共有リソースから「データ」を取得するか,または,共有リソースに「データ」を書き込むメソッドである.

Androidソース

 ソースは,アプリケーションコード内に定数値ではない値を返す「リソースメソッド」への呼び出しである.

Androidシンク

 シンクは,新しい値が書き込まれているか,または,既存のリソースに上書きされた場合に,アプリケーションコードから少なくとも1つの非定数データ値をパラメータとして受け取っている「リソースメソッド」への呼び出しである.

 例えば,IMEI情報は「データ」の一部であり,IMEI情報を読みだすためのメソッドTelephonyManager::getDeviceId()はリソースメソッドである.そして,getDeviceId()メソッドAndroidソースである.これは,アプリケーション内に,すべての携帯端末において異なる値(すなわち非定数値)である値を返すリソースメソッドだからである.一方,SmsManager::sendTextMessage()メソッドは特定の電話番号にテキストメッセージを送信するリソースメソッドであり,そのリソースはGSMネットワークである.また,sendTextMessage()メソッドAndroidシンクであり,これは非定数値であるメッセージテキストと電話番号をパラメータとして受け取るリソースメソッドらかである.

分類アプローチ

f:id:i53:20160208214055p:plain
(Poster LearningSourceSinksより)

 上図は,SuSiの全体的な概要を示している.SuSiは学習において2つのラウンドを実行する.入力フェーズでは,Android APIメソッド(ラベル無しデータ)と,訓練された分類器,特徴データベースを用意する.第1ラウンドではソースか,シンクか,またはそれ以外であるかどうかを分類して,第2ラウンドでは第1ラウンドの結果,ソースとシンクに選ばれたものを特定のカテゴリに分類している.トレーニングデータは手動でソースおよびシンクであるかどうかが注釈付けされたラベルデータからランダムに選ばれたもので作成される.出力フェーズにおいて,ソースとシンクの分類リストを出力する.

 分類において最も重要となる特徴データベースであるが,著者らはAndroidメソッドを分類するために144の構文的および意味的な特徴のセットを用意している.単一の特徴だけでは,与えられたAndroidメソッドがソース,シンク,またはそのどちらでもないかを決定するために明らかに不十分である.しかしながら,すべての特徴を組み合わせることで,非常に正確に分類器を訓練することが可能となる.その主な理由は,Androidフレームワークの多くの開発者が実際には一定の規則的なコーディングスタイルに従うか,または新たなものを実装する際に既存のメソッドの実装の一部を複製するからである.これらソフトウェア開発の社会的側面が,コードベースにおける規則性と冗長性につながっており,著者らの機械学習アプローチに適していると考えられる.

 具体的にSuSiは以下の1st Runの分類における特徴クラスを使用している.例えば,「メソッド名がgetで始まる」特徴クラスなど.

また,2nd Runのカテゴリ分類における特徴は以下のようにグループ化されている.例えば,「Contacts」や「SmsManager」など特定の文字列を含んでいるかなど.

評価

f:id:i53:20160208222547p:plain
10分割の交差検証より,ソース/シンク/それ以外を約92%の精度で特定できることが示されている.また,訓練した分類器によってChromecast APIやGoogleGlass APIのソースとシンクを分類してマニュアルでその成否を検証したところ,Chromecast APIについては適合率・再現率ともに100%,Google GlassAPIについては98%の適合率と100%の再現率であった.

f:id:i53:20160208223031p:plain
上図は,約11,000のマルウェア検体で最も頻繁に使用されているソース(上段)とシンク(下段),および著名な解析ツールにおける検出結果の表であり,研究当時ではTaintDroidやSCanDroidといった著名なツールにおいても特定のソースとシンクについては検出できていないことが分かる.

リミテーション

 SuSiはその「ソース」の定義上,コールバックメソッドを発見することができない.すなわち,位置情報を取得するために利用されるonLocationChangedのようなコールバック関数にはSuSiは適用できない.しかしながら,Andoroid OSにおける,コールバックインタフェースの数は,マニュアルで検査するには十分に少ない数しかなく,すべてのコールバックメソッドを既知の小規模なデータセットとして定義することで,静的解析の際に検出可能となるだろう.

 また,Androidでは,XMLファイルを介してレイアウト制御を定義している.ソースコード内で,システムのfindViewByIdメソッドに渡されたIDによって,ラベルやボタン,パスワードフィールドへの参照を返すことになる.このように,IDに応じて,このメソッドはソースになるかどうかが変化するため,正確な分析のためにはAndroidのリソースシステムをモデル化しなければならない.UIソースがパスワードフィールドのみに制限されれば問題ないが,全ての入力フィールドをソースとして認識する場合には,多くのフォルスポジティブに繋がる可能性がある.