コンテンツにスキップ

Application code not obfuscated

アプリケーションコードが難読化されていません

説明

難読化とは、コードを隠蔽し、理解を困難にするための手法を指します。コンパイルされた Java クラスは、コンパイル段階で難読化が行われない場合、逆コンパイルされる可能性があります。アプリのコードとメタデータを変更することで、攻撃者がコードを理解し、脆弱性を導入したり悪意のある機能を追加したりするためにコードを変更することを困難にします。難読化ツールは通常、クラス、メソッド、変数の名前を意味のない名前に変更し、デバッグ情報を削除し、逆コンパイラを混乱させるためのダミーコードを追加することによって、これを実現します。

攻撃者は、コードや機密情報を盗んだり、アプリのセキュリティを侵害する脆弱性を導入したり、コードを転用して新しいアプリケーションで販売したり、初期のアプリケーションに基づいて悪意のある偽のアプリケーションを作成したりする可能性があります。 このコードが難読化されていない場合、Apktool や JADX などのツールを使用して簡単に逆コンパイルできます。

コードの難読化は、攻撃者によるリバースエンジニアリングを遅らせるだけであり、不可能にするわけではありません。

推奨事項

アプリケーションをリバースエンジニアリングの被害を受けにくくするために検討できる手順は以下のとおりです。

Proguard を使用して Java ソースコードを難読化する。

アプリケーションに Proguard を追加するには、build.gradle ファイルに以下を追加します。

buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

これにより、リリースビルドでのコード難読化に ProGuard を使用するように Gradle に指示します。その後、アプリの "app" ディレクトリに "proguard-rules.pro" ファイルを作成して、難読化ルールを設定できます。

proguard-rules.pro:

# このパッケージのクラス名を保持する
-keep class com.example.myapplication.** { *; }

# これらのクラスのすべてのpublicおよびprotectedメソッドを保持する
-keepclassmembers class com.example.myapplication.** {
    public protected *;
}

# すべてのネイティブメソッド名を保持する
-keepclassmembers class * {
    native <methods>;
}

# 指定された名前のすべてのフィールドを保持する
-keepclassmembers class * {
    private int myField;
}

# Parcelableを実装するすべてのクラスを保持する
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

# すべてのEnumクラスを保持する
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# すべてのアノテーションを保持する
-keepattributes *Annotation*

# すべてのエントリポイント (mainメソッドなど) を保持する
-keep public class * {
    public static void main(java.lang.String[]);
}

# すべてのSerializableクラスを保持する
-keep class * implements java.io.Serializable {
    *;
}

Dexguard を使用して Java ソースコードを難読化する。

アプリケーションで Dexguard を有効にするには、build.gradle ファイルに以下を追加します。

buildTypes {
        release {
            minifyEnabled true
            useProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            dexguard {
                config 'dexguard-release.cfg'
            }
        }
    }

これにより、リリースビルドでのコード難読化に DexGuard を使用するように Gradle に指示します。アプリの "app" ディレクトリに "dexguard-project.txt" ファイルを作成して DexGuard プロジェクトを設定し、"dexguard-release.cfg" ファイルを作成してリリースビルド用の難読化を設定できます。

デフォルトでは、DexGuard を使用してコードの難読化を有効にすると、ProGuard 構成ファイルで指定されたルールに加えて、独自の難読化ルールが使用されます。ただし、useProguard オプションを false に設定することで、ProGuard のルールの使用を無効にすることができます。

  • 実行時に context.getPackageManager().signature をチェックして、アプリケーション署名証明書を検証する
  • context.getPackageManager().getInstallerPackageName を呼び出して、アプリケーションインストーラをチェックし、Android Market と一致することを確認する
  • 実行時に実行環境をチェックする

アプリがエミュレータで実行されているかどうかをチェックする

アプリケーションに次のチェックを追加して、エミュレータで実行されているかどうかを検出できます。

private static String getSystemProperty(String name) throws Exception {
    Class systemPropertyClazz = Class.forName("android.os.SystemProperties");
    return (String) systemPropertyClazz.getMethod("get", new Class[] { String.class }).invoke(systemPropertyClazz, new Object[] { name });
}

public static boolean checkEmulator() {

    try {
        boolean goldfish = getSystemProperty("ro.hardware").contains("goldfish");
        boolean qemu = getSystemProperty("ro.kernel.qemu").length() > 0;
        boolean sdk = getSystemProperty("ro.product.model").equals("sdk");

        if (qemu || goldfish || sdk) {
            return true;
        }

    } catch (Exception e) {}

    return false;
}

実行時にデバッグフラグをチェックする

同様に、実行中にアプリケーションがデバッグモードになっているかどうかをチェックできます。

    context.getApplicationInfo().applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE;

リンク

標準

  • OWASP_MASVS_RESILIENCE:
    • MSTG_RESILIENCE_9
    • MSTG_RESILIENCE_12
  • PCI_STANDARDS:
    • REQ_2_2
  • OWASP_MASVS_v2_1:
    • MASVS_RESILIENCE_3
  • HIPAA_CONTROLS:
    • SECURITY212
    • SECURITY213
    • SECURITY255