Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

フィードお問い合わせプライバシー© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
ResourcePoison — CVE-2025-22441のライトアップとエクスプロイト:Androidでインストール済みアプリからSystemUIプロセスへの権限昇格。信頼されていないApplicationInfoがLoadedApkに渡されることが原因。 | Kitploit
ツール/GitHubGitHub/michalbednarski/resourcepoison
Androidセキュリティ特権昇格脆弱性分析エクスプロイトモバイルセキュリティ論文と研究
GitHubmichalbednarski/resourcepoison

ResourcePoison

CVE-2025-22441のライトアップとエクスプロイト:Androidでインストール済みアプリからSystemUIプロセスへの権限昇格。信頼されていないApplicationInfoがLoadedApkに渡されることが原因。

リポジトリを見る
10829630年前Kitploit レビュー済み

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

この問題の修正はCVE-2025-22441として公開されています: bulletin patch follow up

ApplicationInfoの受け渡し

ApplicationInfoは、インストールされたアプリに関するさまざまな情報を定義する構造体であり、特にリソースとコードが読み込まれるAPKファイルへのパスが最も重要です。

通常はシステムからアプリケーションへ渡されますが、システム以外の呼び出し元が独自のものを提供できるケースが存在することもあります。例えば過去には、bindBackupAgent()メソッドの脆弱性があり、攻撃者がuidとsourceDirの値を持つ独自のApplicationInfoオブジェクトをパラメータとして渡せたものの、それらがシステムに実際にインストールされているアプリと照合されていませんでした。このメソッドはsystem_serverによって内部的に呼び出されることを想定していましたが、adb shellに公開されていました。

今回は、RemoteViews内のApplicationInfoフィールドを詳しく調査しました。

RemoteViewsは、別のプロセスから取得できるビューを記述するオブジェクトです。これは特にホーム画面ウィジェットに使用され、ウィジェットを提供するアプリがRemoteViewsを構築し、それがホーム画面プロセス内で"適用"されます。

RemoteViewsが使用される他の場所としては、通知(SystemUIプロセスによって適用)やオートフィルダイアログ(オートフィルサービスによって提供され、system_serverによって適用)があります。

RemoteViews.mApplicationフィールドはParcelを通じてシリアライズされるため、リモートプロセスから取得される可能性があり、RemoteViewsが適用されるたびに以下のメソッドで使用されます(ソーススニペット):```java private Context getContextForResourcesEnsuringCorrectCachedApkPaths(Context context) { if (mApplication != null) { if (context.getUserId() == UserHandle.getUserId(mApplication.uid) && context.getPackageName().equals(mApplication.packageName)) { return context; } try { LoadedApk.checkAndUpdateApkPaths(mApplication); return context.createApplicationContext(mApplication, Context.CONTEXT_RESTRICTED); } catch (NameNotFoundException e) { Log.e(LOG_TAG, "Package name " + mApplication.packageName + " not found"); } }

return context;

}

ここで最も興味深いのは、`LoadedApk.checkAndUpdateApkPaths()` の呼び出しです。これは静的メソッドであり、いくつかのグローバル状態を変更します [(スニペットのソース)](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/java/android/app/LoadedApk.java;l=2275-2302;drc=5916ee589c4880e2d8a1a9ad6dc852108e4c44c1)```java
public static void checkAndUpdateApkPaths(ApplicationInfo expectedAppInfo) {
    // Get the LoadedApk from the cache
    ActivityThread activityThread = ActivityThread.currentActivityThread();
    if (activityThread == null) {
        Log.e(TAG, "Cannot find activity thread");
        return;
    }
    checkAndUpdateApkPaths(activityThread, expectedAppInfo, /* cacheWithCode */ true);
    checkAndUpdateApkPaths(activityThread, expectedAppInfo, /* cacheWithCode */ false);
}

private static void checkAndUpdateApkPaths(ActivityThread activityThread,
        ApplicationInfo expectedAppInfo, boolean cacheWithCode) {
    String expectedCodePath = expectedAppInfo.getCodePath();
    LoadedApk loadedApk = activityThread.peekPackageInfo(
            expectedAppInfo.packageName, /* includeCode= */ cacheWithCode);
    // If there is load apk cached, or if the cache is valid, don't do anything.
    if (loadedApk == null || loadedApk.getApplicationInfo() == null
            || loadedApk.getApplicationInfo().getCodePath().equals(expectedCodePath)) {
        return;
    }
    // Duplicate framework logic
    List<String> oldPaths = new ArrayList<>();
    LoadedApk.makePaths(activityThread, expectedAppInfo, oldPaths);

    // Force update the LoadedApk instance, which should update the reference in the cache
    loadedApk.updateApplicationInfo(expectedAppInfo, oldPaths);
}

これらのメソッドで何が行われているのか説明しましょう

まず、cacheWithCode をtrueとfalseの両方に設定して、3パラメータのcheckAndUpdateApkPathsを呼び出しています。LoadedApkオブジェクトは2つのモードで構築でき、mIncludeCodeがtrueかfalseのいずれかになります。これはSDK的には、CONTEXT_INCLUDE_CODEフラグが設定されたContextかどうかに対応します

そのメソッドはまずActivityThread.peekPackageInfo()を使用します。これはすでにキャッシュされたLoadedApkインスタンスを返すため、アプリが以前に一致するpackageNameとincludeCodeでLoadedApkを構築していなければ、peekPackageInfo()はnullを返し、checkAndUpdateApkPaths()は何も行いません

RemoteViews.getContextForResourcesEnsuringCorrectCachedApkPaths()に戻ると、そこにはcontext.createApplicationContext(mApplication, Context.CONTEXT_RESTRICTED)があります。CONTEXT_INCLUDE_CODEフラグは指定されておらず(そのメソッドに引数として渡されるコンテキストも同様)、そのためそのメソッドは常にmIncludeCode=falseのLoadedApkを使用します

したがって、RemoteViewsの更新バージョンにコードを含める必要はありません。RemoteViewsは常にコードなしのContextを使用するためです。コミットメッセージには、ApplicationInfoがキャッシュされる場所が2つあるとだけ記載されており、コード付きでバージョンを更新する処理を削除してもここでは問題は発生しないと思います(checkAndUpdateApkPaths()はAppWidgetHostViewとRemoteViewsでのみ使用されるため)。ただし、これに対する反論としては、さまざまなキャッシュが同期されなくなる可能性を回避できるという点があり、cacheWithCode=trueでの呼び出しを削除することでこのバグの最も深刻な影響は取り除かれますが、コードではなくリソースのみの変更が攻撃者にとって依然として価値がある可能性があるため、問題を完全に修正するわけではありません

LoadedApk.updateApplicationInfo()

これまでに示したコードはRemoteViews(ウィジェット、通知など)でのみ使用されますが、ここからは新しいスプリットがインストールされた後に実行中のアプリプロセスを更新するためにも使用されるLoadedApk.updateApplicationInfo()に入ります(たとえば、Play Feature Deliveryのオンデマンド配信を使用する場合など)

ツールをダウンロード