首页
论坛
课程
招聘
[翻译]Android 基础安全测试
2022-8-31 16:16 19279

[翻译]Android 基础安全测试

2022-8-31 16:16
19279

Android 基础安全测试

在上一章中,我们概述了 Android 平台并描述了其应用程序的结构。在本章中,我们将讨论如何设置安全测试环境,并介绍可用于测试 Android 应用程序安全漏洞的基本过程和技巧。这些基本过程是测试用例的基础。

翻译前言

Soft Brick翻译为软砖,与此相关的还有硬砖(Hard Brick)

砖(Brick)的意思是,手机由于严重的配置错误、固件损坏或者硬件问题,无法再运行。

当您的手机开机显示屏幕然后立即自动关闭,或者它一直在振动重新启动,或者它完全死机没有任何明显的迹象,所有这些信号都表明您的手机已经变砖了。

软砖(Soft Brick)是由于某些软件问题(如启动循环或设备在启动过程中的某个时间点冻结)而导致的一个android 设备状态

硬砖(Hard Brick)是当您的设备在没有启动循环的情况下无法启动时发生的 android 设备状态。

 

near-stock翻译为原生

Android 测试设置

您可以在几乎任何运行 Windows、Linux 或 macOS 的机器上设置功能齐全的测试环境。

主机设备

您至少需要Android Studio(随Android SDK一起提供)工具、模拟器和应用程序来管理各种 SDK 版本和框架组件。Android Studio 还附带了一个用于创建模拟器的 Android 虚拟设备 (AVD,Android Virtual Device)管理器。确保您的系统上安装了最新的SDK 工具平台工具包。

 

此外,如果您计划使用包含native库的应用程序,您可能希望通过安装Android NDK来完成主机设置(这在“ Android 上的篡改和逆向工程”一章中也有相关性)。

 

有时,从计算机显示或控制设备会很有用。为此,您可以使用Scrcpy

测试设备

对于动态分析,您需要一台 Android 设备来运行目标应用程序。原则上,您可以在没有真正的 Android 设备的情况下仅使用模拟器进行测试。但是,应用程序在模拟器上的执行速度很慢,模拟器可能无法给出真实的结果。在真实设备上进行测试可以实现更顺畅的过程和更真实的环境。另一方面,模拟器允许您轻松更改 SDK 版本或创建多个设备。下表列出了每种方法优缺点的完整概述。

属性 物理真机 模拟器
恢复能力 可能出现软砖(Soft Brick),但通常仍可以刷新固件。硬砖(Hard Brick)非常罕见。 模拟器可能会崩溃或损坏,但可以创建一个新模拟器或恢复快照。
重置 可以恢复出厂设置或重新刷机。 可以删除和重新创建模拟器。
快照 不支持打快照。 支持快照,非常适合恶意软件分析。
速度 比模拟器快。 通常很慢,但正在改进。
成本 一个设备几百块。但是您可能需要不同的设备,例如带或不带生物识别传感器的设备。 免费和商业解决方案都存在。
刷root难度 依赖特定设备。 默认已经root。
模拟器检测的难度 不是模拟器,所以容易逃避检测。 存在许多工具,从而很容易检测到应用程序正在模拟器中运行。
root检测难度 更容易隐藏root,因为许多root检测算法会检查模拟器属性。使用 Magisk Systemless 几乎不可能检测到root。 模拟器总是会触发root检测算法,因为模拟器是为测试许多出名工具而构建的。
API 级别支持 取决于设备和社区。活跃的社区将持续分发最新版本(例如 LineageOS),而不太受欢迎的设备可能只会收到一些更新。在版本之间切换需要刷机,这是一个繁琐的过程。 始终支持最新版本,包括 beta 版本。可以轻松下载和启动包含特定 API 级别的模拟器。
Native库支持 Native库通常是为 ARM 设备构建的,因此它们可以在物理设备上运行。 一些模拟器在 x86 CPU 上运行,因此它们可能无法运行打包的Native库。
恶意软件危险 恶意软件样本可以感染设备,但如果您可以清除设备存储并刷干净的固件,从而将其恢复为出厂设置,这应该不是问题。请注意,存在试图利用 USB 桥接器的恶意软件样本。 恶意软件样本可以感染模拟器,但可以简单地删除并重新创建模拟器。模拟器可以创建快照并比较不同的快照以帮助进行恶意软件分析。请注意,存在试图攻击虚拟机管理程序的恶意软件的概念证明。

在真实设备上测试

几乎任何物理设备都可用于测试,但需要考虑一些事项。首先,设备需要是可root的。通常是通过漏洞利用或通过未锁定的引导加载程序完成root过程的。漏洞利用不太行,引导加载程序可能会被永久锁定,或者只有在运营商合同终止后才能解锁。

 

最佳设备是专为开发人员打造的Google 旗舰 pixel 设备。这些设备通常带有可解锁的引导加载程序、开源固件、内核、在线可用的收音机和官方操作系统源代码。开发者社区更喜欢 Google 设备,因为它的操作系统最接近 android 开源项目。这些设备通常具有最长的支持行为,包括 2 年的操作系统更新和 1 年的安全更新。

 

或者,Google 的Android One项目包含的设备将获得相同的支持行为(2 年的操作系统更新,1 年的安全更新)并具有接近原生的体验。虽然它最初是作为一个低端设备的项目开始的,但该计划已经发展到包括中端和高端智能手机,其中许多都得到了改装社区的积极支持。

 

LineageOS项目支持的设备也非常适合测试设备。他们有一个活跃的社区,社区里有更方便刷机和刷root的指导,并且Lineage 安装可以快速地获得最新的 Android 版本 。LineageOS 还在 OEM 停止分发更新后很长时间内继续支持新的 Android 版本。

 

使用 Android 物理设备时,您需要在设备上启用开发人员模式和 USB 调试,以便使用ADB调试接口。从 Android 4.2(API 级别 16)开始,应用设置中的开发者选项子菜单被默认隐藏。要激活它,请点击设置中的关于手机的版本号区域七次。请注意,版本号字段的位置因设备而异。例如,在 LG 手机上,它位于关于手机 -> 软件信息下。完成此操作后,开发人员选项将显示在“设置”菜单的底部。激活开发人员选项后,您可以使用USB调试开关。

在模拟器上测试

存在多个模拟器,它们又各有优缺点:

 

免费模拟器:

商业模拟器:

  • Genymotion - 具有许多功能的成熟模拟器,可作为企业内部或基于云的解决方案。免费版可用于非商业用途。
  • Corellium - 通过基于云或企业内部的解决方案,它提供自定义设备虚拟化。

尽管有几个免费的 Android 模拟器,但我们建议使用 AVD,因为与其他模拟器相比,它提供了适合测试您的应用程序的增强功能。在本指南的其余部分,我们将使用官方 AVD 来执行测试。

 

AVD 支持一些硬件仿真,例如GPSSMS运动传感器

 

您可以使用 Android Studio 中的 AVD 管理器启动 Android 虚拟设备 (AVD),也可以使用以下命令从命令行启动 AVD 管理器,该android命令位于 Android SDK 的工具目录中:

1
$ ./android avd

有多种工具和 VM 可用于在模拟器环境中测试应用程序:

还请验证本书末尾的“测试工具”一章。

获得特权访问

建议在真机上进行测试,记得在真机上刷root。root权限可以完全控制操作系统,并允许您绕过应用程序沙箱等限制。这些特权反过来允许您更轻松地使用代码注入和函数挂钩等技术。

 

请注意,刷root是有风险的,在继续之前需要澄清三个主要后果。刷root可能会产生以下影响:

  • 使设备保修失效(在采取任何行动之前,请务必查看制造商的政策)
  • 使设备“变砖”,使其无法操作和无法使用
  • 造成额外的安全风险(因为内置的漏洞利用缓解措施经常被删除)

您不应该刷root在您存储私人信息的个人设备上。我们建议您购买便宜的专用测试设备。许多较旧的设备,例如 Google 的 Nexus 系列,可以运行最新的 Android 版本,非常适合测试。

 

您需要了解,在您的设备刷root最终是您的决定,OWASP 对任何损害概不负责。如果您不确定,请在开始刷root过程之前寻求专家建议。

 

哪些手机可以root

 

几乎任何安卓手机都可以root。Android OS 的商业版本(内核级别的 Linux OS 演进)针对移动手机进行了优化。这些版本的某些功能已被删除或禁用,例如,非特权用户能够成为“root”用户(具有提升的特权)。root 手机意味着允许用户成为 root 用户,例如,添加了一个名为su的标准 Linux 可执行文件,用于更改为另一个用户帐户的权限。

 

为了给移动设备刷root,首先应该解锁BootLoader(简称刷BL)。解锁过程取决于设备制造商(华为已经关闭了解锁码申请,导致不能解锁BL,所以使用小米最好)。然而,出于实际原因,root 一些移动设备比 root 其他设备更受欢迎,尤其是在安全测试方面:由谷歌创建并由三星、LG 和摩托罗拉等公司制造的设备是最受欢迎的,因为它们有许多开发人员使用。当引导加载程序解锁并且 Google 提供了许多工具来支持root本身时,设备保修不会失效。XDA 论坛上发布了一份针对所有主要品牌设备的root指南的精选列表。

 

使用 Magisk 刷root

 

Magisk(“Magic Mask”)是一种root您的 Android 设备的方法。它的特点在于对系统进行修改的方式。虽然其他root工具会改变系统分区上的实际数据,但 Magisk 不会(这被称为“无系统”,原理是通过挂载一个与系统文件相隔离的文件系统来加载自定义内容)。这样可以隐藏对 root 敏感的应用程序(例如银行或游戏)的修改,并允许使用官方的 Android OTA 升级,而无需事先取消设备的 root 权限。

 

你可以阅读GitHub 上的官方文档来熟悉 Magisk 。如果您没有安装 Magisk,您可以在文档中找到安装说明。如果您使用官方的 Android 版本并计划升级,Magisk在 GitHub 上提供了教程

 

此外,开发人员可以使用 Magisk 的强大功能创建自定义模块并将它们提交到官方Magisk 模块存储库。然后可以在 Magisk Manager 应用程序中安装提交的模块。这些可安装模块之一是著名的Xposed 框架的无系统版本(可用于最高 27 的 SDK 版本)。

 

root检测

 

“在 Android 上测试反逆向防御”一章中提供了广泛的root检测方法列表。

 

对于典型的移动应用安全架构,您通常需要在禁用root检测的情况下去测试调试架构。如果这样的架构不可用于测试,您可以通过多种方式禁用root检测,这将在本书后面介绍。

基本测试操作

使用设备shell命令行

测试应用程序时最常见的事情之一是使用设备的shell命令行。在本节中,我们将了解如何从使用或者不使用USB的主机去远程访问 Android shell,以及从设备本地访问 Android shell。

远程shell

为了从您的主机连接到 Android 设备的shell,adb通常是您选择的工具(除非您更喜欢使用远程 SSH 访问,例如通过 Termux)。

 

对于本节,我们假设您已按照“在真机上测试”中的说明正确启用了开发人员模式和 USB 调试。通过 USB 连接 Android 设备后,您可以通过运行以下命令访问远程设备的 shell:

1
$ adb shell

按 Control + D 或输入exit退出

 

如果您的设备已获得 root 权限或您正在使用模拟器,您可以通过su命令在远程 shell 中来获得 root 访问权限:

1
2
3
4
$ adb shell
bullhead:/ $ su
bullhead:/ # id
uid=0(root) gid=0(root) groups=0(root) context=u:r:su:s0

只有当您使用模拟器时,您才可以使用adb root命令以 root 权限重新启动 adb,因此下次您输入adb shell时,您将拥有 root 访问权限。这也允许在您的主机和 Android 文件系统之间双向传输数据,即使可以访问只有 root 用户可以访问的位置(通过adb push/pull)。在下面的“主机-设备数据传输”部分中查看更多关于数据传输的信息。

 

连接到多个设备

 

如果您有多个设备,可以在所有命令中用-s后加设备序列号的方式(例如adb -s emulator-5554 shelladb -s 00b604081540b7c6 shell)。您可以使用以下命令获取所有已连接设备及其序列号的列表:

1
2
3
4
$ adb devices
List of devices attached
00c907098530a82c    device
emulator-5554    device

通过 Wi-Fi 连接到设备

 

您也可以在不使用 USB 数据线的情况下访问您的 Android 设备。为此,您必须将主机和 Android 设备都连接到同一个 Wi-Fi ,然后按照以下步骤操作:

  • 使用 USB 数据线将设备连接到主机,并将目标设备设置为侦听端口 5555 上的 TCP/IP 连接:adb tcpip 5555

  • 断开 USB 数据线并运行adb connect <device_ip_address>。通过运行检查设备现在是否可用adb devices

  • adb shell打开shell命令行。

这样会使设备对同一局域网内的其他设备开放,所以使用USB更好。

例如,在 Nexus 设备上,您可以在设置->系统->关于手机->状态-> IP 地址或转到Wi-Fi菜单并在您连接的网络上点击一次来找到 IP 地址.

 

请参阅Android 开发者文档中的完整说明和注意事项。

 

通过 SSH 连接到设备

 

如果您愿意,还可以启用 SSH 访问。一个方便的选择是使用Termux,您可以轻松地将其配置为提供 SSH 访问(使用密码或公钥身份验证)并使用命令启动它sshd(默认在端口 8022 上启动)。为了通过 SSH 连接到 Termux,您可以简单地运行命令ssh -p 8022 <ip_address>ip_address实际远程设备 IP 在哪里)。此选项有一些额外的好处,因为它允许通过 SFTP 访问文件系统,也在端口 8022 上。

设备上的 Shell 应用程序

虽然与远程 shell 相比,通常使用shell应用程序(例如:Termux )可能非常乏味,但它可以在网络问题或检查某些配置的情况下进行调试。

主机-设备数据传输

使用adb

您可以使用adb命令adb pull <remote> <local>adb push <local> <remote> commands将文件复制到设备或从设备复制文件。它们的用法非常简单。例如,以下内容foo.txt将从您的当前目录(本地)复制到sdcard文件夹(远程):

1
$ adb push foo.txt /sdcard/foo.txt

当您确切地知道要复制的内容和复制到哪里,并且还支持批量文件传输时,通常使用这种方法,例如,您可以将整个目录从 Android 设备拉(复制)到您的主机。

1
2
$ adb pull /sdcard
/sdcard/: 1190 files pulled. 14.1 MB/s (304526427 bytes in 20.566s)

使用 Android Studio 设备文件资源管理器

Android Studio 有一个内置的设备文件资源管理器,您可以通过View -> Tool Windows -> Device File Explorer
图片描述
如果您使用的是已经root过的设备,您现在可以开始探索整个文件系统。但是,当使用非 root 设备访问应用程序沙箱时,除非应用程序是可调试的,否则您将无法在应用程序沙箱中“入狱”。

使用objection

github项目地址https://github.com/sensepost/objection

 

当您在处理特定应用程序并希望复制在沙箱中的文件时,使用objection很有用(请注意,您只能访问目标应用程序有权访问的文件)。这种方法无需将应用程序设置为可调试(debuggable),只有在使用 Android Studio 的设备文件资源管理器时需要这样做(将app设置成可调试)。

 

首先,按照“推荐工具 - Objection”中的说明,使用Objection连接到应用程序。然后,像往常一样在终端上使用ls and cd来探索可用文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ frida-ps -U | grep -i owasp
21228  sg.vp.owasp_mobile.omtg_android
 
$ objection -g sg.vp.owasp_mobile.omtg_android explore
 
...g.vp.owasp_mobile.omtg_android on (google: 8.1.0) [usb] # cd ..
/data/user/0/sg.vp.owasp_mobile.omtg_android
 
...g.vp.owasp_mobile.omtg_android on (google: 8.1.0)  [usb] # ls
Type       ...  Name
---------  ...  -------------------
Directory  ...  cache
Directory  ...  code_cache
Directory  ...  lib
Directory  ...  shared_prefs
Directory  ...  files
Directory  ...  app_ACRA-approved
Directory  ...  app_ACRA-unapproved
Directory  ...  databases
 
Readable: True  Writable: True

你有一个你想下载的文件,你可以运行file download <some_file>. 这会将该文件下载到您的工作目录。您可以使用相同的方式上传文件file upload

1
2
3
4
5
6
7
8
9
10
11
...[usb] # ls
Type    ...  Name
------  ...  -----------------------------------------------
File    ...  sg.vp.owasp_mobile.omtg_android_preferences.xml
 
Readable: True  Writable: True
...[usb] # file download sg.vp.owasp_mobile.omtg_android_preferences.xml
Downloading ...
Streaming file from device...
Writing bytes to destination...
Successfully downloaded ... to sg.vp.owasp_mobile.omtg_android_preferences.xml

不利的一面是,在撰写本文时,objection尚不支持批量文件传输,因此您只能复制单个文件。尽管如此,在某些情况下,这仍然可以派上用场。当你已经在使用objection来探索应用程序并找到一些有趣的文件,而不是从单独的终端记下该文件的完整路径并使用adb pull <path_to_some_file>。所以直接执行file download <some_file>更方便。

使用 Termux

如果你有一个 root 设备,安装了Termux正确配置了 SSH 访问,你应该有一个 SFTP(SSH 文件传输协议)服务器且服务器已经在端口 8022 上运行。你可以从你的终端访问它:

1
2
3
4
5
6
7
8
$ sftp -P 8022 root@localhost
...
sftp> cd /data/data
sftp> ls -1
...
sg.vantagepoint.helloworldjni
sg.vantagepoint.uncrackable1
sg.vp.owasp_mobile.omtg_android

或者简单地使用像FileZilla这样的支持 SFTP 的客户端:
图片描述
查看Termux Wiki以了解有关远程文件访问方法的更多信息。

获取和提取应用程序

有几种方法可以从设备中提取 APK 文件。您需要根据应用程序是公共的还是私有的来决定哪一种是最简单的方法。

可替代的应用商店

最简单的选择之一是从 Google Play 商店的公共应用程序的网站下载 APK。但是,请记住,这些网站不是官方网站,并且不能保证应用程序没有被重新打包或包含恶意软件。一些托管 APK的知名网站:

这些网站保证应用程序的SHA-1和SHA-256校验和不被恶意篡改

 

请注意,您无法控制这些网站,并且您无法保证它们将来会做什么。只有当它是您唯一的选择时才使用它们。

使用 gplaycli

您可以使用gplaycli通过指定其 AppID来下载 (-d) 选定的 APK(添加-p以显示进度条和-v详细信息):

1
2
3
4
5
6
7
8
9
$ gplaycli -p -v -d com.google.android.keep
[INFO] GPlayCli version 3.26 [Python3.7.4]
[INFO] Configuration file is ~/.config/gplaycli/gplaycli.conf
[INFO] Device is bacon
[INFO] Using cached token.
[INFO] Using auto retrieved token to connect to API
[INFO] 1 / 1 com.google.android.keep
[################################] 15.78MB/15.78MB - 00:00:02 6.57MB/s/s
[INFO] Download complete

com.google.android.keep.apk文件将在您的当前目录中。正如您可能想象的那样,这种方法是下载 APK 的一种非常方便的方式,尤其是在自动化方面。

您可以使用自己的 Google Play 凭据或令牌。默认情况下,gplaycli 将使用内部提供的 token

从设备中提取应用程序包

从设备获取应用包是推荐的方法,因为我们可以保证应用没有被第三方修改。要从 root 或非 root 设备获取应用程序,您可以使用以下方法:

 

用于adb pull检索 APK。如果您不知道包名称,第一步是列出设备上安装的所有应用程序:

1
$ adb shell pm list packages

找到应用程序的包名称后,您需要它在系统上存储的完整路径才能下载它。

1
$ adb shell pm path <package name>

有了 APK 的完整路径,您现在可以简单地使用adb pull它来提取它。

1
$ adb pull <apk path>

APK 将下载到您的工作目录中。

 

或者,也有像APK Extractor这样的应用程序不需要 root,甚至可以通过您喜欢的方法共享提取的 APK。如果您不想连接设备或通过网络设置 adb 来传输文件,这会很有用。

测试免安装应用

使用Google Play Instant,您可以创建即时应用程序,这些应用程序可以从浏览器或从 Android 5.0(API 级别 21)开始的应用商店中的“立即尝试”按钮立即启动。它们不需要任何形式的安装。即时应用程序存在一些挑战:

这些因素综合起来可能导致不安全的决策,例如:从应用程序中剥离过多的授权/身份验证/保密逻辑,从而导致信息泄露。

 

注意:即时应用程序需要 App Bundle(aab,把生成apk和签名推迟到google play商店)。App Bundle 在“Android 平台概述”一章的“ App Bundles ”部分中进行了描述。

静态分析注意事项

静态分析可以在对下载的即时应用程序进行逆向工程之后进行,也可以通过分析 App Bundle 来完成。当您分析 App Bundle 时,请检查 Android Manifest 以查看是否dist:module dist:instant="true"被设置(基本模块或带有dist:module设置的特定模块)。接下来,检查各种入口点,这些入口点是在配置文件中被设置的(通过<data android:path="</PATH/HERE>" />)。

 

现在按照入口点,就像您对任何Activity所做的那样并检查:

  • 对于应用程序检索到的数据,是否需要对该数据进行隐私保护?如果是,是否有所有必要的控制措施?

  • 所有通信都安全吗?

  • 当您需要更多功能时,是否也下载了正确的安全控制?

动态分析注意事项

有多种方法可以对您的即时应用进行动态分析。在所有情况下,您必须先安装对即时应用程序的支持并将ia可执行文件添加到您的$PATH

 

即时应用程序支持的安装通过以下命令完成:

1
$ cd path/to/android/sdk/tools/bin && ./sdkmanager 'extras;google;instantapps'

接下来,您必须添加path/to/android/sdk/extras/google/instantapps/ia到您的$PATH.

 

准备就绪后,您可以在运行 Android 8.1(API 级别 27)或更高版本的设备上本地测试即时应用。该应用程序可以通过不同的方式进行测试:

  • 在本地测试应用程序:通过 Android Studio 部署应用程序(并启用Deploy as instant app在Run/Configuration对话框中的复选框)或使用以下命令部署应用程序:

    1
    $ ia run output-from-build-command <app-artifact>
  • 使用 Play Console测试应用:

    1. 将您的 App Bundle 上传到 Google Play 控制台

    2. 准备上传的捆绑包以发布到内部测试轨道。

    3. 在设备上登录内部测试人员帐号,然后从外部准备好的链接或通过测试人员帐号的应用商店中的try now按钮启动您的即时体验。

现在您可以测试应用程序,请检查是否:

  • 有任何数据需要隐私控制以及这些控制是否到位。

  • 所有通信都得到充分保护。

  • 当您需要更多功能时,是否也为这些功能下载了正确的安全控制?

安装应用程序

adb install在模拟器或连接的设备上安装 APK。

1
adb install path_to_apk

请注意,如果您拥有原始源代码并使用 Android Studio,则无需执行此操作,因为 Android Studio 会为您处理应用程序的打包和安装。

信息收集

分析应用程序的一个基本步骤是信息收集。这可以通过检查主机上的应用程序包或远程访问设备上的应用程序数据来完成。您将在后续章节中找到更高级的技术,但现在,我们将专注于基础知识:获取所有已安装应用程序的列表、探索应用程序包以及访问设备本身的应用程序数据目录。这应该让您了解应用程序的全部内容,而无需对其进行逆向工程或执行更高级的分析。我们将回答以下问题:

  • 软件包中包含哪些文件?

  • 该应用程序使用哪些native库?

  • 应用定义了哪些应用组件?哪些服务(service)或内容提供商(content provider)?

  • 应用程序是否可调试?

  • 该应用程序是否包含网络安全策略?

  • 该应用程序在安装时是否会创建任何新文件?

列出已安装的应用程序

在定位设备上安装的应用程序时,您首先必须找出要分析的应用程序的正确包名称。您可以使用pm(Android Package Manager) 或使用frida-ps检索已安装的应用程序:

1
2
3
4
5
6
$ adb shell pm list packages
package:sg.vantagepoint.helloworldjni
package:eu.chainfire.supersu
package:org.teamsik.apps.hackingchallenge.easy
package:org.teamsik.apps.hackingchallenge.hard
package:sg.vp.owasp_mobile.omtg_android

您可以包含选项( -3)以仅显示第三方应用程序及其 APK 文件的位置 ( -f),之后您可以通过adb pull下载它:

1
2
3
4
5
6
$ adb shell pm list packages -3 -f
package:/data/app/sg.vantagepoint.helloworldjni-1/base.apk=sg.vantagepoint.helloworldjni
package:/data/app/eu.chainfire.supersu-1/base.apk=eu.chainfire.supersu
package:/data/app/org.teamsik.apps.hackingchallenge.easy-1/base.apk=org.teamsik.apps.hackingchallenge.easy
package:/data/app/org.teamsik.apps.hackingchallenge.hard-1/base.apk=org.teamsik.apps.hackingchallenge.hard
package:/data/app/sg.vp.owasp_mobile.omtg_android-kR0ovWl9eoU_yh0jPJ9caQ==/base.apk=sg.vp.owasp_mobile.omtg_android

这与在应用程序包 ID 上运行adb shell pm path <app_package_id>相同:

1
2
$ adb shell pm path sg.vp.owasp_mobile.omtg_android
package:/data/app/sg.vp.owasp_mobile.omtg_android-kR0ovWl9eoU_yh0jPJ9caQ==/base.apk

用于frida-ps -Uai获取连接的 USB 设备 (-U ) 上当前安装 (-i ) 的所有应用 (-a):

1
2
3
4
5
6
7
$ frida-ps -Uai
  PID  Name                                      Identifier
-----  ----------------------------------------  --------------------------------------
  766  Android System                            android
21228  Attack me if u can                        sg.vp.owasp_mobile.omtg_android
 4281  Termux                                    com.termux
    -  Uncrackable1                              sg.vantagepoint.uncrackable1

请注意,这还显示了当前正在运行的应用程序的 PID。记下“标识符”和 PID(如果有的话),因为以后您将需要它们。

探索应用程序包

一旦您收集了您想要定位的应用程序的包名称,您就需要开始收集有关它的信息。首先,按照“基本测试操作 - 获取和提取应用程序”中的说明检索 APK。

 

APK 文件实际上是可以使用标准解压缩器解压缩的 ZIP 文件:

1
2
3
4
5
6
7
8
9
$ unzip base.apk
$ ls -lah
-rw-r--r--   1 sven  staff    11K Dec  5 14:45 AndroidManifest.xml
drwxr-xr-x   5 sven  staff   170B Dec  5 16:18 META-INF
drwxr-xr-x   6 sven  staff   204B Dec  5 16:17 assets
-rw-r--r--   1 sven  staff   3.5M Dec  5 14:41 classes.dex
drwxr-xr-x   3 sven  staff   102B Dec  5 16:18 lib
drwxr-xr-27 sven  staff   918B Dec  5 16:17 res
-rw-r--r--   1 sven  staff   241K Dec  5 14:45 resources.arsc

以下是apk解压出来的文件:

  • AndroidManifest.xml:包含应用的包名、目标和最低API级别、应用配置、应用组件、权限等的定义。

  • META-INF:包含应用的元数据

    • MANIFEST.MF:存储应用资源的哈希值

    • CERT.RSA:应用程序的证书

    • CERT.SF:资源列表和 MANIFEST.MF 文件中相应行的 SHA-1 摘要

  • assets:包含应用资源的目录(Android 应用中使用的文件,例如 XML 文件、JavaScript 文件和图片),AssetManager可以检索该目录

  • classes.dex:编译成DEX文件格式的类,Dalvik虚拟机/ART虚拟机可以处理。DEX 是 Dalvik 虚拟机的字节码。它针对小型设备进行了优化

  • lib:包含APK一部分第三方库的目录。

  • res:包含尚未编译到 resources.arsc 中的资源的目录

  • resources.arsc:包含预编译资源的文件,例如布局的 XML 文件

由于使用标准unzip实用程序解压缩会留下一些文件,例如AndroidManifest.xml无法读取的文件,因此您最好使用 apktool 解压缩 APK,如“推荐工具 - apktool”中所述。解包结果为:

1
2
3
4
5
6
7
8
9
10
11
$ ls -alh
total 32
drwxr-xr-x    9 sven  staff   306B Dec  5 16:29 .
drwxr-xr-x    5 sven  staff   170B Dec  5 16:29 ..
-rw-r--r--    1 sven  staff    10K Dec  5 16:29 AndroidManifest.xml
-rw-r--r--    1 sven  staff   401B Dec  5 16:29 apktool.yml
drwxr-xr-x    6 sven  staff   204B Dec  5 16:29 assets
drwxr-xr-x    3 sven  staff   102B Dec  5 16:29 lib
drwxr-xr-x    4 sven  staff   136B Dec  5 16:29 original
drwxr-xr-131 sven  staff   4.3K Dec  5 16:29 res
drwxr-xr-x    9 sven  staff   306B Dec  5 16:29 smali

The Android Manifest

 

Android Manifest 是主要的信息来源,它包含了很多有趣的信息,如包名、权限、应用组件等。

 

以下是一些信息和相应关键字的非详尽列表,您可以通过查看文件或使用grep -i <keyword> AndroidManifest.xml在Android Manifest中轻松搜索:

  • 应用权限:permission(参见“Android 平台 API”)

  • 备份限额:android:allowBackup(请参阅“Android 上的数据存储”)

  • 应用组件:activity, service, provider, receiver(参见“Android 平台 API”和“Android 上的数据存储”)

  • 可调试标志:debuggable(参见“Android 应用程序的代码质量和构建设置”)

请参阅上述章节以了解有关如何测试每个点的更多信息。

 

应用程序二进制

 

如上面“探索应用程序包”中所见,应用程序二进制文件 ( classes.dex) 可以在应用程序包的根目录中找到。它是一个所谓的 DEX(Dalvik Executable)文件,其中包含已编译的 Java 代码。由于其性质,在使用一些转换工具后,您将能够使用反编译器生成 Java 代码。我们还看到了运行 apktool 后获得的文件夹smali。这包含了反汇编 Dalvik 字节码,也就是被称为 smali 的中间语言,这是 Dalvik 可执行文件的可读表示。

 

有关如何对 DEX 文件进行逆向工程的更多信息,请参阅“ Android 上的篡改和逆向工程”一章中的“查看反编译的 Java 代码”部分。

 

Native库

 

您可以在APK 中检索lib文件夹:

1
2
3
4
5
$ ls -1 lib/armeabi/
libdatabase_sqlcipher.so
libnative.so
libsqlcipher_android.so
libstlport_shared.so

或来自有objection的设备:

1
2
3
4
5
6
7
...g.vp.owasp_mobile.omtg_android on (google: 8.1.0) [usb] # ls lib
Type    ...  Name
------  ...  ------------------------
File    ...  libnative.so
File    ...  libdatabase_sqlcipher.so
File    ...  libstlport_shared.so
File    ...  libsqlcipher_android.so

目前,这是您可以获得的有关native库的所有信息,除非您对它们进行逆向,这与逆向不同的是,此代码无法反编译而只能反汇编。有关如何对这些库进行逆向的更多信息,请参阅“ Android 上的篡改和逆向工程”一章中的“查看反汇编原生代码”部分。

 

其他应用资源

 

通常值得看看在 APK 的根目录中找到的其他资源和文件,因为有时它们包含额外的东西,例如密钥存储、加密数据库、证书等。

访问应用程序数据目录

安装应用程序后,还有更多信息可供探索,像objection等工具会派上用场。

 

使用objection时,您可以检索不同类型的信息,其中env将显示应用程序的所有目录信息。

1
2
3
4
5
6
7
8
9
10
11
12
$ objection -g sg.vp.owasp_mobile.omtg_android explore
 
...g.vp.owasp_mobile.omtg_android on (google: 8.1.0) [usb] # env
 
Name                    Path
----------------------  ---------------------------------------------------------------
cacheDirectory          /data/user/0/sg.vp.owasp_mobile.omtg_android/cache
codeCacheDirectory      /data/user/0/sg.vp.owasp_mobile.omtg_android/code_cache
externalCacheDirectory  /storage/emulated/0/Android/data/sg.vp.owasp_mobile.omtg_android/cache
filesDirectory          /data/user/0/sg.vp.owasp_mobile.omtg_android/files
obbDir                  /storage/emulated/0/Android/obb/sg.vp.owasp_mobile.omtg_android
packageCodePath         /data/app/sg.vp.owasp_mobile.omtg_android-kR0ovWl9eoU_yh0jPJ9caQ==/base.apk

在这些信息中,我们发现:

  • 位于/data/data/[package-name]/data/user/0/[package-name]的内部数据目录(又名沙箱目录)
  • 位于/storage/emulated/0/Android/data/[package-name]/sdcard/Android/data/[package-name]的外部数据目录
  • 应用程序包的路径/data/app/

应用程序使用内部数据目录来存储运行时创建的数据,其基本结构如下:

1
2
3
4
5
6
7
8
9
10
11
...g.vp.owasp_mobile.omtg_android on (google: 8.1.0)  [usb] # ls
Type       ...  Name
---------  ...  -------------------
Directory  ...  cache
Directory  ...  code_cache
Directory  ...  lib
Directory  ...  shared_prefs
Directory  ...  files
Directory  ...  databases
 
Readable: True  Writable: True

每个文件夹都有自己的用途:

  • cache:此位置用于数据缓存。例如,在此目录中可以找到 WebView 缓存。

  • code_cache :这是应用程序特定缓存目录的位置,用于存储缓存代码。在运行 Android 5.0(API 级别 21)或更高版本的设备上,当应用程序或整个平台升级时,系统将删除存储在此位置的所有文件。

  • lib :此文件夹存储用 C/C++ 编写的native库。这些库可以具有多个文件扩展名,包括 .so 和 .dll(x86 支持)。此文件夹包含许多子目录,这些子目录特定于平台,包括

    • armeabi:所有基于 ARM 处理器的编译代码

    • armeabi-v7a:所有基于 ARM 处理器的编译代码,仅版本 7 及更高版本

    • arm64-v8a:所有基于 64 位 ARM 处理器译代码,仅版本 8 及更高版本

    • x86:仅适用于 x86 处理器的编译代码

    • x86_64:仅适用于 x86_64 处理器的编译代码

    • mips:MIPS 处理器的编译代码

  • shared_prefs :此文件夹包含一个 XML 文件,该文件存储通过SharedPreferences API保存的值。

  • files :此文件夹存储应用程序创建的常规文件。

  • databases :此文件夹存储应用程序在运行时生成的 SQLite 数据库文件,例如用户数据文件。

但是,应用程序可能不仅会在这些文件夹中存储更多数据,还会在父文件夹(/data/data/[package-name]) 中存储更多数据。

 

有关安全存储敏感数据的更多信息和最佳实践,请参阅“测试数据存储”一章。

监控系统日志

在Android上,你可以通过使用Logcat轻松地查看系统日志。有两种方法来执行Logcat。

  • Logcat 是 Android Studio 中Dalvik 调试监控服务器(DDMS,Dalvik Debug Monitor Server) 的一部分。如果应用程序在调试模式下运行,日志输出将显示在 Android Monitor 的 Logcat 选项卡上。您可以通过在 Logcat 中定义模式来过滤应用程序的日志输出。
    图片描述
  • 您可以使用 adb 执行 Logcat 以永久存储日志输出:
1
$ adb logcat > logcat.log

使用以下grep命令,您可以专门过滤应用程序范围内的日志输出,只需插入包名称即可。当然,您的应用程序需要运行ps才能获得其 PID。

1
$ adb logcat | grep "$(adb shell ps | grep <package-name> | awk '{print $2}')"

设置网络测试环境

基本网络监控/嗅探

使用tcpdump、 netcat (nc) 和Wireshark可以实时远程嗅探所有Android流量。首先,确保您的手机上安装了最新版本的Android tcpdump。以下是安装步骤

1
2
3
$ adb root
$ adb remount
$ adb push /wherever/you/put/tcpdump /system/xbin/tcpdump

如果执行adb root返回错误adbd cannot run as root in production builds,请按如下方式安装 tcpdump:

1
2
3
4
5
6
7
$ adb push /wherever/you/put/tcpdump /data/local/tmp/tcpdump
$ adb shell
$ su
$ mount -o rw,remount /system;
$ cp /data/local/tmp/tcpdump /system/xbin/
$ cd /system/xbin
$ chmod 755 tcpdump

在某些生产版本中,您可能会遇到错误mount: '/system' not in /proc/mounts

 

在这种情况下,您可以将上述行替换为$ mount -o rw,remount /system;$ mount -o rw,remount /Stack Overflow 帖子中所述。

请记住:要使用 tcpdump,您需要手机上的 root 权限!

 

执行tcpdump一次,看看它是否有效。一旦有几个数据包进来,您可以通过按 CTRL+c 来停止 tcpdump。

1
2
3
4
5
6
7
8
9
10
$ tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wlan0, link-type EN10MB (Ethernet), capture size 262144 bytes
04:54:06.590751 00:9e:1e:10:7f:69 (oui Unknown) > Broadcast, RRCP-0x23 reply
04:54:09.659658 00:9e:1e:10:7f:69 (oui Unknown) > Broadcast, RRCP-0x23 reply
04:54:10.579795 00:9e:1e:10:7f:69 (oui Unknown) > Broadcast, RRCP-0x23 reply
^C
3 packets captured
3 packets received by filter
0 packets dropped by kernel

要远程嗅探 Android 手机的网络流量,首先执行tcpdump并将其输出通过管道传输到netcat(nc):

1
$ tcpdump -i wlan0 -s0 -w - | nc -l -p 11111

上面的 tcpdump 命令涉及

  • 监听 wlan0 接口

  • 以字节为单位定义捕获的大小(快照长度)以获取所有内容(-s0)

  • 以及写入文件(-w)。我们传递的是文件而不是文件名,-这将使 tcpdump 写入标准输出。

通过使用管道 ( |),我们将 tcpdump 的所有输出发送到 netcat,它会在端口 11111 上打开一个侦听器。您通常需要监视 wlan0 接口。如果您需要其他界面,请使用命令$ ip addr列出可用选项。

 

要访问端口 11111,您需要通过 adb 将该端口转发到您的主机。

1
$ adb forward tcp:11111 tcp:11111

以下命令通过 netcat 将您连接到转发端口并通过管道连接到 Wireshark。

1
$ nc localhost 11111 | wireshark -k -S -i -

Wireshark 立即启动 (-k)。它从标准输入 (-i -) 获取所有数据,这些数据是netcat连接转发端口流过来的。您应该可以看到来自 wlan0 接口的所有手机流量。
图片描述
您可以使用 Wireshark 以人类可读的格式显示捕获的流量。弄清楚使用了哪些协议以及它们是否未加密。捕获所有流量(TCP 和 UDP)很重要,因此您应该执行测试应用程序的所有功能并对其进行分析。

 

图片描述

 

这个巧妙的小技巧现在可以让您确定使用了哪种协议以及应用程序正在与哪些端点通信。现在的问题是,如果 Burp 无法显示流量,我该如何测试端点?对此没有简单的答案,但一些 Burp 插件可以帮助您入门。

Firebase/Google Cloud Messaging (FCM/GCM)

Firebase Cloud Messaging (FCM) 是 Google Cloud Messaging (GCM) 的继承者,是 Google 提供的一项免费服务,可让您在应用程序服务器和客户端应用程序之间发送消息。服务器和客户端应用程序通过 FCM/GCM Connection Server进行通信,该服务器处理下游和上游消息。
图片描述
Downstream Message(推送通知)从应用服务器发送到客户端应用;Upstream Message从客户端应用程序发送到服务器。
FCM 适用于 Android、iOS 和 Chrome。FCM 目前提供两种Connection Server协议:HTTP 和 XMPP。如官方文档中所述,这些协议的实现方式不同。以下示例演示了如何拦截这两种协议。

 

测试设置准备

 

您需要在手机上配置 iptables 或使用 bettercap 来拦截流量。

 

FCM 可以使用 XMPP 或 HTTP 与 Google 后端进行通信。

 

HTTP

 

FCM 使用端口 5228、5229 和 5230 进行 HTTP 通信。通常只使用端口 5228。

  • 为 FCM 使用的端口配置本地端口转发。以下示例适用于 macOS:
1
2
3
4
5
$ echo "
rdr pass inet proto tcp from any to any port 5228-> 127.0.0.1 port 8080
rdr pass inet proto tcp from any to any port 5229 -> 127.0.0.1 port 8080
rdr pass inet proto tcp from any to any port 5230 -> 127.0.0.1 port 8080
" | sudo pfctl -ef -
  • 拦截代理必须监听上面端口转发规则中指定的端口(8080端口)。

XMPP

 

对于 XMPP 通信,FCM 使用端口5235(生产)和 5236(测试)。

  • 为 FCM 使用的端口配置本地端口转发。以下示例适用于 macOS:
1
2
3
4
$ echo "
rdr pass inet proto tcp from any to any port 5235-> 127.0.0.1 port 8080
rdr pass inet proto tcp from any to any port 5236 -> 127.0.0.1 port 8080
" | sudo pfctl -ef -

拦截请求

 

拦截代理必须监听上面端口转发规则中指定的端口(8080端口)。

 

启动应用并触发使用 FCM 的函数。您应该在拦截代理中看到 HTTP 消息。
图片描述

 

推送通知的端到端加密

 

作为额外的安全层,可以使用Capillary对推送通知进行加密。Capillary 是一个库,可以基于 Java 的应用程序服务器到 Android 客户端的端到端 (E2E) 加密,并用于简化推送消息的发送。

设置拦截代理

一些工具支持对HTTP(S) 协议的网络分析。 OWASP ZAPBurp Suite Professional 是最著名的拦截网络流量工具。拦截代理为测试人员提供了一个中间人的位置。这个位置对于读取或修改所有应用程序请求和响应很有用,这些请求和响应用于测试授权、会话、管理等。

虚拟设备的拦截代理

在 Android 虚拟设备 (AVD) 上设置 Web 代理

 

以下过程适用于 Android Studio 3.x 附带的 Android 模拟器,用于在模拟器上设置 HTTP 代理:

  1. 设置您的代理以侦听本地主机,例如端口 8080。

  2. 在模拟器设置中配置 HTTP 代理:

  • 点击模拟器菜单栏中的三个点

  • 打开设置菜单

  • 单击代理选项卡

  • 选择手动代理配置

  • 在主机名字段中输入“127.0.0.1”,在端口号字段中输入您的代理端口(例如,“8080”)

  • 点击应用

    图片描述

HTTP 和 HTTPS 请求现在应该通过主机上的代理进行路由。如果没有,请尝试关闭和打开飞行模式。

 

也可以在启动 AVD 时使用emulator 命令在命令行上配置 AVD 的代理。以下示例启动 AVD Nexus_5X_API_23 并将代理设置为 127.0.0.1 和端口 8080。

1
$ emulator @Nexus_5X_API_23 -http-proxy 127.0.0.1:8080

在虚拟设备上安装 CA 证书

 

安装 CA 证书的一种简单方法是将证书推送到设备并通过安全设置将其添加到证书存储库中。例如,您可以按如下方式安装 PortSwigger (Burp) CA 证书:

  1. 启动 Burp 并使用主机上的 Web 浏览器导航到 burp/,然后cacert.der单击“CA 证书”按钮下载。

  2. 将文件扩展名从 更改.der.cer.

  3. 将文件推送到模拟器:

    1
    $ adb push cacert.cer /sdcard/
  4. 导航到设置->安全->从 SD 卡安装

  5. 向下滚动并点击cacert.cer

然后系统会提示您确认安装证书(如果您还没有设置设备 PIN,系统还会要求您设置 PIN)。

 

对于 Android 7.0(API 级别 24)及更高版本,请遵循“绕过网络安全配置”部分中描述的相同过程。

物理设备的拦截代理

首先必须评估可用的网络设置选项。用于测试的移动设备和运行拦截代理的主机必须连接到同一个Wi-Fi网络。使用(现有)接入点或开热点

 

配置网络并在测试主机和移动设备之间建立连接后,还需要几个步骤。

  • 代理必须被配置为指向拦截代理

  • 拦截代理的CA 证书必须添加到 Android 设备证书存储库中的受信任证书中。用于存储 CA 证书的菜单的位置可能取决于 Android 版本和 Android OEM 对设置菜单的修改。

  • 如果叶证书的有效期恰好延长了一定时间(Chrome 为 39 个月),某些应用程序(例如Chrome 浏览器)可能会显示NET::ERR_CERT_VALIDITY_TOO_LONG错误。如果使用默认 Burp CA 证书,则会发生这种情况,因为 Burp Suite 颁发的叶证书与其 CA 证书具有相同的有效性。您可以通过创建自己的 CA 证书并将其导入 Burp Suite 来规避此问题,如本博客中所述。

完成这些步骤并启动应用程序后,请求应显示在拦截代理中。

可以在secure.force.com上找到使用 Android 设备设置OWASP ZAP的视频。

 

其他一些差异:

  • 从 Android 8.0(API 级别 26)开始,当 HTTPS 流量通过另一个连接进行隧道传输时,应用程序的网络行为会发生变化。
  • 从 Android 9(API 级别 28)开始,当握手期间出现问题时,SSLSocket 和 SSLEngine 在错误处理方面的表现会有所不同。

如前所述,从 Android 7.0(API 级别 24)开始,Android 操作系统将默认不再信任用户 CA 证书,除非在应用程序中指定。在下一节中,我们将解释绕过此 Android 安全控制的两种方法。

绕过网络安全配置

从 Android 7.0(API 级别 24)开始,网络安全配置允许应用通过定义应用信任的 CA 证书来自定义其网络安全设置。

 

为了实现应用程序的网络安全配置,您需要创建一个名为 .xml 的新 xml 资源文件network_security_config.xml。这在Android 网络安全配置培训中有详细说明。

 

创建后,应用程序还必须在清单文件中包含一个条目以指向新的网络安全配置文件。

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application android:networkSecurityConfig="@xml/network_security_config"
                    ... >
        ...
    </application>
</manifest>

网络安全配置使用一个 XML 文件,应用程序在该文件中指定哪些 CA 证书是受信任的。有多种方法可以绕过网络安全配置,下文将对此进行介绍。另请参阅Android P 中的网络安全配置安全分析师指南以获取更多信息。

 

将用户证书添加到网络安全配置

 

网络安全配置有不同的配置可用于通过 src 属性添加非系统证书颁发机构:

1
2
<certificates src=["system" | "user" | "raw resource"]
              overridePins=["true" | "false"] />

每个证书可以是以下之一:

  • 指向包含 X.509 证书文件的“raw resource”ID

  • "system" 用于预安装的系统 CA 证书

  • "user" 用于用户添加的 CA 证书

应用信任的 CA 证书可以是系统信任的 CA,也可以是用户 CA。通常,您已经将拦截代理的证书添加为 Android 中的附加 CA。因此,我们将重点关注“用户”设置,它允许您通过以下网络安全配置强制Android 应用信任此证书:

1
2
3
4
5
6
7
8
<network-security-config>
   <base-config>
      <trust-anchors>
          <certificates src="system" />
          <certificates src="user" />
      </trust-anchors>
   </base-config>
</network-security-config>

要实施此新设置,您必须按照以下步骤操作:

  • 使用 apktool 之类的反编译工具反编译应用程序:

    1
    $ apktool d <filename>.apk
  • 通过创建包含<certificates src="user" />如上所述的网络安全配置来使应用程序信任用户证书

  • 在反编译应用程序时进入apktool创建的目录并使用apktool重新构建应用程序。新的 apk 将在dist目录中。

    1
    $ apktool b
  • 您需要重新打包应用程序,如“逆向工程和篡改”一章的“重新打包”部分所述。有关重新打包过程的更多详细信息,您还可以查阅Android 开发者文档,该文档对整个过程进行了说明。

请注意,即使此方法非常简单,但它的主要缺点是您必须为要评估的每个应用程序执行此操作,这是测试的额外开销。

请记住,如果您正在测试的应用程序具有其他强化措施,例如验证应用程序签名,您可能无法再启动该应用程序。作为重新打包的一部分,您将使用自己的密钥对应用程序进行签名,因此签名更改触发应用程序立即终止。您需要通过在重新打包应用程序期间修补它们或通过 Frida 进行动态检测来识别和禁用此类检查。

 

有一个可用的 python 脚本可以自动执行上述步骤,称为Android-CertKiller。此 Python 脚本可以从已安装的 Android 应用程序中提取 APK,对其进行反编译,使其可调试,添加允许用户证书的新网络安全配置,构建和签名新 APK,并使用 SSL 绕过安装新 APK。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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 中的默认格式),然后运行以下命令:

    1
    2
    3
    $ 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 中,然后运行以下命令:

    1
    chmod 644 <hash>.0

按照上面描述的步骤,您允许任何应用程序信任代理的证书,这允许您拦截其流量,除非应用程序使用 SSL pinning。

潜在障碍

应用程序通常会实施安全控制,这使得对应用程序执行安全审查变得更加困难,例如root检测和证书锁定。理想情况下,你会同时获得一个启用了这些控件的应用程序的版本,以及一个禁用了这些控件的版本。这使你能够分析控制的正确实施,然后你可以继续使用不那么安全的版本进行进一步的测试。

 

当然,这并不总是可行的,您可能需要对启用了所有安全控制的应用程序执行黑盒评估。以下部分向您展示了如何规避针对不同应用程序的证书锁定。

无线网络中的客户端隔离

一旦您设置了拦截代理并拥有 MITM 位置,您可能仍然看不到任何东西。这可能是由于应用程序中的限制(请参阅下一节),但也可能是由于您所连接的 Wi-Fi 中所谓的客户端隔离。

 

无线客户端隔离是一种安全功能,可防止无线客户端相互通信。此功能对于访客和 BYOD SSID 非常有用,可以增加安全级别以限制连接到无线网络的设备之间的攻击和威胁。

 

如果我们需要测试的Wi-Fi有客户端隔离怎么办?

 

您可以在 Android 设备上配置代理指向 127.0.0.1:8080,通过 USB 将手机连接到主机并使用 adb 进行反向端口转发:

1
$ 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 上运行的代理

1
$ iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination <Your-Proxy-IP>:8080

验证 iptables 设置并检查 IP 和端口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ 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 配置,你可以刷新规则:

1
$ iptables -t nat -F

bettercap

 

阅读“测试网络通信”一章和测试用例“模拟中间人攻击”,了解运行 bettercap 的进一步准备和说明。

 

运行代理的主机和 Android 设备必须连接到同一个无线网络。使用以下命令启动 bettercap,将下面的 IP 地址 (XXXX) 替换为您的 Android 设备的 IP 地址。

1
2
3
4
5
$ 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 或配置不需要在 Android 手机上设置代理的 iptables。我们之前没有提到的第三个选项,它适用于这个场景是使用 Frida。在 Android 上,可以通过查询ProxyInfo类并检查 getHost() 和 getPort() 方法来检测是否设置了系统代理。可能有多种其他方法可以完成相同的任务,您需要反编译 APK 才能识别具体的类和方法名称。

 

您可以在下面找到 Frida 脚本的样本源代码,该脚本将帮助您重载用于验证是否设置了代理并始终返回 false 的方法(在本例中称为 isProxySet)。即使现在配置了代理,应用程序现在也会认为没有设置任何代理,因为函数返回 false。

1
2
3
4
5
6
7
8
9
10
11
12
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
        }
    });
});

证书固定

某些应用程序将实施 SSL Pinning,这会阻止应用程序接受您的拦截证书作为有效证书。这意味着您将无法监控应用程序和服务器之间的流量。

 

有关静态和动态禁用 SSL 固定的信息,请参阅“测试网络通信”一章中的“绕过 SSL 固定”。

参考

  • 手动签名(Android 开发者文档) - https://developer.android.com/studio/publish/app-signing#signing-manually

  • 自定义信任 - https://developer.android.com/training/articles/security-config#CustomTrust

  • Android 网络安全配置培训 - https://developer.android.com/training/articles/security-config

  • Android P 中的网络安全配置安全分析师指南 - https://www.nowsecure.com/blog/2018/08/15/a-security-analysts-guide-to-network-security-configuration-in-android-p /

  • Android 开发者文档 - https://developer.android.com/studio/publish/app-signing#signing-manually

  • Android 8.0 行为变化 - https://developer.android.com/about/versions/oreo/android-8.0-changes

  • Android 9.0 行为变化 - https://developer.android.com/about/versions/pie/android-9.0-changes-all#device-security-changes

  • 代号、标签和内部版本号 - https://source.android.com/setup/start/build-numbers

  • 创建和管理虚拟设备 - https://developer.android.com/studio/run/managing-avds.html

  • 移动设备生根指南 - https://www.xda-developers.com/root/

  • API 级别 - https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels

  • AssetManager - https://developer.android.com/reference/android/content/res/AssetManager

  • SharedPreferences API - https://developer.android.com/training/basics/data-storage/shared-preferences.html

  • 使用 Logcat 进行调试 - https://developer.android.com/tools/debugging/debugging-log.html

  • Android 的 APK 格式 - https://en.wikipedia.org/wiki/Android_application_package

  • 使用 Tcpdump、nc 和 Wireshark 进行 Android 远程嗅探 - https://blog.dornea.nu/2015/02/20/android-remote-sniffing-using-tcpdump-nc-and-wireshark/

  • 无线客户端隔离 - https://documentation.meraki.com/MR/Firewall_and_Traffic_Shaping/Wireless_Client_Isolation


[2023春季班]《安卓高级研修班(网课)》月薪两万班招生中~

最后于 2022-9-22 11:19 被阿涌配个蛋编辑 ,原因: 图片挂了
收藏
点赞5
打赏
分享
最新回复 (5)
雪    币: 277
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
TrumpWY 活跃值 2022-9-1 13:38
2
0
巨佬
雪    币: 1891
活跃值: 活跃值 (148)
能力值: (RANK:0 )
在线值:
发帖
回帖
粉丝
赛文奥特曼 活跃值 2022-9-1 14:33
3
0
大佬好文章
雪    币: 524
活跃值: 活跃值 (636)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
克里斯托夫 活跃值 2022-9-13 07:49
4
0
多谢分享
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_wkdbwlwc 活跃值 2022-9-22 11:15
5
0
请问大佬 翻译的原文是哪篇啊? 有链接么? 
雪    币: 137
活跃值: 活跃值 (191)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Jnj3369 活跃值 2022-10-3 19:55
6
0
很有趣的文章啊.谢谢!
游客
登录 | 注册 方可回帖
返回