AVTOKYO2013.5 CVE-2013-4787(Master Key Vulnerability)のソースコード的解説

3,346 views

Published on

English version is here.
http://www.slideshare.net/MasataNishida/avtokyo20135-detail-of-cve20134787

Published in: Technology
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,346
On SlideShare
0
From Embeds
0
Number of Embeds
162
Actions
Shares
0
Downloads
27
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide

AVTOKYO2013.5 CVE-2013-4787(Master Key Vulnerability)のソースコード的解説

  1. 1. http://www.flickr.com/photos/bcostin/2619263350/ CVE-2013-4787(Master Key Vulnerability) & Zip implementation of Android Masata NISHIDA AVTOKYO2013.5 (16th Feb. 2014) 日本語版
  2. 2. 自己紹介 • ニシダマサタ (西田雅太) • セキュアブレイン所属 • 普段は解析・研究よりもコード書いてる • Rubyist • @masata_masata 2
  3. 3. Agenda • CVE-2013-4787のソースコード的解説 • AndroidのZip周りの実装の微妙な点の紹介 3
  4. 4. CVE-2013-4787 Master Key Vulnerability 4 http://www.flickr.com/photos/plaisanter/5344873860/
  5. 5. CVE-2013-4787 Master Key Vulnerability • Android OSの脆弱性 • 署名を変更せずに正規のアプリの中に任意の実行 コードが挿入できてしまう ⇒すげー影響でかい & ユーザは防ぎようがない... http://bluebox.com/corporate-blog/bluebox-uncovers-android-master-key/ 5
  6. 6. これ、アカンやつや! 6
  7. 7. Keywords • Apkファイル = Zipファイル • Zipファイルのフォーマット • Apkの署名確認 7 http://www.flickr.com/photos/mrcam/206628965/
  8. 8. APK File (Android Application Package) APKファイルはZipファイル 必ずDalvik VMの実行ファイルとマニフェストファイルを含む classes.dex sample.apk (zipファイル) DEXファイル (Java実行コード) AndroidManifest.xml マニフェストファイル 8
  9. 9. Zip Format local file header Local File Header (ファイル情報) File Data (圧縮データ) File data local file header File data central directory file header central directory file header Central Directory File Header ファイル名、圧縮前後のサイズ ファイルデータへのオフセット値
 圧縮方式とか End of central directory record 9
  10. 10. Androidの署名確認 • 全てのアプリには署名がしてある • Zipに含まれた各ファイルに対して署名してある • • 署名した後で入れ替えられない アプリインストール時に署名を確認する 10 http://www.flickr.com/photos/gearys/276917907/
  11. 11. ここで、Zipエントリーに複数の同じ名前の
 ファイルが含まれるパターンを考える 11
  12. 12. APK File duplicated files sample.apk (zipファイル) classes.dex classes.dex AndroidManifest.xml AndroidManifest.xml Zipファイルに同じファイル名のエントリーが 存在することは、仕様上問題ない...はず あとは、Zipを解釈する実装側の問題 12
  13. 13. APK File duplicated files classes.dex sample.apk (zipファイル) 偽物 classes.dex 本物 AndroidManifest.xml 偽物 AndroidManifest.xml 本物 Apkの中に偽物の実行コードとマニフェストを
 挿入してインストールしてみると... 13
  14. 14. 元の署名のままで、
 別の実行コードを含んだ
 アプリが作れてしまう! 14
  15. 15. なんでこんなことが起こるか? • Android OSに複数のZipアーカイバ実装がある • 署名チェック → java.util.zip • アプリインストール → C++実装 • frameworks/native/libs/utils/ZipFileRO.cpp • dalvik/libdex/ZipArchive.cpp Zipエントリー内に重複エントリーが
 あったときの挙動の違いが原因 15
  16. 16. ZipのCentral Directory File Headerを
 パースする部分のソースを読んでみる 16 http://www.flickr.com/photos/ajstarks/4196202909/
  17. 17. ZipFileRO & libdex/ZipArchive • ZipFileROとlibdex/ZipArchiveはほとんど似たよう な実装 • Central Directory File Headerをパースして、順繰 りにファイル名をハッシュテーブルに詰めていく 17
  18. 18. bool ZipFileRO::parseZipArchive(void)! {! :! :! const unsigned char* ptr = cdPtr;! for (int i = 0; i < numEntries; i++) {! :! :! unsigned int fileNameLen, extraLen, commentLen, hash;! ! fileNameLen = get2LE(ptr + kCDENameLen);! extraLen = get2LE(ptr + kCDEExtraLen);! commentLen = get2LE(ptr + kCDECommentLen);! ! /* add the CDE filename to the hash table */! hash = computeHash((const char*)ptr + kCDELen, fileNameLen);! addToHash((const char*)ptr + kCDELen, fileNameLen, hash);! ! ptr += kCDELen + fileNameLen + extraLen + commentLen;! :! :! }! :! :! } ハッシュテーブルへの追加 ファイル名からハッシュ値の計算 18
  19. 19. ZipFileRO & libdex/ZipArchive void ZipFileRO::addToHash(const char* str, int strLen, unsigned int hash)! {! int ent = hash & (mHashTableSize-1);! ! /*!      * We over-allocate the table, so we're guaranteed to find an empty slot.!      */! while (mHashTable[ent].name != NULL)! ent = (ent + 1) & (mHashTableSize-1);! ! mHashTable[ent].name = str;! mHashTable[ent].nameLen = strLen;! } hash値が重複していたら、次のhash値が空いているか
 調べて入れる
 名前の重複 → 先勝ち 19
  20. 20. JavaのZip実装 public class ZipFile implements Closeable, ZipConstants {! ! ! ! ! ! private final LinkedHashMap<String, ZipEntry> mEntries = new LinkedHashMap<String, ZipEntry>();! private void readCentralDir() throws IOException {! ! :! ! :! RAFStream rafStream = new RAFStream(raf, centralDirOffset);! BufferedInputStream bufferedStream = new BufferedInputStream(rafStream, 4096);! byte[] hdrBuf = new byte[CENHDR]; // Reuse the same buffer for each entry.! for (int i = 0; i < numEntries; ++i) {! ZipEntry newEntry = new ZipEntry(hdrBuf, bufferedStream);! mEntries.put(newEntry.getName(), newEntry);! }! }! } ファイル名をキーとしてHashMapにZipEntryをセットしている. ファイル名が重複 → チェックしないで上書き → 後勝ち 20
  21. 21. …ということで、 • 署名チェック → 後勝ち • • 後ろのZipエントリーが使われる 実際のインストール → 先勝ち • 前のZipエントリーが使われる 21 http://www.flickr.com/photos/49121171@N00/6831724767/
  22. 22. 本来のclasses.dexの zipエントリーの前に 他のclasses.dexを
 入れれば、そっちが
 インストールされる!! http://unsplash.com/post/57711421529/download-by-may-pamintuan 22
  23. 23. Patch Android security bug 8219321 重複エントリーがあったら、例外投入というJava 側の修正 23
  24. 24. おまけ:Zip周りの怪しい点 24 http://www.flickr.com/photos/26207806@N00/1315037834/
  25. 25. Zip周りの怪しい点 〜話したかったこと〜 • インストール時にZip(Apk)のファイルヘッダを あまりちゃんと見ていない話 • encryptフラグの無視 • compression methodは非圧縮かDeflate圧縮で 扱われる 25
  26. 26. 26

×