Amankan transfer data antara dua aplikasi

Halo semuanya, hari ini saya ingin memberi tahu Anda tentang beberapa opsi untuk mentransfer data antara dua aplikasi Android dan mempertimbangkannya dari sudut pandang keamanan. Saya memutuskan untuk menulis artikel ini karena dua alasan. Pertama, saya sering mulai menemui kurangnya pemahaman tentang pengembang mekanisme untuk bekerja dengan komponen aplikasi android. Yang kedua - saya berhenti memahami apa yang menjadi pilihan mekanisme ini atau itu berdasarkan ketika mengimplementasikan fitur dan ingin menyampaikan bagaimana seharusnya terlihat pada minimum.

Tantangan

Kami memiliki 2 aplikasi yang mengakses API yang sama. Klien dapat mengakses API dengan token akses (sessionId). Anda harus menerapkan transisi yang mulus dari satu aplikasi ke aplikasi lainnya. Untuk melakukan ini, Anda harus mencari-cari di antara mereka, misalnya, biarkan sessionId.

Opsi # 1: QUERY DEEPLINK

Opsi yang paling jelas adalah mentransfer token ke Query DeepLink. Akan terlihat seperti ini:
slave://main?sessionId=686A885A4FB644053C584B9BE2A70C7D
Dalam hal ini, penerima akan dapat mengekstrak sessionId dan menggunakannya tanpa meminta izin dari pengguna. Dari sisi pengembang, sepertinya tugas telah selesai, tapi mari kita gali lebih dalam.

Pembajakan deeplink


Karena aplikasi apa pun dapat mendaftarkan skema tinkoff: //, OS dapat membuka aplikasi yang salah. Hal ini dimungkinkan karena kenyataan bahwa tidak ada pendaftaran dan pembatasan penggunaan skema. Aplikasi jahat dapat mendaftarkan skema tinkoff: // dan mencegat permintaan ke aplikasi Tinkoff dan mulai sendiri. Dalam hal ini, sessionId akan jatuh ke tangan yang salah dan akun Anda akan dikompromikan. Selain itu, DeepLink Hijacking memungkinkan Anda untuk melakukan phishing, misalnya, menampilkan bidang untuk memasukkan nama pengguna dan kata sandi.

Secara konseptual, prosesnya terlihat seperti ini:

gambar

Ada 2 solusi untuk masalah ini. Pertama, teknologi AppLinks tidak lagi memungkinkan pengembang untuk menyesuaikan skema, sebaliknya, http / https digunakan. Dalam hal ini, OS mengambil tautan slave.com/profile dan menghubungi host slave.com untuk verifikasi. Yang kedua - URL Intent - alih-alih memanggil slave: //, intent: // disebut, di mana pengidentifikasi unik aplikasi yang akan diluncurkan dilewatkan. Ini terlihat seperti ini:

 intent://main/#Intent;scheme=slave;package=com.example.slave.client.android;end" 

Dalam hal ini, tidak mungkin untuk mencegat peluncuran aplikasi, karena paket spesifik ditentukan. Namun, masalahnya tetap bahwa pengguna dapat menginstal aplikasi dari sumber pihak ketiga dengan packageId yang sama dengan budak Anda. Dalam hal ini, jika Anda tidak memiliki aplikasi budak yang sah, aplikasi jahat akan menginstal dan menerima token Anda.

Fiksasi sesi


Ini adalah serangan di mana penyerang memaksa klien untuk membuat sesi dengan perangkat lunak target menggunakan sessionId yang disediakan oleh penyerang. Segera setelah pengguna mengautentikasi, penyerang akan dapat menggunakan pengidentifikasi yang sudah diistimewakan ini untuk tujuannya sendiri. Serangan mengeksploitasi fakta bahwa perangkat lunak target menggunakan sessionId yang sama setelah eskalasi hak istimewa.


Bagaimana tampilannya dalam kasus kami:

  1. penyerang mendapat sesi anonim dari aplikasi
  2. melemparkan surat dengan indah kepada korban atas nama bank, di mana ia diundang untuk pergi ke rekening pribadinya
  3. saat mengklik tautan, kita menuju ke DeepLink dengan slave sesi penyerang: // main? sessionId = 686A885A4FB644053C584B9BE2A70C7D
  4. aplikasi seluler mengambil sesi, memahami bahwa itu tidak memiliki hak yang cukup dan meminta pengguna untuk mengotentikasi
  5. pengguna melewatinya, sesi telah meningkatkan hak
  6. pengguna dalam aplikasi, penyerang dengan sesi istimewa, untung

Adalah benar untuk memperbaikinya pada API, mengeluarkan sessionId lain setelah eskalasi hak istimewa, tetapi kami sedang menulis aplikasi seluler. Dan cara kami adalah menolak untuk mentransfer token dari master ke slave. Plus, ini akan memberi kita perlindungan mendalam dan jika ada yang rusak pada API dan token tidak akan berubah ketika hak istimewa ditingkatkan, maka serangan akan tetap mustahil.

Kebocoran pihak ke-3


Minus lain dari opsi ini. Banyak orang menggunakan layanan pihak ketiga untuk DeepLink karena kemudahan menghasilkan tautan, analitik, dan hal-hal keren lainnya. Dalam hal ini, Anda cukup memberikan token Anda kepada perusahaan pihak ketiga.

Opsi # 2: PENYEDIA KONTEN

Bagaimana kita akan melakukannya? Kami mendefinisikan penyedia konten utama dan membuat budak pergi ke penyedia konten ini untuk token.



Dengan demikian, kami menyingkirkan risiko mentransfer token ke aplikasi yang salah dalam kasus Pembajakan DeepLink dan membuat serangan Fiksasi Sesi tidak mungkin. Tetapi kami memiliki masalah lain - dalam versi saat ini, secara umum, aplikasi apa pun dapat meminta token kapan saja, bahkan jika kami tidak memulai peluncurannya.

Tingkat perlindungan


Dalam kebanyakan kasus, Anda perlu memverifikasi bahwa budak ditandatangani dengan kunci yang sama dengan master, yaitu, mereka milik penulis yang sama. Untuk kasus ini, manajer paket memiliki metode checkSignatures yang memeriksa tanda tangan aplikasi. Untuk menggunakan fungsi ini, Anda perlu menambahkan izin dengan protectionLevel = "signature" di Penyedia Konten di manifes aplikasi:

 <permission android:name="com.example.contentprovider.access" android:protectionLevel="signature"/> <application> <provider ... android:readPermission="com.example.contentprovider.access"> </application> 

Skema ini hampir tidak akan berubah dari angka sebelumnya, hanya jaminan yang akan muncul bahwa hanya aplikasi dengan tanda tangan dari penulis yang sama yang akan mendapatkan akses ke token.

Kondisi Balap Izin


Ada satu fitur yang sangat tidak menyenangkan bahwa nama izin tidak unik, yang dapat digunakan oleh aplikasi jahat dan mendaftarkan izin dengan nama kami dan protectionLevel = "normal" di hadapan kami. Dalam hal ini, ketika menginstal aplikasi kita, izin sudah ada pada OS dan itu tidak akan ditimpa. Akibatnya, penyedia konten kami akan tetap tidak terlindungi dan dengan akses resmi dari aplikasi apa pun.

Tanda tangan yang berbeda


Sayangnya, aplikasi tidak selalu ditandatangani dengan kunci yang sama, misalnya, beberapa aplikasi dibeli, atau "secara historis", tetapi transisi yang mulus masih diperlukan. Dalam hal ini, kami mengambil verifikasi tanda tangan pada diri kami.
Bagaimana ini bisa diterapkan:
Penyedia Konten memiliki metode getCallingPackage (), di mana kita bisa mendapatkan packageId dari aplikasi yang telah diterapkan untuk data, dan dengan packageId kita bisa mendapatkan daftar tanda tangan dan memeriksanya dengan yang ada di dalamnya.

 String pkg = this.getCallingPackage(); PackageInfo pkgInfo = pkgmgr.getPackageInfo(pkg, GET_SIGNATURES); Signatures[] signatures = pkgInfo.signatures; for (Signature sig: signatures) { if (sig.equals(TRUSTED_SIGNATURE)) { // trusted signature found, trust the application } } 



Tampaknya kami melakukan semuanya dengan sempurna, tetapi tidak.

Kerentanan id palsu


Masalahnya adalah bahwa ketika Android menciptakan rantai kepercayaan, proses verifikasi hanya membandingkan subjek, dan tidak memverifikasi tanda tangan di bidang penanda tangan sertifikat. Akibatnya, seorang penyerang dapat membangun rantai kepercayaan tanpa tanda tangan yang sebenarnya.

Karena kesalahan ini, rantai sertifikat yang salah dihasilkan, yang mungkin termasuk sertifikat yang sah yang tertanam di APK, tetapi tidak benar-benar digunakan untuk menandatangani aplikasi. Pada akhirnya, saya akan meninggalkan tautan ke komit yang memperbaiki kerentanan ini. Masalahnya diperbaiki di Android 4.4, jadi kami hanya bisa menaikkan Level API ke 19.

Kesimpulan

Hari ini kami memeriksa bagaimana fitur harus dianalisis selama pengembangan.
Kami juga memeriksa opsi untuk mentransfer rahasia antara dua aplikasi, di mana kami menganalisis masalah dari setiap opsi dan menemukan cara untuk menghindarinya.

Semua aplikasi aman!

Referensi

Source: https://habr.com/ru/post/id448198/


All Articles