2024年网络安全最全如何解决APP抓包问题【网络安全】_app 防止抓包

openssl genrsa -out key.pem 3072 -nodes
openssl req -new -x509 -key key.pem -sha256 -config openssl.cnf -out cert.pem -days 730 -subj “/C=JP/ST=/L=/O=m4bln/CN=MY CA”
openssl pkcs12 -export -inkey key.pem -in cert.pem -out cert_and_key.pfx
把cert_and_key.pfx导入burp

复制代码


目前还没遇到过这种情况,但是如果遇到了这种问题要知道怎么解决。



> 
> 以上两种方法都是仅依靠了系统校验证书的方式进行抓包,APP在整个请求HTTPS的请求过程时还并未进行证书校验,和在普通的浏览器中访问并无区别,只是要将想要被信任的证书放入系统证书路径内。
> 
> 
> 


### 4.SSLPinning


对于像ttt.com这种自签名的免费证书,不需要CA权威认证的证书,大多数APP开发商都会使用。那么如果在安卓开发的过程中,将证书的验证逻辑放在APP内部,与系统和浏览器毫无相关,这时再想将burp证书导入系统受信任路径下也于事无补了。


APP自己校验证书,分为两种,一种是将验证逻辑也在代码中,一种是写在安卓7.0之后才有的`network-security-config`中。


验证是方式也有两种,一种是验证证书公钥的hash值,一种是直接验证证书的公钥文件。


这种通过APP自身的验证方式就叫做证书绑定(也叫`Certificate Pinning`或`SSL Pinning`)。


那么如何去判断一个APP是否使用了证书绑定呢?首先拿到apk文件,用apktool工具进行反编译,查看敏感文件



apktool d -s <file.apk> -o

复制代码


开发人员经常会将网络配置的相关文件保存到指定位置,如下图就指定在了xml目录下。 ![image.png](https://img-blog.csdnimg.cn/img_convert/1c8ee16ea5fce11819b61a25c027fb53.webp?x-oss-process=image/format,png)


所以在反编译后的res/xml目录下会有一个`network_security_config.xml`文件,打开看到标签,说明使用了证书绑定机制。


![image.png](https://img-blog.csdnimg.cn/img_convert/4cf4eb9cfc5b6b06abd62202348d00f5.webp?x-oss-process=image/format,png)


#### 在配置文件中检验的两种方法



<!--证书校验-->
<domain-config>
    <domain includeSubdomains="true">www.ttt.com</domain>
    <trust-anchors>
        <certificates src="@raw/ttt"/>
    </trust-anchors>
</domain-config>

<!--公钥校验-->
<domain-config cleartextTrafficPermitted="true">
    <domain includeSubdomains="true">ttt.com</domain>
    <!--利用xml校验证书公钥的hash值-->
    <pin-set expiration="2099-01-01"
        tools:ignore="MissingBackupPin">
        <pin digest="SHA-256">7VMdvZE3PGbxb0Pgf1PlCp+MI8KZ2ZC5psM8TIylNDA=</pin>
    </pin-set>
    <!--利用xml校验证书的公钥文件-->
    <trust-anchors>
        <certificates src="@raw/ttt"/>
    </trust-anchors>
</domain-config>

复制代码


这两种校验机制出现一种即可,从代码中可以看出,ttt.com就是安卓自己要校验绑定的域名。


如果只是在这个文件进行校验,有两种解决方案:一是直接将文件中校验的部分或注释掉,再重新打包和签名即可,但是这过程又有些麻烦,并不是上上策,如果遇到了不能重打包的apk就尴尬了。。。二是最常用的也是最好用的frida来hook关键函数进行绕过,后面会讲解。当然有些人会直接在真机或者模拟器上安装xposed模块,但是我个人觉得每次使用都要软重启,可能还会造成卡机,所以感觉还是使用frida最方便。


#### 在代码中检验的两种方法


1.利用代码校验证书的公钥hash



String hostname = “www.ttt.com”;
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(hostname, “sha256/7VMdvZE3PGbxb0Pgf1PlCp+MI8KZ2ZC5psM8TIylNDA=”)
.build();
OkHttpClient client = new OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}).build();

复制代码


2.利用代码校验证书的公钥证书文件



// 获取证书输入流
InputStream openRawResource = getApplicationContext().getResources().openRawResource(R.raw.ttt);
Certificate ca = CertificateFactory.getInstance(“X.509”).generateCertificate(openRawResource);
// 创建 Keystore 包含我们的证书
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry(“ca”, ca);
// 创建一个 TrustManager 仅把 Keystore 中的证书 作为信任的锚点
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); // 建议不要使用自己实现的X509TrustManager,而是使用默认的X509TrustManager
trustManagerFactory.init(keyStore);
// 用 TrustManager 初始化一个 SSLContext
sslContext = SSLContext.getInstance(“TLS”); //定义:public static SSLContext sslContext = null;
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());

OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory(),
(X509TrustManager) trustManagerFactory.getTrustManagers()[0] )
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}).build();

复制代码


通过frida进行hook,这种绕过的脚本也很多,比较熟悉的有JustTrustMe和`DroidSSLUnpinning`,他们的底层原理都是一样的,通过hook关键的验证函数,进行逻辑绕过。


frida的安装过程就不详细讲解了,网上很多教程。这里我使用的是`frida 12.8.0 + frida-tools=5.3.0`


这里我使用的hook.js的脚本如下:



/* Android ssl certificate pinning bypass script for various methods
by Maurizio Siddu modify by Ch3nYe

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 (quadruple bypass) //
/
try {
// Bypass OkHTTPv3 {1}
var okhttp3_Activity_1 = Java.use(‘okhttp3.CertificatePinner’);
okhttp3_Activity_1.check.overload(‘java.lang.String’, ‘java.util.List’).implementation = function (a, b) {
console.log(‘[+] Bypassing OkHTTPv3 {1}: ’ + a);
return true;
};
} catch (err) {
console.log(’[-] OkHTTPv3 {1} pinner not found’);
//console.log(err);
}
try {
// Bypass OkHTTPv3 {2}
// This method of CertificatePinner.check could be found in some old Android app
var okhttp3_Activity_2 = Java.use(‘okhttp3.CertificatePinner’);
okhttp3_Activity_2.check.overload(‘java.lang.String’, ‘java.security.cert.Certificate’).implementation = function (a, b) {
console.log(‘[+] Bypassing OkHTTPv3 {2}: ’ + a);
return true;
};
} catch (err) {
console.log(’[-] OkHTTPv3 {2} pinner not found’);
//console.log(err);
}
try {
// Bypass OkHTTPv3 {3}
var okhttp3_Activity_3 = Java.use(‘okhttp3.CertificatePinner’);
okhttp3_Activity_3.check.overload(‘java.lang.String’, ‘[Ljava.security.cert.Certificate;’).implementation = function (a, b) {
console.log(‘[+] Bypassing OkHTTPv3 {3}: ’ + a);
return true;
};
} catch(err) {
console.log(’[-] OkHTTPv3 {3} pinner not found’);
//console.log(err);
}
try {
// Bypass OkHTTPv3 {4}
var okhttp3_Activity_4 = Java.use(‘okhttp3.CertificatePinner’);
okhttp3_Activity_4[‘’].implementation = function (a, b) {
console.log(‘[+] Bypassing OkHTTPv3 {4}: ’ + a);
};
} catch(err) {
console.log(’[-] OkHTTPv3 {4} pinner not found’);
//console.log(err);
}

// Trustkit (triple bypass) //
//
try {
// Bypass Trustkit {1}
var trustkit_Activity_1 = Java.use(‘com.datatheorem.android.trustkit.pinning.OkHostnameVerifier’);
trustkit_Activity_1.verify.overload(‘java.lang.String’, ‘javax.net.ssl.SSLSession’).implementation = function (a, b) {
console.log(‘[+] Bypassing Trustkit {1}: ’ + a);
return true;
};
} catch (err) {
console.log(’[-] Trustkit {1} pinner not found’);
//console.log(err);
}
try {
// Bypass Trustkit {2}
var trustkit_Activity_2 = Java.use(‘com.datatheorem.android.trustkit.pinning.OkHostnameVerifier’);
trustkit_Activity_2.verify.overload(‘java.lang.String’, ‘java.security.cert.X509Certificate’).implementation = function (a, b) {
console.log(‘[+] Bypassing Trustkit {2}: ’ + a);
return true;
};
} catch (err) {
console.log(’[-] Trustkit {2} pinner not found’);
//console.log(err);
}
try {
// Bypass Trustkit {3}
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 {3} 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 (a, b) {
console.log(‘[+] Bypassing OpenSSLEngineSocketImpl Conscrypt: ’ + b);
};
} 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 (a, b, c) {
console.log(‘[+] Bypassing PhoneGap sslCertificateChecker: ’ + a);
return true;
};
} catch (err) {
console.log(’[-] PhoneGap sslCertificateChecker pinner not found’);
//console.log(err);
}

// IBM MobileFirst pinTrustedCertificatePublicKey (double bypass) //

try {
// Bypass IBM MobileFirst {1}
var WLClient_Activity_1 = Java.use(‘com.worklight.wlclient.api.WLClient’);
WLClient_Activity_1.getInstance().pinTrustedCertificatePublicKey.overload(‘java.lang.String’).implementation = function (cert) {
console.log(‘[+] Bypassing IBM MobileFirst pinTrustedCertificatePublicKey {1}: ’ + cert);
return;
};
} catch (err) {
console.log(’[-] IBM MobileFirst pinTrustedCertificatePublicKey {1} pinner not found’);
//console.log(err);
}
try {
// Bypass IBM MobileFirst {2}
var WLClient_Activity_2 = Java.use(‘com.worklight.wlclient.api.WLClient’);
WLClient_Activity_2.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 {2} pinner not found’);
//console.log(err);
}

// IBM WorkLight (ancestor of MobileFirst) HostNameVerifierWithCertificatePinning (quadruple bypass) //
///
try {
// Bypass IBM WorkLight {1}
var worklight_Activity_1 = Java.use(‘com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning’);
worklight_Activity_1.verify.overload(‘java.lang.String’, ‘javax.net.ssl.SSLSocket’).implementation = function (a, b) {
console.log(‘[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {1}: ’ + a);
return;
};
} catch (err) {
console.log(’[-] IBM WorkLight HostNameVerifierWithCertificatePinning {1} pinner not found’);
//console.log(err);
}
try {
// Bypass IBM WorkLight {2}
var worklight_Activity_2 = Java.use(‘com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning’);
worklight_Activity_2.verify.overload(‘java.lang.String’, ‘java.security.cert.X509Certificate’).implementation = function (a, b) {
console.log(‘[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {2}: ’ + a);
return;
};
} catch (err) {
console.log(’[-] IBM WorkLight HostNameVerifierWithCertificatePinning {2} pinner not found’);
//console.log(err);
}
try {
// Bypass IBM WorkLight {3}
var worklight_Activity_3 = Java.use(‘com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning’);
worklight_Activity_3.verify.overload(‘java.lang.String’, ‘[Ljava.lang.String;’, ‘[Ljava.lang.String;’).implementation = function (a, b) {
console.log(‘[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {3}: ’ + a);
return;
};
} catch (err) {
console.log(’[-] IBM WorkLight HostNameVerifierWithCertificatePinning {3} pinner not found’);
//console.log(err);
}
try {
// Bypass IBM WorkLight {4}
var worklight_Activity_4 = Java.use(‘com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning’);
worklight_Activity_4.verify.overload(‘java.lang.String’, ‘javax.net.ssl.SSLSession’).implementation = function (a, b) {
console.log(‘[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {4}: ’ + a);
return true;
};
} catch (err) {
console.log(’[-] IBM WorkLight HostNameVerifierWithCertificatePinning {4} 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 (a, b) {
console.log(‘[+] Bypassing Conscrypt CertPinManager: ’ + a);
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 (a, b) {
console.log(‘[+] Bypassing CWAC-Netsecurity CertPinManager: ’ + a);
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 (a, b, c) {
console.log(‘[+] Bypassing Worklight Androidgap WLCertificatePinningPlugin: ’ + a);
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 {
// Bypass Squareup CertificatePinner {1}
var Squareup_CertificatePinner_Activity_1 = Java.use(‘com.squareup.okhttp.CertificatePinner’);
Squareup_CertificatePinner_Activity_1.check.overload(‘java.lang.String’, ‘java.security.cert.Certificate’).implementation = function (a, b) {
console.log(‘[+] Bypassing Squareup CertificatePinner {1}: ’ + a);
return;
};
} catch (err) {
console.log(’[-] Squareup CertificatePinner {1} pinner not found’);
//console.log(err);
}
try {
// Bypass Squareup CertificatePinner {2}
var Squareup_CertificatePinner_Activity_2 = Java.use(‘com.squareup.okhttp.CertificatePinner’);
Squareup_CertificatePinner_Activity_2.check.overload(‘java.lang.String’, ‘java.util.List’).implementation = function (a, b) {
console.log(‘[+] Bypassing Squareup CertificatePinner {2}: ’ + a);
return;
};
} catch (err) {
console.log(’[-] Squareup CertificatePinner {2} pinner not found’);
//console.log(err);
}

// Squareup OkHostnameVerifier [OkHTTP v3] (double bypass) //
/
try {
// Bypass Squareup OkHostnameVerifier {1}
var Squareup_OkHostnameVerifier_Activity_1 = Java.use(‘com.squareup.okhttp.internal.tls.OkHostnameVerifier’);
Squareup_OkHostnameVerifier_Activity_1.verify.overload(‘java.lang.String’, ‘java.security.cert.X509Certificate’).implementation = function (a, b) {
console.log(‘[+] Bypassing Squareup OkHostnameVerifier {1}: ’ + a);
return true;
};
} catch (err) {
console.log(’[-] Squareup OkHostnameVerifier pinner not found’);
//console.log(err);
}
try {
// Bypass Squareup OkHostnameVerifier {2}
var Squareup_OkHostnameVerifier_Activity_2 = Java.use(‘com.squareup.okhttp.internal.tls.OkHostnameVerifier’);
Squareup_OkHostnameVerifier_Activity_2.verify.overload(‘java.lang.String’, ‘javax.net.ssl.SSLSession’).implementation = function (a, b) {
console.log(‘[+] Bypassing Squareup OkHostnameVerifier {2}: ’ + a);
return true;
};
} catch (err) {
console.log(’[-] Squareup OkHostnameVerifier pinner not found’);
//console.log(err);
}

// Android WebViewClient (double bypass) //
///
try {
// Bypass WebViewClient {1} (deprecated from Android 6)
var AndroidWebViewClient_Activity_1 = Java.use(‘android.webkit.WebViewClient’);
AndroidWebViewClient_Activity_1.onReceivedSslError.overload(‘android.webkit.WebView’, ‘android.webkit.SslErrorHandler’, ‘android.net.http.SslError’).implementation = function (obj1, obj2, obj3) {
console.log(‘[+] Bypassing Android WebViewClient {1}’);
};
} catch (err) {
console.log(‘[-] Android WebViewClient {1} pinner not found’);
//console.log(err)
}
try {
// Bypass WebViewClient {2}
var AndroidWebViewClient_Activity_2 = Java.use(‘android.webkit.WebViewClient’);
AndroidWebViewClient_Activity_2.onReceivedSslError.overload(‘android.webkit.WebView’, ‘android.webkit.WebResourceRequest’, ‘android.webkit.WebResourceError’).implementation = function (obj1, obj2, obj3) {
console.log(‘[+] Bypassing Android WebViewClient {2}’);
};
} catch (err) {
console.log(‘[-] Android WebViewClient {2} 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);

复制代码


启动frida进行hook指定APP的包名



frida -U -f com.example.safehttps -l hook.js --no-pause

复制代码


![image.png](https://img-blog.csdnimg.cn/img_convert/7d1a316e9a051a8d1fb5b92c449d1bb0.webp?x-oss-process=image/format,png)


可以看到开启burp抓包成功。


### 5.开启双向校验


双向校验顾名思义也就是服务器也要对客户端进行证书校验,在刚才客户端校验服务端的基础上添加一直被校验的逻辑在里面。


首先ttt.com所在的nginx服务器要开启双向认证 ![image.png](https://img-blog.csdnimg.cn/img_convert/f07c15486e0b4b176fda65eb56eb4832.webp?x-oss-process=image/format,png)


开启客户端的校验后,在浏览器进行访问,会发现返回400,没有被请求的SSL证书发送,是因为浏览器正常请求不会携带证书信息去请求ttt.com ![image.png](https://img-blog.csdnimg.cn/img_convert/10255f0bf793b79dda629156743fe904.webp?x-oss-process=image/format,png)


那么如何携带客户端的证书,就要利用burp来操作,将ttt.com的证书添加到TLS客户证书 ![image.png](https://img-blog.csdnimg.cn/img_convert/733c600c418a383fde47b42d246b2749.webp?x-oss-process=image/format,png)


这时再访问 ![image.png](https://img-blog.csdnimg.cn/img_convert/42e044b1f66c4ec331f5d7cc91fae961.webp?x-oss-process=image/format,png)


在APP中进行绑定客户端的证书文件,一般是p12格式文件,会放在assets目录下或者raw目录下,client.p12会有一个密钥内置在代码中,需要找到才能添加进burp中。 ![image.png](https://img-blog.csdnimg.cn/img_convert/569a6427484aa91bd6f4d70876e8f284.webp?x-oss-process=image/format,png)


这个在反编译后的目录下也能找到,通常在assets或者res/raw目录下查找,但是再导入burp这一步是需要证书密码的,比如上图能明显看到密码是123456,但是找不到证书密码怎么办,可以看一下目录下是否存在lib文件夹,如果存在的话极大可能是将密码写进so层了,这就需要你会IDA反汇编获取证书密钥了,这部分在此不详细阐述,感兴趣的朋友可以先去研究一下。 ![image.png](https://img-blog.csdnimg.cn/img_convert/e52377fdc623630c450b501454dafae3.webp?x-oss-process=image/format,png)


#### APP双向校验验证


服务器校验客户端的证书ClientSSLSocketFactory,服务端将客户端的证书进行绑定。



TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException(“Unexpected default trust managers:” + Arrays.toString(trustManagers));
}
trustManager = (X509TrustManager) trustManagers[0];

OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(Objects.requireNonNull(ClientSSLSocketFactory.getSocketFactory(getApplicationContext())), Objects.requireNonNull(trustManager))
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
//强行返回true 即验证成功
return true;
}
}).build();

复制代码



public class ClientSSLSocketFactory {
private static final String KEY_STORE_PASSWORD = “123456”; // 证书密码
private static InputStream client_input;

public static SSLSocketFactory getSocketFactory(Context context) {
    try {
        //客户端证书
        client_input = context.getResources().getAssets().open("client.p12");
        SSLContext sslContext = SSLContext.getInstance("TLS");
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(client_input, KEY_STORE_PASSWORD.toCharArray());
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, KEY_STORE_PASSWORD.toCharArray());
        sslContext.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
        return sslContext.getSocketFactory();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            client_input.close();
        } catch (IOException e) {
            e.printStackTrace();

还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!

王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。

对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!

【完整版领取方式在文末!!】

93道网络安全面试题

内容实在太多,不一一截图了

黑客学习资源推荐

最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

😝朋友们如果有需要的话,可以联系领取~

1️⃣零基础入门
① 学习路线

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

image

② 路线对应学习视频

同时每个成长路线对应的板块都有配套的视频提供:

image-20231025112050764

2️⃣视频配套工具&国内外网安书籍、文档
① 工具

② 视频

image1

③ 书籍

image2

资源较为敏感,未展示全面,需要的最下面获取

在这里插入图片描述在这里插入图片描述

② 简历模板

在这里插入图片描述

因篇幅有限,资料较为敏感仅展示部分资料,添加上方即可获取👆

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 16
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值