绕过WebView SSL Pinning抓https数据
2022-7-15 00:14:55 Author: 哆啦安全(查看原文) 阅读量:55 收藏

0x01 前言

Android 中的证书固定,Android WebView 中证书锁定,在Android 7.0 Nougat (SDK 24)开始才有的,在 Android 7.0 Nougat (SDK 24)之前,无论开发人员使用什么库,都无法真正管理 Webview 上的固定,因为Android 7.0 Nougat (SDK 24)的网络安全配置允许应用程序定义自己的规则集。

为了不让攻击者抓到数据包货执行中间人攻击,开发人员使用了WebView SSLPinning,如果我们想成功地对固定的证书域执行中间人攻击,就必须获得实际证书或能够生成有效证书(来自受信任的证书颁发机构)

1.1 WebView 忽略证书验证

1.1.1 Okhttp3忽略HTTPS证书校验

import java.security.SecureRandom;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class SSLSocketClient {

public static SSLSocketFactory getSSLSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, getTrustManager(), new SecureRandom());
return sslContext.getSocketFactory();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private static TrustManager[] getTrustManager() {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}

@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}

@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
};
return trustAllCerts;
}

public static HostnameVerifier getHostnameVerifier() {
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
};
return hostnameVerifier;
}
}

sClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.sslSocketFactory(SSLSocketClient.getSSLSocketFactory())
.hostnameVerifier(SSLSocketClient.getHostnameVerifier())
.build();

1.1.2 WebView忽略HTTPS证书校验

Android WebView组件加载网页发生证书认证错误时,会调用WebViewClient类的onReceivedSslError方法,如果该方法实现调用了handler.proceed()来忽略该证书错误,则会受到中间人攻击的威胁,可能导致隐私泄露

httptest APP中,WebView忽略了SSL证书错误,可能引起中间人攻击

/*
* https协议
* WebView 不进行证书校验
*/

button_webview_ssl_without_ca.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyWebViewClient mWebViewClient = new MyWebViewClient();
mWebViewClient.setCheckflag("trustAllCerts");
mWebview.setWebViewClient(mWebViewClient);
mWebview.loadUrl("https://www.baidu.com/?q=WebView_without_CAcheck");
}
});

WebView直接调用onReceivedSslError方法时,直接执行handler.proceed()来忽略该证书错误,setWebViewClient() 实现方法如下:

wv.setWebViewClient(new WebViewClient() {
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();//忽略证书错误继续加载页面
}
});

客户端访问使用Https协议加密的url时,如果服务器证书校验错误,客户端应该拒绝继续加载页面

在使用WebView进行HTTPS请求时,同样可以对HTTPS证书进行校验,WebView控件对请求逻辑进行了封装,所以进行证书校验更加方便,具体代码如下所示,handler.cancel()相当于使用系统证书校验::

private class MyWebViewClient extends WebViewClient {
private String checkflag="checkCerts"; // 是否忽略证书校验

public void setCheckflag(String checkflag) {
this.checkflag = checkflag;
}

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
if("trustAllCerts".equals(checkflag)){//忽略证书校验
handler.proceed();
}else {
handler.cancel();
Toast.makeText(MainActivity.this, "证书异常,停止访问", Toast.LENGTH_SHORT).show();
}
}
}

打开Burp,并在Android 设备中配置好代理,然后打开APP后点击【WEBVIEW SSL(忽略证书校验)】按钮,APP成功访问,并在界面显示百度的一个gif图片,Burp也成功抓到信息,如下:

1.2 WebView 系统证书校验

WebView没有自定义SSL Pinning的实现方法,只能通过network_security_config.xml配置证书绑定

/*
* https协议
* WebView 使用系统证书校验
* 默认证书链校验,只信任系统CA(根证书)
*
* tips: OKHTTP默认的https请求使用系统CA验证服务端证书(Android7.0以下还信任用户证书,Android7.0开始默认只信任系统证书)
*/

button_webview_ssl_with_system_ca.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyWebViewClient mWebViewClient = new MyWebViewClient();
mWebViewClient.setCheckflag("checkCerts");
mWebview.setWebViewClient(mWebViewClient);
mWebview.loadUrl("https://www.baidu.com/?q=WebView_with_SystemCAcheck");
}
});

绕过WebView 系统证书校验的方法,跟绕过HTTPS 系统证书校验的方法一样,只需要将抓包工具的证书安装到系统信任库里面即可正常抓包或反编译APK在<app>\res\xml\network_security_config.xml<app>\AndroidManifest.xml中添加如下信息后重打包APK并签名就能抓到数据:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config>
<trust-anchors>
<!-- 信任系统预置CA 证书 -->
<certificates src="system" />
<!-- 信任用户添加的 CA 证书,Charles 和 Fiddler 抓包工具安装的证书属于此类 -->
<certificates src="user" />
</trust-anchors>
</base-config>
</network-security-config>

AndroidManifest.xml:

<application  android:networkSecurityConfig="@xml/network_security_config">

:在Android 7.0以前,应用默认会信任系统证书和用户证书,Android 7.0开始,默认只信任系统证书,在root环境下,将证书导入系统目录的方法。只要想办法把证书弄到系统证书列表,就可以抓包解密明文数据,具体的证书安装到系统证书目录的方法,如下:

目前在Android 7.0或以上的系统有启用了对第三方证书的限制,但在Android 7.0以下依旧可以将Fiddler/Charles/Burp的证书安装在用户的CA集中抓取https请求

将Burp或者Charles的证书作为系统级别的信任证书安装。建议重新生产burp证书并重启burp后再导出。系统级别的受信任证书以特殊格式存储在/system/etc/security/cacerts文件夹中。我们可以将Burp的证书写入此位置。

导出一个Burp/Charles证书之后,adb push到模拟器,然后修改后缀为crt直接安全,这种方式在Android 6及之前的版本可用,从Android 7.0开始,Android更改了信任用户安装的证书的默认行为,应用程序仅信任系统级CA。这样就导致安装证书后,如果尝试通过Burp或者Charlse代理访问https网站,系统会提示“该证书并非来自可信的授权中心”

对于Android 7.0 (API 24) 之后,做了些改动,使得系统安全性增加了,导致:

  • APP 默认不信任用户域的证书

    • 之前把抓包工具的ssl证书,通过【从SD卡安装】安装到受信任的凭据 -> 用户。就没用了,因为不再受信任了

    • 只信任(安装到)系统域的证书

    • 导致无法抓包https,抓出来的https的请求,都是加了密的,无法看到原文了

对此,总结出相关解决思路和方案:

  • 让系统信任抓包工具的ssl证书

    • 作为app的开发者自己:改自己的app的配置,允许https抓包(得到或本身有app的源码,把证书放到受系统信任的系统证书中去)

    • 把证书放到受系统信任的系统证书中去(root权限)

  • 绕开https不去校验

    • 借助于其他(JustTrustMe等)工具绕开https的校验(例如XPosed、太极XPosed等框架)

1) Android 7抓包问题解决方法

  1. 导出Burp的证书后,使用openssl来做一些改动,最后上传到/system/etc/security/cacerts


[email protected]:~# openssl x509 -inform DER -in cert-der.crt -out PortSwiggerCA.pem
[email protected]:~# openssl x509 -inform PEM -subject_hash_old -in PortSwiggerCA.pem|head -1
[email protected]:~# mv PortSwiggerCA.pem 9999.0
  1. adb传输文件报错couldn‘t create file:Read-only file system解决方法

D:\>adb shell
VOG-AL00:/ # mount -o remount -o rw /system
mount -o remount -o rw /system
VOG-AL00:/ # exit;
exit;

D:\>adb root
adbd is already running as root

D:\>adb remount
remount succeeded

D:\>adb push 9999.0 /system/etc/security/cacerts
330 KB/s (1330 bytes in 0.003s)

D:\>adb shell chmod 644 /system/etc/security/cacerts/9999.0

再次输入adb push就能正常传输文件

2)Android10 抓包问题解决方法

安卓 10 采用了的安全策略-将系统分区 /system 挂载为只读,因此Android10以上需要刷入Magisk,在模块里搜索move Cert(MagiskTrustUserCerts) 安装模块,重启后证书就已经被移动到系统目录(system/etc/security/cacerts),可以正常抓包了

Magisk下载地址:https://github.com/topjohnwu/Magisk
MagiskTrustUserCerts下载地址:https://github.com/NVISOsecurity/MagiskTrustUserCerts

2.1 绕过WebView证书文件校验

/*
* https协议 SSL Pinning WebView
* 通过network_security_config.xml中定义的证书和密钥进行绑定
*/

button_webview_ssl_pinning.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyWebViewClient mWebViewClient = new MyWebViewClient();
mWebViewClient.setCheckflag("checkCerts");
mWebview.setWebViewClient(mWebViewClient);
mWebview.loadUrl("https://www.sogou.com/web?query=WebView_SSLPinningXML"); // 证书文件校验
}
});

:【确定样本APK中编译好的证书是否同学你在使用的时候失效了,建议自行使用下面的方法自行编译】此处的本地证书要替换一下为最新的,下载官网最新的sogou.pem然后在/替换掉/res/raw/目录下的sogou.pem文件

openssl s_client -connect sogou.com:443 -servername sogou.com | openssl x509 -out sogou.pem


network_security_config.xml配置的WebView的证书文件校验和公钥校验内容:

正常访问不挂代理,内容如下:

挂代理访问,内容如下:

绕过方式:利用Android 特性绕过,使用Frida

JS脚本:

Java.perform(function() {
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);
}

});

2.2 绕过WebView证书公钥校验

/*
* https协议 SSL Pinning WebView
* 通过network_security_config.xml中定义的证书和密钥进行绑定
*/

button_webview_ssl_pinning.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyWebViewClient mWebViewClient = new MyWebViewClient();
mWebViewClient.setCheckflag("checkCerts");
mWebview.setWebViewClient(mWebViewClient);
mWebview.loadUrl("https://www.sogou.com/web?query=WebView_SSLPinningXML"); // 证书文件校验
// mWebview.loadUrl("https://www.zhihu.com/"); // 证书公钥校验
}
});

:【确定样本APK中编译好的证书是否同学你在使用的时候失效了,建议自行使用下面的方法自行编译】此处证书公钥要替换一下

openssl s_client -connect zhihu.com:443 -servername zhihu.com | openssl x509 -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

正常访问不挂代理,内容如下:

挂代理访问,内容如下:

绕过方式:利用Android 特性绕过,使用Frida

JS脚本:

Java.perform(function() {
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);
}

});

当然,也可以通过res/xml/network_security_config.xml配置文件对服务端证书进行校验,例如针对证书校验,反编译APK将对应的证书替换为Burp的即可绕过;公钥校验的同理

CSDN原文地址https://orangey.blog.csdn.net/article/details/124755818

参考链接

https://www.cnblogs.com/Potato-Eater/p/9792725.html

https://ch3nye.top/Android-HTTPS认证的N种方式和对抗方法总结/

推荐阅读

Web安全零基础速成培训班

Android APP开发零基础速成培训班

Android APP逆向分析零基础速成培训班

Android10系统定制之frida逆向分析速成培训班

零基础学编程/零基础学安全/零基础学逆向实战速成培训班


文章来源: http://mp.weixin.qq.com/s?__biz=Mzg2NzUzNzk1Mw==&mid=2247493089&idx=2&sn=1a4b63527d5eea18820ea4bcac9780d1&chksm=ceb8a0aff9cf29b9d8264c9e5c6ce1c54e8759e90dca866ba5ff84b13e4d0153cf315611fa9e#rd
如有侵权请联系:admin#unsafe.sh