SSL Pinning Bypass di Aplikasi iOS



Hai, nama saya Andrey Batutin, saya Pengembang iOS Senior di DataArt. Dalam artikel sebelumnya, kami berbicara tentang bagaimana Anda bisa mengendus lalu lintas aplikasi seluler kami menggunakan proksi HTTPS. Dalam hal ini, kita akan membahas cara mem-bypass Pinning SSL. Untuk berjaga-jaga, saya sarankan membaca artikel pertama jika Anda belum membacanya: ini akan diperlukan untuk memahami teks di bawah ini.

Sebenarnya, dalam praktiknya Pinning SSL digunakan sehingga metode yang diuraikan untuk memeriksa dan memodifikasi lalu lintas aplikasi seluler tidak dapat diakses oleh orang jahat atau bos yang ingin tahu.

Apa itu Pinning SSL


Pada artikel sebelumnya, kami memasang Sertifikat Root Charles pada perangkat seluler kami, yang memungkinkan Proxy Charles kami menerima, mendekripsi, menunjukkan lalu lintas kepada kami, mengenkripsi kembali dan mengirimkannya ke Dropbox.

Jika saya, sebagai pengembang aplikasi seluler, ingin lalu lintas saya diperiksa hanya oleh server saya dan bukan orang lain, bahkan jika yang lain ini telah menginstal sertifikat SSL-nya pada perangkat, saya dapat menggunakan Pinning SSL.

Esensinya adalah bahwa selama jabat tangan SSL, klien memeriksa sertifikat yang diterima dari server.

Artikel ini membahas metode Pinning SSL termudah untuk diterapkan dengan menggunakan daftar sertifikat yang diizinkan yang disambungkan ke dalam aplikasi (daftar putih).

Lebih lanjut tentang jenis Pinning SSL dapat ditemukan di sini .

Implementasi Pinning SSL di FoodSniffer


Kode proyek lengkap ada di sini . Pertama, kita perlu mendapatkan dua sertifikat dalam format DER untuk dua host:


Server kedua menyimpan JSON sendiri dengan daftar pembelian kami.

Untuk mendapatkan sertifikat dalam format yang tepat, saya menggunakan Mozila Firefox.

Buka dropbox.com di browser.

Klik pada simbol kunci di bilah alamat.





Klik Informasi Lebih Lanjut, pilih Keamanan -> Lihat Sertifikat.



Kemudian pilih Detail dan temukan sertifikat akhir di Hirarki Sertifikat.



Klik Ekspor dan simpan dalam format DER.



Ulangi prosedur yang sama untuk uc9b17f7c7fce374f5e5efd0a422.dl.dropboxusercontent.com.

Catatan
Server konten Dropbox (* .dl.dropboxusercontent.com) menggunakan sertifikat wildcard. Ini berarti bahwa sertifikat yang Anda ekstrak untuk server uc9b17f7c7fce374f5e5efd0a422 akan cocok untuk server Dropbox * .dl.dropboxusercontent.com lainnya.

Akibatnya, saya mendapat dua file dengan sertifikat:

dropboxcom.crt ,
dldropboxusercontentcom.crt ,

yang saya tambahkan ke proyek aplikasi iOS FoodSniffer.



Kemudian saya menambahkan ekstensi untuk kelas pelanggan FoodListAPIC, di mana saya memeriksa sertifikat yang diterima dari server. Untuk melakukan ini, saya mencarinya di daftar sertifikat yang diizinkan, memproses delegasi Tantangan Otentikasi NSURLSessionDelegate protokol:

extension FoodListAPIConsumer { func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { guard let trust = challenge.protectionSpace.serverTrust else { completionHandler(.cancelAuthenticationChallenge, nil) return } let credential = URLCredential(trust: trust) if (validateTrustCertificateList(trust)) { completionHandler(.useCredential, credential) } else { completionHandler(.cancelAuthenticationChallenge, nil) } } func validateTrustCertificateList(_ trust:SecTrust) -> Bool{ for index in 0..<SecTrustGetCertificateCount(trust) { if let certificate = SecTrustGetCertificateAtIndex(trust, index){ let serverCertificateData = SecCertificateCopyData(certificate) as Data if ( certificates.contains(serverCertificateData) ){ return true } } } return false } } 

Dalam array sertifikat , saya memiliki representasi data dari sertifikat yang diizinkan.

Sekarang, ketika Proxy Charles sedang berjalan, aplikasi akan terputus karena fakta bahwa sertifikat Charles tidak termasuk dalam daftar yang diizinkan. Pengguna akan melihat kesalahan berikut:



Peretas dikalahkan!

Tetapi sekarang ada satu masalah kecil - bagaimana saya, pengembang, dapat memonitor lalu lintas HTTPS dari aplikasi saya sendiri?

Frida


Salah satu opsi adalah untuk menonaktifkan SSL Pinning dengan kerangka injeksi kode dinamis dari kerangka Frida .

Idenya adalah bahwa metode validateTrustCertificateList selalu mengembalikan true selama pengembangan aplikasi.

Ini, tentu saja, dapat dicapai tanpa injeksi kode dinamis, misalnya, menggunakan kondisi #jika targetEnvironment (simulator) untuk menonaktifkan Pinning SSL pada simulator, tetapi itu terlalu sederhana.

Dengan menggunakan Frida, kita dapat menulis skrip JavaScript (secara cerdik, bukan?) Di mana kita mengganti implementasi validateTrustCertificateList dengan yang selalu mengembalikan true.
Dan skrip ini akan disuntikkan ke aplikasi pada tahap eksekusi.

Cara kerja Frida di iOS, Anda bisa baca di sini .

Instalasi Frida (diambil dari sini ).



sudo pip instal frida-tools

Skrip Frida


Script langsung untuk menggantikan fungsi validateTrustCertificateList terlihat seperti ini:

 // Are we debugging it? DEBUG = true; function main() { // 1 var ValidateTrustCertificateList_prt = Module.findExportByName(null, "_T016FoodSnifferFrida0A15ListAPIConsumerC024validateTrustCertificateD0SbSo03SecG0CF"); if (ValidateTrustCertificateList_prt == null) { console.log("[!] FoodSniffer!validateTrustCertificateList(...) not found!"); return; } // 2 var ValidateTrustCertificateList = new NativeFunction(ValidateTrustCertificateList_prt, "int", ["pointer"]); // 3 Interceptor.replace(ValidateTrustCertificateList_prt, new NativeCallback(function(trust) { if (DEBUG) console.log("[*] ValidateTrustCertificateList(...) hit!"); return 1; }, "int", ["pointer"])); console.log("[*] ValidateTrustCertificateList(...) hooked. SSL pinnig is disabled."); } // Run the script main(); 

  1. Kami menemukan pointer untuk memvalidasiTrustCertificateList di biner aplikasi dengan nama lengkap fungsi.
  2. Kami membungkus pointer dalam pembungkus NativeFunction, yang menunjukkan jenis parameter dan nilai output fungsi.
  3. Ganti implementasi fungsi validateTrustCertificateList dengan yang selalu mengembalikan 1 (mis. True).

Seluruh skrip ada di {source_root} /fridascrpts/killCertPinnig.js .

Salah satu masalah adalah bagaimana nama lengkap fungsi _T016FoodSnifferFrida0A15ListAPIConsumerC024validateTrustCertificateD0SbSo03SecG0CF diperoleh

Untuk ini, saya menggunakan teknik berikut.

  • Dibuat target FoodSnifferFrida tambahan dalam aplikasi.
  • Saya menghubungkan perpustakaan FridaGadget.dylib ke sana, yang saya ambil di sini. Prosedur koneksi perpustakaan dijelaskan secara lebih rinci di sini.
  • Meluncurkan aplikasi FoodSniffer di simulator.
  • Menggunakan perintah ini untuk menemukan nama fungsi yang sepenuhnya memenuhi syarat validateTrustCertificateList :
    frida-trace -R -f re.frida.Gadget -i "* validateTrust *"
  • Dapatkan dalam bentuk:

Dan kemudian menggunakannya di killCertPinnig.js .

Mengapa nama "aneh" seperti itu berakhir pada akhirnya dan apa arti semua T016 dan 0A15 ini, dapat dilihat di sini .

Pinning Pembunuhan SSL


Sekarang akhirnya luncurkan FoodSniffer dengan SSL Pinnig dinonaktifkan!

Luncurkan Proxy Charles.

Jalankan FoodSnifferFrida target dalam proyek Xcode di simulator. Kita seharusnya melihat layar putih saja. Aplikasi menunggu Frida untuk terhubung.


Jalankan Frida untuk menjalankan skrip killCertPinnig.js :
frida -R -f re.frida.Gadget -l ./fridascrpts/killCertPinnig.js

Mari kita tunggu koneksi ke aplikasi iOS:



Lanjutkan aplikasi menggunakan perintah% resume:



Sekarang kita akan melihat daftar makanan dalam aplikasi:



Dan JSON dalam Proxy Charles:



Untung!

Kesimpulan


Frida seperti Wireshark untuk binari. Ini bekerja pada platform iOS, Android, Linux, Windows. Kerangka kerja ini memungkinkan Anda untuk melacak panggilan ke metode dan fungsi - baik sistem dan pengguna. Dan juga mengganti nilai parameter, nilai balik dan implementasi fungsi.

Memotong SSL Pinning di lingkungan pengembangan menggunakan Frida mungkin tampak sedikit berlebihan . Itu menarik saya karena saya tidak perlu memiliki logika khusus dalam aplikasi untuk debugging dan pengembangan aplikasi. Logika ini mengacaukan kode dan, jika diterapkan secara tidak benar, dapat bocor ke versi rilis perakitan (makro, halo untuk Anda!).

Selain itu, Frida berlaku untuk Android. Yang memberi saya kesempatan untuk membuat hidup lebih mudah bagi seluruh tim saya dan memastikan proses yang lancar untuk mengembangkan seluruh lini produk.
Frida memposisikan dirinya sebagai alat injeksi kode proses kotak hitam. Dengan itu, dimungkinkan, tanpa mengubah kode langsung dari aplikasi iOS, untuk menambahkan panggilan metode logging ke runtime, yang bisa sangat diperlukan ketika men-debug bug yang kompleks dan langka.

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


All Articles