Обходим SSL Pinning на Android
LOLZTEAMПодробный гайд по обходу SSL Pinning с помощью Frida!
Статья носит образовательный характер, мы ни к чему не призываем и не обязываем. Информация представлена исключительно в ознакомительных целях.
Немного теории
По умолчанию, устанавливая SSL соединение по протоколу HTTPS, клиент проверяет сертификат сервера по двум пунктам:
- что цепочку SSL сертификата можно проследить от вашего личного SSL сертификата через промежуточные и до корневого сертификата доверенного центра сертификации;
- что Ваш SSL сертификат соответствует запрошенному имени хоста.
Но клиент не проверяет, точно ли данный сертификат является именно тем сертификатом, который использует ваш сервер. Сопоставление клиентом SSL сертификатов, которые находятся в хранилище доверенных сертификатов устройства, и тех, которые используются на удаленном сервере, открывает потенциальную дыру в безопасности.
Решение этой проблемы - SSL pinning – внедрение SSL сертификата, который используется на сервере, в код мобильного приложения. В этом случае приложение будет игнорировать хранилище сертификатов устройства, полагаясь только на свое хранилище и позволяя создать защищенное SSL соединение с хостом, подписанным только сертификатом, что хранится в самом приложении.
Мы же с вами разберем, как можно обойти это ограничение, чтобы снимать сертификаты на приложениях.
Приступим
- Для начала скачаем Python - https://www.python.org/downloads/.
- Запускаем, ставим галочку на "Add Python 3.8 to PATH" и дальше на "Install Now".
- Далее для того, чтобы Python нормально заработал, переходим в Параметры->Приложения и возможности->Псевдонимы выполнения приложения и снимаем тумблеры.
- Проверяем, что Python установился, в cmd этой командой:
python --version
Теперь установим эмулятор Memu
- Переходим на сайт https://www.memuplay.com/ и качаем свежую версию.
- Устанавливаем себе в удобную папку эмулятор и, не забыв нажать "Decline", когда нам предложат, установить антивирус McAfee
- Запускаем Multi-MEmu и в настройках виртуальной машины включаем root.
Установка и настройка BURPSuite
- Скачиваем с официального сайта BURP Suite - https://portswigger.net/burp, версию Community.
- Переходим в "Proxy" и "Options", нажимаем "add".
- Дальше нажимаем "OК".
- Запускаем эмулятор. Затем устанавливаем приложение, на котором вы хотите снять сертификат.
- В эмуляторе переходим "Настройки - WiFi - Наша_WiFi_Cеть - Расширенные настройки" и добавляем туда наш прокси, который мы выбрали выше.
- Дальше идем в браузер пишем:
http://burpsuite
- или наш прокси, который мы выбрали.
- После того как скачали, идем в файловый менеджер, переименовываем с cacert.der на cacert.crt и устанавливаем его.
Теперь переходим к Frida
- Открываем cmd и пишем туда по очереди:
1 . pip install frida 2 . pip install objection 3 . pip install frida-tools
- Дальше качаем на сайте свежую версию adbtool - тык и распаковываем в удобную папку, в моем случае это C:\adb.
- Сохраняем скрипт (ищи его в конце статьи) под именем fridascript.js в папке adb.
- Переходим в эмулятор "Настройки - О планшете", кликаем по "Номеру сборки", пока вы не станете разработчиком.
- Теперь идем в пункт настроек "Для разработчиков" и включаем "Отладку по USB".
- Открываем cmd в папке adb.
- И в открывшемся cmd пишем:
adb connect 127.0.0.1:21503
- Проверим что устройство подключилась к adb , вводим еще одну команду:
adb devices
- Дальше нам надо скачать Frida-server в соответствие с архитектурой нашего устройства, для этого впишем в cmd еще одну команду:
adb shell getprop ro.product.cpu.abi
- Переходим на GitHub - https://github.com/frida/frida/releases/, и скачиваем нужную версию, в моем случае это frida-server-12.11.1-android-x86_64.xz.
- Внедряем frida-server в наше устройство:
adb push C:\adb\тут ваша версия /data/local/tmp/ adb shell chmod 777 /data/local/tmp/тут ваша версия
- Теперь нам надо запустить frida-server:
adb shell /data/local/tmp/тут ваша версия &
- Не закрывая cmd, мы запускаем новый cmd таким же способом, как и выше (из папки adb), и пишем:
frida-ps -U
- И ищем то приложение, с которого нам нужно снять сертификат.
- Теперь заинжектим скрип fridascript.js в приложение:
frida -U -l fridascript.js --no-paus -f тут ваше приложения
- Мои поздравления! Вы отснифали андроид приложение!
На этом все! Надеюсь, было полезно!
Обещанный скрипт, который вам необходимо поставить.
/* Android ssl certificate pinning bypass script for various methods by Maurizio Siddu Run with: frida -U -f [APP_ID] -l frida_multiple_unpinning.js --no-pause */ setTimeout(function() { Java.perform(function () { console.log(''); console.log('======'); console.log('[#] Android Bypass for various Certificate Pinning methods [#]'); console.log('======'); var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager'); var SSLContext = Java.use('javax.net.ssl.SSLContext'); // TrustManager (Android < 7) var TrustManager = Java.registerClass({ // Implement a custom TrustManager name: 'dev.asd.test.TrustManager', implements: [X509TrustManager], methods: { checkClientTrusted: function (chain, authType) {}, checkServerTrusted: function (chain, authType) {}, getAcceptedIssuers: function () {return []; } } }); // Prepare the TrustManager array to pass to SSLContext.init() var TrustManagers = [TrustManager.$new()]; // Get a handle on the init() on the SSLContext class var SSLContext_init = SSLContext.init.overload( '[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom'); try { // Override the init method, specifying the custom TrustManager SSLContext_init.implementation = function(keyManager, trustManager, secureRandom) { console.log('[+] Bypassing Trustmanager (Android < 7) request'); SSLContext_init.call(this, keyManager, TrustManagers, secureRandom); }; } catch (err) { console.log('[-] TrustManager (Android < 7) pinner not found'); //console.log(err); } // OkHTTPv3 (double bypass) try { var okhttp3_Activity = Java.use('okhttp3.CertificatePinner'); okhttp3_Activity.check.overload('java.lang.String', 'java.util.List').implementation = function (str) { console.log('[+] Bypassing OkHTTPv3 {1}: ' + str); return true; }; // This method of CertificatePinner.check could be found in some old Android app okhttp3_Activity.check.overload('java.lang.String', 'java.security.cert.Certificate').implementation = function (str) { console.log('[+] Bypassing OkHTTPv3 {2}: ' + str); return true; }; } catch (err) { console.log('[-] OkHTTPv3 pinner not found'); //console.log(err); } // Trustkit (triple bypass) try { var trustkit_Activity = Java.use('com.datatheorem.android.trustkit.pinning.OkHostnameVerifier'); trustkit_Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function (str) { console.log('[+] Bypassing Trustkit {1}: ' + str); return true; }; trustkit_Activity.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function (str) { console.log('[+] Bypassing Trustkit {2}: ' + str); return true; }; var trustkit_PinningTrustManager = Java.use('com.datatheorem.android.trustkit.pinning.PinningTrustManager'); trustkit_PinningTrustManager.checkServerTrusted.implementation = function () { console.log('[+] Bypassing Trustkit {3}'); }; } catch (err) { console.log('[-] Trustkit pinner not found'); //console.log(err); } // TrustManagerImpl (Android > 7) try { var TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl'); TrustManagerImpl.verifyChain.implementation = function (untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) { console.log('[+] Bypassing TrustManagerImpl (Android > 7): ' + host); return untrustedChain; }; } catch (err) { console.log('[-] TrustManagerImpl (Android > 7) pinner not found'); //console.log(err); } // Appcelerator Titanium try { var appcelerator_PinningTrustManager = Java.use('appcelerator.https.PinningTrustManager'); appcelerator_PinningTrustManager.checkServerTrusted.implementation = function () { console.log('[+] Bypassing Appcelerator PinningTrustManager'); }; } catch (err) { console.log('[-] Appcelerator PinningTrustManager pinner not found'); //console.log(err); } // OpenSSLSocketImpl Conscrypt try { var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl'); OpenSSLSocketImpl.verifyCertificateChain.implementation = function (certRefs, JavaObject, authMethod) { console.log('[+] Bypassing OpenSSLSocketImpl Conscrypt'); }; } catch (err) { console.log('[-] OpenSSLSocketImpl Conscrypt pinner not found'); //console.log(err); } // OpenSSLEngineSocketImpl Conscrypt try { var OpenSSLEngineSocketImpl_Activity = Java.use('com.android.org.conscrypt.OpenSSLEngineSocketImpl'); OpenSSLSocketImpl_Activity.verifyCertificateChain.overload('[Ljava.lang.Long;', 'java.lang.String').implementation = function (str1, str2) { console.log('[+] Bypassing OpenSSLEngineSocketImpl Conscrypt: ' + str2); }; } catch (err) { console.log('[-] OpenSSLEngineSocketImpl Conscrypt pinner not found'); //console.log(err); } // OpenSSLSocketImpl Apache Harmony try { var OpenSSLSocketImpl_Harmony = Java.use('org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl'); OpenSSLSocketImpl_Harmony.verifyCertificateChain.implementation = function (asn1DerEncodedCertificateChain, authMethod) { console.log('[+] Bypassing OpenSSLSocketImpl Apache Harmony'); }; } catch (err) { console.log('[-] OpenSSLSocketImpl Apache Harmony pinner not found'); //console.log(err); } // PhoneGap sslCertificateChecker (https://github.com/EddyVerbruggen/SSLCertificateChecker-PhoneGap-Plugin) try { var phonegap_Activity = Java.use('nl.xservices.plugins.sslCertificateChecker'); phonegap_Activity.execute.overload('java.lang.String', 'org.json.JSONArray', 'org.apache.cordova.CallbackContext').implementation = function (str) { console.log('[+] Bypassing PhoneGap sslCertificateChecker: ' + str); return true; }; } catch (err) { console.log('[-] PhoneGap sslCertificateChecker pinner not found'); //console.log(err); } // IBM MobileFirst pinTrustedCertificatePublicKey (double bypass) try { var WLClient_Activity = Java.use('com.worklight.wlclient.api.WLClient'); WLClient_Activity.getInstance().pinTrustedCertificatePublicKey.overload('java.lang.String').implementation = function (cert) { console.log('[+] Bypassing IBM MobileFirst pinTrustedCertificatePublicKey {1}: ' + cert); return; }; WLClient_Activity.getInstance().pinTrustedCertificatePublicKey.overload('[Ljava.lang.String;').implementation = function (cert) { console.log('[+] Bypassing IBM MobileFirst pinTrustedCertificatePublicKey {2}: ' + cert); return; }; } catch (err) { console.log('[-] IBM MobileFirst pinTrustedCertificatePublicKey pinner not found'); //console.log(err); } // IBM WorkLight (ancestor of MobileFirst) HostNameVerifierWithCertificatePinning (quadruple bypass) try { var worklight_Activity = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning'); worklight_Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSocket').implementation = function (str) { console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {1}: ' + str); return; }; worklight_Activity.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function (str) { console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {2}: ' + str); return; }; worklight_Activity.verify.overload('java.lang.String', '[Ljava.lang.String;', '[Ljava.lang.String;').implementation = function (str) { console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {3}: ' + str); return; }; worklight_Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function (str) { console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {4}: ' + str); return true; }; } catch (err) { console.log('[-] IBM WorkLight HostNameVerifierWithCertificatePinning pinner not found'); //console.log(err); } // Conscrypt CertPinManager try { var conscrypt_CertPinManager_Activity = Java.use('com.android.org.conscrypt.CertPinManager'); conscrypt_CertPinManager_Activity.isChainValid.overload('java.lang.String', 'java.util.List').implementation = function (str) { console.log('[+] Bypassing Conscrypt CertPinManager: ' + str); return true; }; } catch (err) { console.log('[-] Conscrypt CertPinManager pinner not found'); //console.log(err); } // CWAC-Netsecurity (unofficial back-port pinner for Android < 4.2) CertPinManager try { var cwac_CertPinManager_Activity = Java.use('com.commonsware.cwac.netsecurity.conscrypt.CertPinManager'); cwac_CertPinManager_Activity.isChainValid.overload('java.lang.String', 'java.util.List').implementation = function (str) { console.log('[+] Bypassing CWAC-Netsecurity CertPinManager: ' + str); return true; }; } catch (err) { console.log('[-] CWAC-Netsecurity CertPinManager pinner not found'); //console.log(err); } // Worklight Androidgap WLCertificatePinningPlugin try { var androidgap_WLCertificatePinningPlugin_Activity = Java.use('com.worklight.androidgap.plugin.WLCertificatePinningPlugin'); androidgap_WLCertificatePinningPlugin_Activity.execute.overload('java.lang.String', 'org.json.JSONArray', 'org.apache.cordova.CallbackContext').implementation = function (str) { console.log('[+] Bypassing Worklight Androidgap WLCertificatePinningPlugin: ' + str); return true; }; } catch (err) { console.log('[-] Worklight Androidgap WLCertificatePinningPlugin pinner not found'); //console.log(err); } // Netty FingerprintTrustManagerFactory try { var netty_FingerprintTrustManagerFactory = Java.use('io.netty.handler.ssl.util.FingerprintTrustManagerFactory'); //NOTE: sometimes this below implementation could be useful //var netty_FingerprintTrustManagerFactory = Java.use('org.jboss.netty.handler.ssl.util.FingerprintTrustManagerFactory'); netty_FingerprintTrustManagerFactory.checkTrusted.implementation = function (type, chain) { console.log('[+] Bypassing Netty FingerprintTrustManagerFactory'); }; } catch (err) { console.log('[-] Netty FingerprintTrustManagerFactory pinner not found'); //console.log(err); } // Squareup CertificatePinner [OkHTTP < v3] (double bypass) try { var Squareup_CertificatePinner_Activity = Java.use('com.squareup.okhttp.CertificatePinner'); Squareup_CertificatePinner_Activity.check.overload('java.lang.String', 'java.security.cert.Certificate').implementation = function (str1, str2) { console.log('[+] Bypassing Squareup CertificatePinner {1}: ' + str1); return; }; Squareup_CertificatePinner_Activity.check.overload('java.lang.String', 'java.util.List').implementation = function (str1, str2) { console.log('[+] Bypassing Squareup CertificatePinner {2}: ' + str1); return; }; } catch (err) { console.log('[-] Squareup CertificatePinner pinner not found'); //console.log(err); } // Squareup OkHostnameVerifier [OkHTTP v3] (double bypass) try { var Squareup_OkHostnameVerifier_Activity = Java.use('com.squareup.okhttp.internal.tls.OkHostnameVerifier'); Squareup_OkHostnameVerifier_Activity.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function (str1, str2) { console.log('[+] Bypassing Squareup OkHostnameVerifier {1}: ' + str1); return true; }; Squareup_OkHostnameVerifier_Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function (str1, str2) { console.log('[+] Bypassing Squareup OkHostnameVerifier {2}: ' + str1); return true; }; } catch (err) { console.log('[-] Squareup OkHostnameVerifier pinner not found'); //console.log(err); } // Android WebViewClient try { var AndroidWebViewClient_Activity = Java.use('android.webkit.WebViewClient'); AndroidWebViewClient_Activity.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.SslErrorHandler', 'android.net.http.SslError').implementation = function (obj1, obj2, obj3) { console.log('[+] Bypassing Android WebViewClient'); }; } catch (err) { console.log('[-] Android WebViewClient pinner not found'); //console.log(err); } // Apache Cordova WebViewClient try { var CordovaWebViewClient_Activity = Java.use('org.apache.cordova.CordovaWebViewClient'); CordovaWebViewClient_Activity.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.SslErrorHandler', 'android.net.http.SslError').implementation = function (obj1, obj2, obj3) { console.log('[+] Bypassing Apache Cordova WebViewClient'); obj3.proceed(); }; } catch (err) { console.log('[-] Apache Cordova WebViewClient pinner not found'); //console.log(err): } // Boye AbstractVerifier try { var boye_AbstractVerifier = Java.use('ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier'); boye_AbstractVerifier.verify.implementation = function (host, ssl) { console.log('[+] Bypassing Boye AbstractVerifier: ' + host); }; } catch (err) { console.log('[-] Boye AbstractVerifier pinner not found'); //console.log(err): } }); }, 0);
Больше интересных статей на нашем форуме: https://lolz.guru/articles/
Подписывайтесь на канал и делитесь ссылкой на статью с друзьями!