MASTG-TECH-0012: 绕过证书绑定
一些应用程序会实施 SSL 绑定,这会阻止应用程序接受您的拦截证书作为有效证书。这意味着您将无法监控应用程序和服务器之间的流量。
对于大多数应用程序,可以在几秒钟内绕过证书绑定,但前提是该应用程序使用了这些工具涵盖的 API 函数。如果应用程序使用自定义框架或库实施 SSL 绑定,则必须手动修补和停用 SSL 绑定,这可能非常耗时。
本节介绍绕过 SSL 绑定的各种方法,并提供有关在现有工具无法提供帮助时应采取措施的指导。
绕过方法¶
根据设备上可用的框架,有几种方法可以绕过黑盒测试的证书绑定
- Frida:使用 frida-multiple-unpinning
- Objection:使用
android sslpinning disable
命令。 - Xposed:安装TrustMeAlready或 SSLUnpinning 模块。
如果您有安装了 frida-server 的 root 设备,您可以通过运行以下 objection 命令来绕过 SSL 绑定(如果您使用的是非 root 设备,请参阅 重新打包应用程序)
android sslpinning disable
以下是输出示例
另请参阅Objection 的 Android SSL 绑定禁用帮助,以获取更多信息,并检查pinning.ts文件以了解绕过的工作原理。
请注意,来自 Frida CodeShare的 frida-multiple-unpinning 脚本比 Objection 脚本涵盖更多场景。
静态绕过自定义证书绑定¶
在应用程序的某个位置,必须定义端点和证书(或其哈希)。在反编译应用程序后,您可以搜索
- 证书哈希:
grep -ri "sha256\|sha1" ./smali
。将识别的哈希替换为您的代理 CA 的哈希。或者,如果哈希伴随域名,您可以尝试将域名修改为不存在的域名,以便不绑定原始域名。这在混淆的 OkHTTP 实现上效果很好。 - 证书文件:
find ./assets -type f \( -iname \*.cer -o -iname \*.crt \)
。将这些文件替换为您的代理证书,确保它们格式正确。 - 信任存储文件:
find ./ -type f \( -iname \*.jks -o -iname \*.bks \)
。将您的代理证书添加到信任存储,并确保它们格式正确。
请记住,应用程序可能包含没有扩展名的文件。最常见的文件位置是
assets
和res
目录,也应该进行调查。
例如,假设您找到一个使用 BKS(BouncyCastle)信任存储的应用程序,并且它存储在文件 res/raw/truststore.bks
中。要绕过 SSL 绑定,您需要使用命令行工具 keytool
将您的代理证书添加到信任存储。Keytool
随 Java SDK 一起提供,以下值是执行命令所需的
- password - 密钥库的密码。在反编译的应用程序代码中查找硬编码的密码。
- providerpath - BouncyCastle Provider jar 文件的位置。您可以从Bouncy Castle 军团下载它。
- proxy.cer - 您的代理证书。
- aliascert - 将用作您的代理证书别名的唯一值。
要添加您的代理证书,请使用以下命令
keytool -importcert -v -trustcacerts -file proxy.cer -alias aliascert -keystore "res/raw/truststore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "providerpath/bcprov-jdk15on-164.jar" -storetype BKS -storepass password
要列出 BKS 信任存储中的证书,请使用以下命令
keytool -list -keystore "res/raw/truststore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "providerpath/bcprov-jdk15on-164.jar" -storetype BKS -storepass password
进行这些修改后,使用 apktool 重新打包应用程序并将其安装在您的设备上。
如果应用程序使用本机库来实现网络通信,则需要进一步的逆向工程。在博客文章识别 smali 代码中的 SSL 绑定逻辑,对其进行修补,然后重新组装 APK中可以找到此类方法的示例
动态绕过自定义证书绑定¶
动态绕过绑定逻辑使其更方便,因为无需绕过任何完整性检查,并且执行试错尝试的速度要快得多。
找到正确的挂钩方法通常是最困难的部分,并且可能需要相当长的时间,具体取决于混淆程度。由于开发人员通常会重复使用现有的库,因此搜索识别所用库的字符串和许可证文件是一个好方法。识别出库后,检查未混淆的源代码,以找到适合动态检测的方法。
例如,假设您找到一个使用混淆的 OkHTTP3 库的应用程序。文档显示 CertificatePinner.Builder
类负责为特定域添加 pin。如果您可以修改 Builder.add 方法的参数,您可以将哈希更改为属于您的证书的正确哈希。如Jeroen Beckers 的这篇博客文章中所述,可以通过两种方式找到正确的方法
- 如上一节所述,搜索哈希和域名。实际的绑定方法通常将在这些字符串附近使用或定义
- 在 SMALI 代码中搜索方法签名
对于 Builder.add 方法,您可以通过运行以下 grep 命令找到可能的方法:grep -ri java/lang/String;\[Ljava/lang/String;)L ./
此命令将搜索所有将字符串和字符串的可变列表作为参数的方法,并返回一个复杂的对象。根据应用程序的大小,这可能在代码中有一个或多个匹配项。
使用 Frida 挂钩每种方法并打印参数。其中一种将打印出域名和证书哈希,之后您可以修改参数以规避已实施的绑定。