MASTG-TECH-0011: 设置拦截代理
一些工具支持依赖于 HTTP(S) 协议的应用的网络分析。最重要的工具是所谓的拦截代理; ZAP 和 Burp Suite 是最著名的。拦截代理使测试人员能够处于 中间人 (MITM) 位置。这个位置可用于读取和/或修改所有应用请求和端点响应,这些请求和响应用于测试授权、会话、管理等。
虚拟设备的拦截代理¶
在 Android 虚拟设备 (AVD) 上设置 Web 代理¶
以下过程适用于 Android Studio 3.x 附带的 Android 模拟器,用于在模拟器上设置 HTTP 代理
- 设置您的代理以侦听 localhost 和例如端口 8080。
-
在模拟器设置中配置 HTTP 代理
- 单击模拟器菜单栏中的三个点
- 打开设置菜单
- 单击代理选项卡
- 选择手动代理配置
- 在主机名字段中输入“127.0.0.1”,并在端口号字段中输入您的代理端口(例如,“8080”)
- 点击应用
HTTP 和 HTTPS 请求现在应通过主机上的代理进行路由。如果不是,请尝试关闭并重新打开飞行模式。
还可以通过使用 模拟器命令在命令行上配置 AVD 的代理来启动 AVD。以下示例启动 AVD Nexus_5X_API_23 并将代理设置为 127.0.0.1 和端口 8080。
emulator @Nexus_5X_API_23 -http-proxy 127.0.0.1:8080
在虚拟设备上安装 CA 证书¶
安装 CA 证书的简单方法是将证书推送到设备,并通过安全设置将其添加到证书存储中。例如,您可以按如下方式安装 PortSwigger (Burp) CA 证书
- 启动 Burp 并使用主机上的 Web 浏览器导航到 burp/,然后单击“CA 证书”按钮下载
cacert.der
。 - 将文件扩展名从
.der
更改为.cer
。 -
将文件推送到模拟器
adb push cacert.cer /sdcard/
-
导航到设置 -> 安全 -> 从 SD 卡安装。
- 向下滚动并点击
cacert.cer
。
然后,系统应提示您确认证书的安装(如果您尚未设置设备 PIN,系统还会要求您设置)。
这会将证书安装在用户证书存储中(已在 Genymotion VM 上测试)。为了将证书放置在根存储中,您可以执行以下步骤
- 使用
adb root
和adb shell
以 root 身份运行 adb。 - 在
/data/misc/user/0/cacerts-added/
中找到新安装的证书。 - 将证书复制到以下文件夹
/system/etc/security/cacerts/
。 - 重新启动 Android VM。
对于 Android 7.0(API 级别 24)及更高版本,请按照“绕过网络安全配置”部分中描述的相同过程操作。
物理设备的拦截代理¶
必须首先评估可用的网络设置选项。用于测试的移动设备和运行拦截代理的主机必须连接到同一 Wi-Fi 网络。使用(现有)接入点或创建 ad-hoc 无线网络。
配置网络并建立测试主机和移动设备之间的连接后,还需要执行几个步骤。
- 必须配置代理以指向拦截代理。
- 必须将拦截代理的 CA 证书添加到 Android 设备证书存储中的可信证书。用于存储 CA 证书的菜单位置可能取决于 Android 版本和 Android OEM 对设置菜单的修改。
- 如果叶证书的有效期恰好超过一定时间(Chrome 中为 39 个月),则某些应用程序(例如 Chrome 浏览器)可能会显示
NET::ERR_CERT_VALIDITY_TOO_LONG
错误。如果使用默认的 Burp CA 证书,则会发生这种情况,因为 Burp Suite 颁发叶证书的有效期与其 CA 证书的有效期相同。您可以通过创建自己的 CA 证书并将其导入 Burp Suite 来规避此问题,如本博客文章中所述。
完成这些步骤并启动应用后,请求应会显示在拦截代理中。
有关使用 Android 设备设置 ZAP 的视频可以在 secure.force.com 上找到。
其他一些差异:从 Android 8.0(API 级别 26)开始,当 HTTPS 流量通过另一个连接隧道传输时,应用的*网络行为*会发生变化。从 Android 9(API 级别 28)开始,SSLSocket 和 SSLEngine 在握手期间出现问题时的错误处理方式会略有不同。
如前所述,从 Android 7.0(API 级别 24)开始,默认情况下 Android OS 将不再信任用户 CA 证书,除非在应用程序中指定。在以下部分中,我们将解释绕过此 Android 安全控制的两种方法。
绕过网络安全配置¶
在本节中,我们将介绍几种绕过 Android 网络安全配置的方法。
向网络安全配置添加自定义用户证书¶
网络安全配置有不同的配置可用,可以通过 src 属性添加非系统证书颁发机构
<certificates src=["system" | "user" | "raw resource"]
overridePins=["true" | "false"] />
每个证书可以是以下之一
"raw resource"
是指向包含 X.509 证书的文件的 ID"system"
用于预安装的系统 CA 证书"user"
用于用户添加的 CA 证书
应用信任的 CA 证书可以是系统信任的 CA 证书,也可以是用户 CA 证书。通常,您已经将拦截代理的证书作为 Android 中的其他 CA 添加。因此,我们将重点关注“用户”设置,该设置允许您强制 Android 应用信任以下网络安全配置的证书
<network-security-config>
<base-config>
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</base-config>
</network-security-config>
要实现此新设置,您必须按照以下步骤操作
-
使用 apktool 等反编译工具反编译应用
apktool d <filename>.apk
-
通过创建一个包含
<certificates src="user" />
的网络安全配置来使应用程序信任用户证书,如上所述 -
进入 apktool 在反编译应用时创建的目录,然后使用 apktool 重新构建应用。新 apk 将位于
dist
目录中。apktool b
-
您需要重新打包应用,如“ 重新打包应用”中所述。有关重新打包过程的更多详细信息,您还可以查阅Android 开发者文档,其中对整个过程进行了说明。
请注意,即使此方法非常简单,但其主要缺点是您必须对要评估的每个应用程序应用此操作,这会增加测试的开销。
请记住,如果您正在测试的应用具有额外的强化措施,例如应用签名验证,您可能无法再启动该应用。作为重新打包的一部分,您将使用自己的密钥对应用进行签名,因此签名更改将导致触发此类检查,这可能会导致应用立即终止。您需要通过在重新打包应用或通过 Frida 进行动态检测期间修补这些检查来识别并禁用这些检查。
有一个 python 脚本可用于自动化上述步骤,称为 Android-CertKiller。此 Python 脚本可以从已安装的 Android 应用中提取 APK,对其进行反编译,使其可调试,添加一个新的网络安全配置(允许用户证书),构建和签名新的 APK,并安装带有 SSL 旁路的新 APK。
python main.py -w
***************************************
Android CertKiller (v0.1)
***************************************
CertKiller Wizard Mode
---------------------------------
List of devices attached
4200dc72f27bc44d device
---------------------------------
Enter Application Package Name: nsc.android.mstg.owasp.org.android_nsc
Package: /data/app/nsc.android.mstg.owasp.org.android_nsc-1/base.apk
I. Initiating APK extraction from device
complete
------------------------------
I. Decompiling
complete
------------------------------
I. Applying SSL bypass
complete
------------------------------
I. Building New APK
complete
------------------------------
I. Signing APK
complete
------------------------------
Would you like to install the APK on your device(y/N): y
------------------------------------
Installing Unpinned APK
------------------------------
Finished
使用 Magisk 将代理证书添加到系统信任的 CA 中¶
为了避免为每个应用程序配置网络安全配置的义务,我们必须强制设备接受代理的证书作为系统信任的证书之一。
有一个 Magisk 模块会自动将所有用户安装的 CA 证书添加到系统信任的 CA 列表中。
在 Github 发布页面下载该模块的最新版本,将下载的文件推送到设备,并通过单击 +
按钮将其导入 Magisk Manager 的“模块”视图。最后,Magisk Manager 需要重新启动才能使更改生效。
从现在开始,用户通过“设置”、“安全和位置”、“加密和凭据”、“从存储安装”安装的任何 CA 证书(位置可能不同)都会通过此 Magisk 模块自动推送到系统的信任存储中。重新启动并验证 CA 证书是否列在“设置”、“安全和位置”、“加密和凭据”、“受信任的凭据”(位置可能不同)中。
手动将代理证书添加到系统信任的 CA 中¶
或者,您可以手动按照以下步骤操作以实现相同的结果
- 使 /system 分区可写,这只有在 root 设备上才有可能。运行“mount”命令以确保 /system 可写:
mount -o rw,remount /system
。如果此命令失败,请尝试运行以下命令mount -o rw,remount -t ext4 /system
-
准备代理的 CA 证书以匹配系统证书格式。以
der
格式导出代理的证书(这是 Burp Suite 中的默认格式),然后运行以下命令$ openssl x509 -inform DER -in cacert.der -out cacert.pem $ openssl x509 -inform PEM -subject_hash_old -in cacert.pem | head -1 mv cacert.pem <hash>.0
-
最后,将
<hash>.0
文件复制到目录 /system/etc/security/cacerts,然后运行以下命令chmod 644 <hash>.0
通过按照上述步骤操作,您可以允许任何应用程序信任代理的证书,这使您可以拦截其流量,除非应用程序使用 SSL 证书锁定。
潜在障碍¶
应用程序通常会实施一些安全控制措施,这使得对应用程序执行安全审查变得更加困难,例如 root 检测和证书锁定。理想情况下,您应该同时获取一个启用了这些控制措施的应用程序版本和一个禁用了这些控制措施的版本。这使您可以分析控制措施的正确实施,然后您可以继续使用不太安全的版本进行进一步测试。
当然,这并不总是可行的,您可能需要在启用了所有安全控制措施的应用程序上执行黑盒评估。以下部分向您展示了如何绕过不同应用程序的证书锁定。
无线网络中的客户端隔离¶
设置拦截代理并获得 MITM 位置后,您可能仍然看不到任何内容。这可能是由于应用程序中的限制(请参阅下一节),但也可能是由于您连接的 Wi-Fi 中所谓的客户端隔离。
无线客户端隔离是一项安全功能,可防止无线客户端相互通信。此功能对于访客和 BYOD SSID 非常有用,它增加了一层安全级别,以限制连接到无线网络设备之间的攻击和威胁。
如果我们需要用于测试的 Wi-Fi 具有客户端隔离该怎么办?
您可以在 Android 设备上配置代理以指向 127.0.0.1:8080,通过 USB 将手机连接到主机,并使用 adb 进行反向端口转发
adb reverse tcp:8080 tcp:8080
完成此操作后,Android 手机上的所有代理流量都将进入 127.0.0.1 上的端口 8080,并且它将通过 adb 重定向到主机上的 127.0.0.1:8080,您现在将在 Burp 中看到流量。使用此技巧,您还可以在具有客户端隔离的 Wi-Fi 中测试和拦截流量。
非代理感知应用¶
设置拦截代理并获得 MITM 位置后,您可能仍然看不到任何内容。这主要是由于以下原因
- 该应用正在使用 Xamarin 等框架,该框架根本没有使用 Android 操作系统的代理设置,或者
- 您正在测试的应用正在验证是否设置了代理,并且现在不允许任何通信。
在这两种情况下,您都需要额外的步骤才能最终看到流量。在以下部分中,我们将描述两种不同的解决方案:bettercap 和 iptables。
您还可以使用您控制下的接入点来重定向流量,但这将需要额外的硬件,我们现在专注于软件解决方案。
对于这两种解决方案,您都需要在 Burp 的“代理”选项卡/“选项”/“编辑接口”中激活“支持隐形代理”。
iptables¶
您可以使用 Android 设备上的 iptables 将所有流量重定向到您的拦截代理。以下命令会将端口 80 重定向到您在端口 8080 上运行的代理
iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination <Your-Proxy-IP>:8080
验证 iptables 设置并检查 IP 和端口。
$ iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DNAT tcp -- anywhere anywhere tcp dpt:5288 to:<Your-Proxy-IP>:8080
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
Chain natctrl_nat_POSTROUTING (0 references)
target prot opt source destination
Chain oem_nat_pre (0 references)
target prot opt source destination
如果您想重置 iptables 配置,您可以刷新规则
iptables -t nat -F
bettercap¶
有关运行 bettercap 的进一步准备和说明,请参阅 通过 ARP 欺骗实现 MITM 位置。
运行代理的主机和 Android 设备必须连接到同一无线网络。使用以下命令启动 bettercap,并将以下 IP 地址 (X.X.X.X) 替换为您的 Android 设备的 IP 地址。
$ sudo bettercap -eval "set arp.spoof.targets X.X.X.X; arp.spoof on; set arp.spoof.internal true; set arp.spoof.fullduplex true;"
bettercap v2.22 (built for darwin amd64 with go1.12.1) [type 'help' for a list of commands]
[19:21:39] [sys.log] [inf] arp.spoof enabling forwarding
[19:21:39] [sys.log] [inf] arp.spoof arp spoofer started, probing 1 targets.
代理检测¶
一些移动应用尝试检测是否设置了代理。如果是这样,他们会认为这是恶意的,并且无法正常工作。
为了绕过这种保护机制,您可以设置 bettercap 或配置 iptables,而无需在 Android 手机上设置代理。我们之前没有提到过的第三个选项是使用 Frida,它适用于这种情况。可以通过查询 ProxyInfo
类并检查 getHost() 和 getPort() 方法来检测是否在 Android 上设置了系统代理。可能还有其他各种方法可以实现相同的任务,您需要反编译 APK 才能识别实际的类和方法名称。
下面您可以找到一个 Frida 脚本的样板源代码,该脚本将帮助您重载正在验证是否设置了代理的方法(在这种情况下称为 isProxySet),并且始终返回 false。即使现在配置了代理,该应用也会认为没有设置代理,因为该函数返回 false。
setTimeout(function(){
Java.perform(function (){
console.log("[*] Script loaded")
var Proxy = Java.use("<package-name>.<class-name>")
Proxy.isProxySet.overload().implementation = function() {
console.log("[*] isProxySet function invoked")
return false
}
});
});