译文声明
本文是翻译文章,文章原作者 Jeroen Beckers ,文章来源:https://blog.nviso.eu 原文地址:https://blog.nviso.eu/2020/11/19/proxying-android-app-traffic-common-issues-checklist/
译文仅供参考,具体内容表达以及含义以原文为准
引言
在进行移动评估时,通常会有两个子评估:移动前端和后端API。为了检查API的安全性,需要大量的文档(例如Swagger或Postman文件)。或者可以让移动应用程序为您生成所有流量,并通过代理简单地拦截和修改流量(MitM攻击)。
有时设置代理很容易,但是有时也是非常困难且耗时。这时可以查看自己的“完整性检查表”方便找出错误的步骤。
在此文章中使用PortSwigger的Burp Suite代理,同时相同的步骤也可以用于任何HTTP代理。
下面的示例中,代理将托管在192.168.1.100.,端口:8080检查
0x01应用程序是否使用SSL固定?
通过networkSecurityConfig固定
通过OKHttp固定
在混淆的应用程序中固定混淆的OkHttp
固定各种库
固定在第三方应用程序框架(Flutter,Xamarin,Unity)中
设置设备
首先,我们需要确保在设备上正确设置了所有内容。无论您尝试使用MitM的应用程序如何,这些步骤均适用。
0x02设备上是否配置了代理?
显而易见的第一步是在设备上配置代理。使用者界面会因您的Android版本而有所不同,但找起来并不难。
完整性检查:
转到:“设置”>“连接”>“Wi-Fi”,选择您所使用的Wi-Fi网络,点击“高级”>“代理”>“手动”,然后输入您的代理详细信息:
代理主机名:192.168.1.100
代理端口:8080
0x03Burp是否在所有接口上监听?
默认情况,Burp仅在本地接口(127.0.0.1)上侦听,但是由于我们要从其他设备进行连接,因此Burp需要在已加入Wi-Fi网络的特定接口上侦听。您可以在所有接口上侦听,也可以在特定接口上侦听(如果知道所需的接口)。作为健全性检查,我通常会选择“在所有界面上收听”。注意Burp具有一个API,该API可能允许同一Wi-Fi网络上的其他人查询您的代理并从中检索信息。
完整性检查
在主机上搜索 http://192.168.1.100:8080。 Burp就会出现。
解答
在Burp中,转到“代理”>“选项“>“代理侦听器”窗口中单击您的代理,然后在“绑定到地址”配置上选中“所有接口”
0x04设备可以连接到代理?
某些网络具有主机/客户端隔离功能,因此不允许客户端相互通信。在这种情况下,由于路由器不允许,您的设备将无法连接到代理。
完整性检查
打开设备上的浏览器,然后浏览 http://192.168.1.100:8080,Burp就会出现。如果已经配置了代理,那么应该就能够浏览到 http:// burp。
解答
-
在禁用主机/客户端隔离的情况下设置自定义无线网络
-
将您的代理托管在可访问的设备(例如AWS ec2实例)上
-
进行ARP欺骗攻击,使移动设备认为您是路由器
-
使用adb reverse通过USB代理您的流量
- 将设备上的代理配置为端口8080上转到127.0.0.1
- 通过USB连接设备,并确保adb设备显示您的设备
- 执行adb反向tcp:8080 ,它将在:8080上接收的所有流量发送到:8080
- 此时可以浏览到http://127.0.0.1:8080就看到Burp的出现
0x05可以代理HTTP通信吗?
HTTP流量的步骤通常比HTTPS流量简单的多,因此这里的快速完整性检查可确保您的代理已正确设置并可由设备访问。
完整性检查
浏览 http://neverssl.com 确保您在Burp中可以看到该请求。 Neverssl.com是一个不使用HSTS的网站,不会将其发送到HTTPS版本,从而使其成为测试纯文本流量的选择。
解答
查看HTTP是否有问题的
Burp的拦截已启用,进行请求等待
0x06设备上是否已安装Burp证书?
为了拦截HTTPS流量,需要在设备上安装代理的证书。
完整性检查
转到设置>安全性>受信任的凭据>用户,并确保列出了您的证书。另外,可以尝试拦截来自设备浏览器的HTTPS流量。
解答
-
在浏览器中导航到http:// burp
-
点击右上方的“ CA证书”;将开始下载
-
使用adb或文件管理器将扩展名从der更改为crt
adb shell mv /sdcard/Download/cacert.der /sdcard/Download/cacert.crt
-
使用文件管理器导航到文件,然后打开文件以开始安装
0x07Burp证书是否已安装为根证书?
默认情况下,较新版本的Android上的应用程序不信任用户证书。可以重新打包应用程序以将相关控件添加到network_security_policy.xml文件中,但是将根CA放入系统存储中将会省去其他步骤(例如第三方框架)的麻烦。
完整性检查
转到设置>安全性>受信任的凭据>系统,并确保列出了您的证书。
解答
为了将证书列为根证书,设备需要以Magisk直根
-
正常安装客户端证书
-
安装MagiskTrustUser模块
-
重新启动设备以启用模块
-
再次重启以触发文件复制
也可以:
-
确保证书格式正确,然后将其复制/粘贴到/ system / etc / security / cacerts目录中。但是,要使其正常工作,您的/ system分区需要可写。一些生根方法可以做到这一点,但是它很脏,Magisk更好。以正确的格式获取证书也有些繁琐
-
修改networkSecurityConfig,以将用户证书包括为信任锚(请参见下文)。不过,将您的证书作为系统证书会更好,所以我很少采用这种方法
0x08Burp证书的寿命?
Google(以及Android)缩短了证书的最长接受期限。如果证书的过期日期较长,Android / Chrome将不会接受。
完整性检查
使用浏览器连接到代理,查看根CA和证书的时间。如果他们不到1年,就会失效。如果时间超过一年,安全起见创建一个新的CA。可以在Android上使用最新版本的Chrome浏览器来验证证书的有效期。如果出现错误,Chrome就会显示 : ERR_CERT_VALIDITY_TOO_LONG
解答
这里有两种可能的解决方案:
-
确保安装了最新版本的Burp,这会减少生成证书的时间
-
制作自己的根CA,该CA仅可使用365天。实际上根CA生成的证书也将少于365天。因为证书可以与团队成员共享,并且可以安装在参与活动的所有设备上
0x09应用程序代理知道吗?
许多应用程序只是忽略了系统的代理设置。标准库的应用程序通常将使用系统代理设置,但是依赖于解释语言的应用程序(例如Xamarin和Unity),本机编译的应用程序(例如Flutter)通常要求开发人员将代理支持明确地编程到应用程序中。
完整性检查
运行应用程序时,能够在Burp的Proxy选项卡中看到HTTPS数据,或在Dashboard面板的Burp的事件日志中看到HTTPS连接错误。由于整个设备都是代理服务器,因此能够看到使用SSL固定的应用程序(例如Google Play)的许多阻止请求,查看是否可以找到与该应用程序相关的域。如果没有看到任何相关的失败连接,则说明您的应用程序很可能没有代理。
完整性检查,也可以查看应用程序是否使用第三方框架。如果应用程序是用Flutter编写的,则肯定不会意识到代理,而如果应用程序是Xamarin或Unity编写,则很有可能会忽略系统的代理设置。
-
用apktool反编译
-
apktool d myapp.apk
-
进入已知位置
-
Flutter:
myapp/lib/arm64-v8a/libflutter.so
-
Xamarin:
myapp/unknown/assemblies/Mono.Android.dll
-
Unity:
myapp/lib/arm64-v8a/libunity.so
解答
可以尝试一些方法:
- 使用ProxyDroid(仅限root用户)。尽管它比较早一些,但仍然可以很好地运行。 ProxyDroid使用iptables来强制将流量重定向到您的代理
- 通过第二个无线接口设置自定义热点,并使用iptables自己重定向流量。您可以在mitmproxy文档中找到设置,这是另一个有用的HTTP代理。完全相同的设置适用于Burp
在这两种情况下,您都已从“代理意识”设置转换为“透明代理”设置。您必须做两件事:
- 在设备上禁用代理。否则Burp将同时收到代理请求和透明请求,二者互不兼容。
- 将Burp配置为通过代理>选项>活动代理>编辑>请求处理>支持不可见代理来支持透明代理
再次执行完整性检查,可以在Burp的事件日志中看到SSL错误。
0x10应用程序是否使用自定义端口?
仅在应用程序不支持代理时,这才真正适用。在这种情况下,将使用iptables拦截流量,但是这些iptables规则仅针对特定端口。在ProxyDroid源代码中,可以看到仅目标端口80(HTTP)和443(HTTPS)。如果应用程序使用非标准端口(例如8443或8080),则不会被拦截。
完全性检查
我们需要找到离开应用程序的流量,该流量不会到达端口80(HTTP)或443(HTTPS)。最好的方法是侦听离开应用程序的所有流量。如果正在使用第二个Wi-Fi热点,则可以在设备上或主机上使用tcpdump进行此操作。
在具有root特权的adb shell上运行以下命令:
tcpdump -i wlan0 -n -s0 -v
将看到许多不同的连接。理想情况下,一旦知道应用程序发出了一些请求,就应该启动命令,打开应用程序并停止tcpdump。一段时间后,您将看到与具有非默认端口的远程主机的连接。在下面的示例中,端口8088上有多个到192.168.2.70的连接:
或者,您可以使用tcpdump -i wlan0 -n -s0 -w /sdcard/output.pcap将tcpdump的输出发送到pcap。从设备检索到output.pcap文件后,可以使用WireShark打开它并进行检查:
解答
如果您的应用程序确实不了解代理并且无法通过自定义端口进行通信,则ProxyDroid将无法为您提供帮助。 ProxyDroid不允许您添加自定义端口,尽管它是一个开源项目,因此PR很好。这意味着您必须手动使用iptables。
- 您可以在主机上充当路由器的地方设置第二个热点,从而执行MitM
- 或者您使用ARP欺骗在路由器和设备之间执行活动MitM
- 可以自己使用iptables并将所有流量转发到Burp。由于Burp在单独的主机上侦听,所以最好的解决方案是使用adb reverse将设备上的端口映射到Burp实例。这样,您无需设置单独的热点,只需要通过USB连接设备即可。
- 在主机上:adb反向
tcp:8080 tcp:8080
- 在设备上,以root用户身份 :
iptables -t nat -A OUTPUT -p tcp -m tcp --dport 8088 -j REDIRECT --to-ports 8080
- 在主机上:adb反向
0x11应用程序是否使用SSL固定?
此时,在Burp的事件日志仪表板中看到HTTPS连接失败。下一步验证是否使用SSL固定,并禁用它。尽管许多Frida脚本都声称是通用的根绕过,但没有一个脚本可以接近。 Android应用程序可以使用许多不同的技术编写,并且通常仅支持其中一些技术。
请注意,某些应用程序具有固定特定域的多种方法,需要组合脚本才能禁用所有SSL固定
0x12通过Android固定:networkSecurityConfig
Android允许应用程序使用network_security_config.xml文件执行SSL固定。该文件在AndroidManifext.xml中引用,位于res / xml /中。该名称通常为network_security_config.xml,但不一定必须如此。作为示例应用程序,Microsoft Authenticator应用程序定义了以下两个引脚 :
解答
使用任何普通的通用脚本 :
- 运行异议并执行android sslpinning disable命令
- 使用Frida代码共享 :
frida -U --codeshare akabe1/frida-multiple-unpinning -f be.nviso.app
- 使用apktool d和apktool b删除AndroidManifest中的networkSecurityConfig设置。通常通过Frida来完成它的速度要快得多,而且很少需要。
0x13通过OkHttp固定
固定域的另一种常用方式是通过OkHttp库。通过grepping OkHttp和/或sha256进行快速验证。会找到与OkHttp相关的引用(甚至是散列)以及所固定的内容:
解答
使用普通的通用旁路脚本:
- 运行异议并执行android sslpinning disable命令
- 使用Frida代码共享:
frida -U --codeshare akabe1/frida-multiple-unpinning -f be.nviso.app
- 使用apktool反编译apk,并修改固定域。默认情况下,OkHttp将允许未专门固定的连接。因此,查找和修改固定的域名,固定将被禁用。但是使用Frida的速度要快得多,因此很少采用这种方法。
0x14通过混淆的应用程序中的OkHttp进行固定
通用固定脚本可能会在混淆的应用程序上运行,因为它们寻找混淆的Android库。但是,如果应用程序使用的不是默认的Android库,则这些类将被混淆,脚本将无法找到正确的类。 OkHttp就是一个很好的例子。当应用程序使用OkHttp且已被混淆时,必须找出CertificatePinner.Builder类的混淆名称。可以在下面看到通过搜索相同的sha256字符串使用模糊的OkHttp的情况。通常仍会找到字符串引用以及一些程序包名称。这当然取决于混淆的程度。
解答
需要编写自己的Frida脚本,才能挂接CertificatePinner.Builder类的混淆版本。
作者编写的Frida脚本https://blog.nviso.eu/2019/04/02/circumventing-ssl-pinning-in-obfuscated-apps-with-okhttp/
0x15通过各种固定的库
除了使用networkSecurityConfig或OkHttp,开发人员还可以使用许多不同的标准Java类或导入的库执行SSL固定。此外,某些基于Java的第三方应用程序(例如PhoneGap或AppCelerator框架)为开发人员提供了特定功能,以向应用程序添加固定。
可以通过编程方式进行,尝试各种反固定脚本,至少要弄清楚触发了哪种方法,以便您可以在应用程序上获取信息,之后便可以进一步对该应用程序进行逆向工程,弄明白拦截为何仍不起作用。
解答
尝试找到尽可能多的SSL固定脚本,并监听其输出。如果可以确定使用的某些类或框架,这将帮助创建针对应用程序的自定义SSL固定绕过。
执行android sslpinning disable命令
使用Frida脚本。其中许多具有重叠的功能,但您永远不会知道。注意其中有多少声称是通用的
- https://codeshare.frida.re/@akabe1/frida-multiple-unpinning/
- https://codeshare.frida.re/@pcipolloni/universal-android-ssl-pinning-bypass-with-frida/
- https://codeshare.frida.re/@sowdust/universal-android-ssl-pinning-bypass-2/
- https://codeshare.frida.re/@masbog/frida-android-unpinning-ssl/
- https://codeshare.frida.re/@segura2010/android-certificate-pinning-bypass/
- https://codeshare.frida.re/@akabe1/frida-universal-pinning-bypasser/
0x16固定在第三方应用程序框架中
第三方应用程序框架将针对TLS和HTTP拥有自己的低层实现,并且默认的固定绕过脚本将不起作用。如果应用是用Flutter,Xamarin或Unity编写的,则需要进行一些手动的逆向工程。
查明是否使用了第三方应用程序框架
如上一步所述,以下文件是Flutter,Xamarin或Unity的赠品:
- Flutter:
myapp/lib/arm64-v8a/libflutter.so
- Xamarin:
myapp/unknown/assemblies/Mono.Android.dll
- Unity:
myapp/lib/arm64-v8a/libunity.so
0x17固定在Flutter应用程序中
Flutter不识别代理,不使用系统的CA存储。每个Flutter应用程序均包含用于验证连接的可信CA的完整副本。因此,尽管极有可能没有执行SSL固定,但它仍然不会信任设备上的根CA,因此无法进行拦截。
解答
这两个博客里面有
https://blog.nviso.eu/2019/08/13/intercepting-traffic-from-android-flutter-applications/
https://blog.nviso.eu/2020/05/20/intercepting-flutter-traffic-on-android-x64/
0x18固定在Xamarin和Unity应用程序中
Xamarin / Unity应用程序通常并不难,但确实需要手动进行逆向工程和修补。 Xamarin / Unity应用程序在assemblys /文件夹中包含.dll文件,可以使用.NET反编译器将其打开。DNSpy工具允许修改dll文件
解答
步骤如下:
- 使用apktool提取apk并找到.dll文件
- 使用DNSpy打开.dll文件并找到HTTP固定逻辑
- 通过修改C#代码或IL修改逻辑
- 保存修改后的模块
- 用修改后的版本覆盖.dll文件
- 重新打包并辞职
- 重新安装应用程序并运行
0x19仍然无法拦截流量怎么办?
在完成所有步骤之后,有可能无法拦截所有流量。典型的罪魁祸首 :
- 非HTTP协议(我们仅使用HTTP代理,因此不会拦截非HTTP协议)
- 非常沉重的混淆
- 防篡改控件
通常,在手机游戏或金融应用程序中看到这些功能。此时,将需要对应用程序进行反向工程并编写自己的Frida脚本。这可能是一个非常困难且耗时的过程,而像这样的分步指南将永远无法为您提供帮助。但这当然是乐趣的开始。