Flutter , Google tarafından desteklenen DART dilini kullanan bir framework olarak her geçen gün popülerliği artmaktadır. Flutter dilinde yazılmış bir mobil uygulama karşınıza geldiğinde, bu framework üzerinden son noktaları (endpoint) nasıl tespit edebileceğiniz anlatılmaktadır. Apk Combo web sitesi üzerinden indirilen uygulama, ilk olarak jadx-gui ile incelemeye başlanmıştır. Kaynak kodunda ilk olarak dikkatinizi çeken Flutter sınıfı olacaktır.
Flutter framework olarak üç şekilde build edilmeye izin vermektedir.
- Debug modunda hızlı yüklemeye
- Profile modunda performans testi yapmaya
- Release modunda ise uygulamayı yayına hazır hale geldiğinde kullanılıyor.
Uygulamamız release modunda karşımıza geldiği için işimize yarayan herhangi bir bulgu ile karşılaşılmamıştır.
Uygulamayı test cihazına yükledikten sonra ilk yaptığımız Burp ile gelen trafiği incelemek oldu. Her uygulamanın Burp üzerinden geçmesine rağmen, test edeceğimiz uygulamaya dair hiçbir veri geçmemesini bir türlü anlamlandıramıyoruz.
Flutter’a dair yazılar araştırmamız sonucunda, DART dili, sistem seviyesinde proxy kabul etmemesinden dolayı trafik Burp üzerinden geçmediğini öğreniyoruz.
Test cihazı Root’lu olduğu için bu problemi ProxyDroid ile çözmek kolay olacaktır. ProxyDroid ile Burp’un kurulu olduğu bilgisayarın ip adresi ve portunu girmemiz, tüm trafiğin yönlendirilmesini sağlayacaktır.
Not: Burp Proxy’de bulunan Proxy options kısmında interface seçimini isteği kabul edecek şekilde ayarlamayı unutmamak gerekiyor.
Ancak uygulamayı Burp’e yönlendirmek tüm problemlerin çözülmesini sağlamayacaktır. SSLPining problemi bu noktada karşımıza çıkacak ve karşılaşılan ikinci problem olacaktır.
SSLPining uygulamaların hangi sitelerin sertifikalarına güvenmesi gerektiğini söyleyen bir tekniktir. Bu teknik Facebook, Google, Twitter gibi dev şirketler tarafından resmi uygulamalarda kullanılmaktadır. Android İşletim Sistemi’nde yazılan uygulamalar üzerinde SSLPining’i iptal etmenin farklı yolları mevcut fakat bu yazı Frida üzerinden nasıl gerçekleştireceğimizi anlatarak devam ediyoruz.
Frida mobil ve masaüstü uygulamaları test etmek amacıyla geliştirilmiş bir Framework’tür. Andorid ve IOS için de desteği bulunmaktadır. Memory erişimi sayesinde ve uygulamaların functionlarına hook (kanca) atarak, uygulama üzerinde testler yapılmasını kolaylaştıran özelliklere de sahiptir.
Frida Android üzerinde bulunan bazı apilerin SSLPining özelliklerini devre dışı bırakabiliyor. Bu adresteki script java, okhttp3 gibi birçok apinin sslpining özelliğini devre dışı bırakabilmektedir. Fakat bu snippet uygulmamızdaki SSLPiningi devre dışı bırakamamıştır.
Unhandled Exception: HandshakeException: Handshake error in client (OS Error:)
…şeklinde hata alıp vermektedir. Sonrasında hata kodunu araştırarak Flutterda ssl unpinning yapılabileceğini görüyoruz.
Flutter uygulamaları, compile edilip minimize edildiği için, ulaşmamız gereken fonksiyonlar libflutter.so kütüphanesi içerisinde yer alıyor. Intercepting Traffic From Android Flutter Applications sayfasında yazan bilgiler doğrultusunda boringssl kütüphanesindeki ssl_verify_result_t güvenli SSL bağlantısı olup olmadığını belirlediğini tespit ediyoruz.
Ghidra ile libflutter.so dosyasını açıp analiz etmesine izin verdikten sonra, Search başlığının altında en altta bulunan For Strings ile x509.cc ‘yi aramaya başlıyoruz. Karşımıza çıkan referanslardan birinde
FUN_005df3b8 fonksiyonu ile karşılaşıldı. Yine aynı siteye baktığımda ilk 10 byte memory içinde araştırıp fonksiyonu bulmak istedik ancak sitedeki…
frida -U -f com.xx.app -l flutter.js –no-pause
…komutu hiçbir şekilde libflutter.so kütüphanesini bulamıyor. Biraz uğraştıktan sonra fark ettiğimiz husus, frida kütüphane yüklenmeden kütüphaneye bağlanmaya (hook atmaya) çalışıyor, bu da hataya sebep oluyordu.
Önce uygulamayı önce telefonda çalıştırıp sonrasında komutu…
frida -U com.xx.app -l flutter.js
…şeklinde güncellediğimiz zaman ise Access Violation hatası almaya başlıyoruz. Bu noktada Memory yetkilerini düşünerek Frida içinde nasıl aşabileceği düşünüyoruz.
Frida nın api sayfasında ufak bir gezinti sonrasında…
Memory.protect (base,size,”rwx”);
…komutunun belirtilen adres ve boyutu boyunca memory de okuma yazma ve yürütme yetkilerini düzenlediğini fark ediyoruz. Koda eklediğim bu kod functiondan sonra bir çok adres elde ettik halbuki elde etmemiz gereken sadece bir tane olması gerekiyordu.
Bu noktada ilk 10 byte yerine 48 byte’ı arayarak işimizi garantiye alıyoruz. Netice de SSLpining’i devre dışı bırakılmıştır. Bu uzun ve zahmetli süreç sonunda giden istekleri görmenin değeri paha biçilemez olacaktır.
Kullandığımız kod ise aşağıdaki gibidir.
function hook_ssl_ verify_result (address) { Interceptor.attach (address, { onEnter: function(args) { console.log(” Disabling SSL validation”) }, onLeave: function(retval) { console.log (“Retval: ” + retval) retval.replace (0x1); console.log ( “Changed retval is => ” + retval) } }); } function disablePinning () { var m = Process.find ModuleByName (“libflutter.so”); var pattern = “f7 5b bd a9 f5 53 01 a9 f3 7b 02 a9 f4 03 03 2a 3f 60 08 94 f3 03 00 2a 8f ff ff 97 40 03 00 b4 f7 03 00 aa 7f 0a 00 71 81 00 00 54 76 00 00 35″ var result = Memory.protect (m.base,m.size,”rwx”); var res = Memory.scan (m.base, m.size, pattern, { onMatch: function (address, size) { console.log (‘[+] ssl_verify_result found at: ‘ + address.toString ()); hook_ssl_verify_result (address); }, onError: function (reason) { console.log (‘[!] There was an error scanning memory’); }, onComplete: function () { console.log (“All done”) } }); } setTimeout (disablePinning, 1000) |
Yazar: Üzeyir Destan