対象:モバイルアプリエンジニア・セキュリティ研究者・CTFプレイヤー
第1章:Fridaで「何を見るか」── 動的解析の視点
Fridaは実行中のプロセスにJavaScriptコードを注入し、関数の呼び出し・引数・戻り値を監視・改ざんできる動的計装フレームワークです。Burp SuiteがHTTP通信を可視化するのに対し、Fridaは「アプリ内部の処理」を丸裸にします。
しかし、現代のアプリは数千〜数万の関数から成り立っています。すべての関数を追うのは不可能ですし、非効率です。Fridaを効果的に使うには「何を見るか」の優先順位を持つことが重要です。
- 1-1. Fridaで監視すべき「5つのカテゴリ」
- 1-2. frida-traceで「まず全体を把握する」
- 2-1. AndroidのJavax.crypto APIをフックする
- 2-2. ハードコードされた暗号鍵の発見
- 2-3. ハッシュ関数の監視(パスワード処理を追う)
- 3-1. SSL Pinningとは何か・なぜバイパスが必要か
- 3-2. 段階的なSSL Pinningバイパス
- 3-3. プレーンHTTP通信・Socketの傍受
- 4-1. ルート検出・エミュレーター検出のバイパス
- 4-2. 生体認証・PIN認証のバイパス
- 4-3. JWTトークンの実行時改ざん
- 5-1. SharedPreferencesの監視
- 5-2. SQLiteデータベースの操作を監視する
- 5-3. ファイルI/Oの監視
- 6-1. Frida診断の全体フロー
- 6-2. Pythonスクリプトで診断を自動化する
- 6-3. 実践チェックリスト
1-1. Fridaで監視すべき「5つのカテゴリ」
セキュリティ診断の観点から、Fridaで特に注目すべき処理は以下の5カテゴリに整理できます。
| カテゴリ | 対象となる処理・関数 | 診断で発見できる問題 |
| ① 暗号化・復号 | AES/RSA/Hash処理、鍵生成 | ハードコードされた鍵、弱い暗号アルゴリズム |
| ② 認証・認可 | ログイン、トークン検証、権限チェック | 認証バイパス、ルート検出回避 |
| ③ ネットワーク通信 | HTTP/HTTPS、Socket接続 | SSL Pinning回避、平文通信の発見 |
| ④ データ保存 | ファイルI/O、DB操作、SharedPreferences | 機密データの平文保存 |
| ⑤ 入力値・出力値 | ユーザー入力処理、ログ出力 | シークレットのログ漏洩、バリデーション不備 |
1-2. frida-traceで「まず全体を把握する」
診断対象のアプリを初めて触るとき、どのクラス・メソッドが呼ばれているかを把握するためにfrida-traceを使います。frida-traceはFridaに付属するCLIツールで、ワイルドカードで一致する全関数の呼び出しを自動ログします。
# Androidアプリ上の暗号化関連クラスをすべてトレース
frida-trace -U -j '*!*encrypt*' -j '*!*decrypt*' -j '*!*cipher*' -f com.example.app
# ネットワーク関連メソッドをトレース
frida-trace -U -j '*!*connect*' -j '*!*request*' -j '*!*send*' -f com.example.app
# ネイティブ関数(C/C++)のSSL関連をトレース
frida-trace -U -i 'SSL_*' -i 'BIO_*' -f com.example.app
frida-traceは一致した関数ごとに __handlers__/<クラス名>/<メソッド名>.js というJSファイルを自動生成します。この中に onEnter / onLeave を追記することで、引数・戻り値のログを追加できます。
💡 frida-traceの出力量が多すぎる場合は、-j ‘*!*AES*’ のようにより絞った文字列で検索するか、出力をファイルにリダイレクト(frida-trace … > trace.log)して後から分析します。
第2章:暗号化処理の解析 ── 鍵・アルゴリズムを暴く
モバイルアプリが扱う中で最も重要なのが暗号化処理です。APIキー、パスワード、セッショントークン──これらはアプリ内で暗号化・復号されます。Fridaでその瞬間を捉えれば、暗号化前の平文データや使われている鍵を取得できます。
2-1. AndroidのJavax.crypto APIをフックする
AndroidのJava層での暗号化は、ほぼ javax.crypto パッケージを通ります。このクラスをフックすれば、アプリが使う暗号アルゴリズム・鍵・平文データを一網打尽にできます。
// crypto_hook.js
// javax.crypto.Cipher の暗号化・復号をすべて傍受する
Java.perform(function () {
var Cipher = Java.use('javax.crypto.Cipher');
// doFinal(byte[]) ── 実際の暗号化/復号が行われるメソッド
Cipher.doFinal.overload('[B').implementation = function (input) {
var algorithm = this.getAlgorithm(); // 例: AES/CBC/PKCS5Padding
var opmode = this.getOpMode(); // 1=暗号化, 2=復号
var inputHex = bytesToHex(input);
console.log('\n[Cipher.doFinal] ─────────────────────────');
console.log(' Algorithm : ' + algorithm);
console.log(' Mode : ' + (opmode === 1 ? 'ENCRYPT' : 'DECRYPT'));
console.log(' Input : ' + inputHex);
var result = this.doFinal(input); // 元のメソッドを呼ぶ
console.log(' Output : ' + bytesToHex(result));
return result;
};
// Cipher.init() から鍵を取得する
Cipher.init.overload('int', 'java.security.Key').implementation = function (opmode, key) {
var keyBytes = key.getEncoded();
console.log(' Key : ' + bytesToHex(keyBytes)); // 鍵の生バイト
return this.init(opmode, key);
};
// バイト配列→16進数変換ユーティリティ
function bytesToHex(bytes) {
var hex = '';
for (var i = 0; i < bytes.length; i++) {
hex += ('0' + (bytes[i] & 0xFF).toString(16)).slice(-2);
}
return hex;
}
});
# スクリプトを適用
frida -U -f com.example.app -l crypto_hook.js --no-pause
⚠️ このスクリプトで取得した鍵・平文データは、自社アプリの診断や学習目的のみに使用してください。他者のアプリに対する無断使用は不正競争防止法・不正アクセス禁止法の対象となります。
2-2. ハードコードされた暗号鍵の発見
アプリのソースコード中に暗号鍵が直書きされている(ハードコード)ケースは、セキュリティ診断でよく見つかります。Fridaでこれを検出する手順を見てみましょう。
静的解析と動的解析の組み合わせ:
- ① jadx(Javaデコンパイラ)でAPKをデコンパイル
- ② AES・SECRET_KEY・KEY・password・token 等の文字列を検索
- ③ 怪しいバイト配列やBase64文字列を特定
- ④ Fridaでその変数を参照しているメソッドをフックして実行時の値を確認
// hardcoded_key_finder.js
// String クラスの equals メソッドをフックして秘密の比較値を探す
Java.perform(function () {
var String = Java.use('java.lang.String');
String.equals.implementation = function (other) {
var self = this.toString();
// 機密っぽいキーワードが含まれる比較だけをログ
if (self.length > 8 && /[A-Za-z0-9+/=]{16,}/.test(self)) {
console.log('[String.equals]');
console.log(' this : ' + self);
console.log(' other : ' + other.toString());
console.log(' stack : ' + Java.use('android.util.Log') .getStackTraceString(Java.use('java.lang.Exception').$new()));
}
return this.equals(other);
};
});
✅ ハードコードされた鍵はOWASP Mobile Top 10の「M1: Improper Credential Usage(不適切な認証情報の扱い)」に該当する重大な脆弱性です。発見したら必ず報告書に記載しましょう。
2-3. ハッシュ関数の監視(パスワード処理を追う)
ログイン処理では、パスワードをハッシュ化してサーバーに送ることが多いです。どのハッシュアルゴリズムが使われているか、ソルトはあるかを確認します。
// hash_monitor.js
Java.perform(function () {
var MessageDigest = Java.use('java.security.MessageDigest');
MessageDigest.getInstance.overload('java.lang.String').implementation = function (algo) {
console.log('[MessageDigest] Algorithm: ' + algo);
// MD5, SHA-1 は現代では脆弱。SHA-256以上を推奨
if (algo === 'MD5' || algo === 'SHA-1') {
console.log(' ⚠️ WEAK ALGORITHM DETECTED: ' + algo);
}
return this.getInstance(algo);
};
MessageDigest.digest.overload('[B').implementation = function (input) {
var inputStr = Java.use('java.lang.String').$new(input, 'UTF-8');
console.log('[MessageDigest.digest] Input (UTF-8): ' + inputStr);
var result = this.digest(input);
return result;
};
});
💡 MD5やSHA-1はハッシュの衝突攻撃が実証されており、パスワードのハッシュには不適切です。パスワードのハッシュにはBcrypt・Argon2・PBKDF2など、計算コストの高いKDF(鍵導出関数)を使うべきです。
第3章:ネットワーク通信の解析 ── SSL Pinningとプレーンソケット
アプリのネットワーク通信はセキュリティ診断において最重要項目の一つです。Fridaを使えば、SSLライブラリやHTTPクライアントをフックして、暗号化前・復号後のデータを取得できます。
3-1. SSL Pinningとは何か・なぜバイパスが必要か
SSL Pinning(証明書ピニング)とは、アプリが「自分が知っている証明書だけを信頼する」仕組みです。通常のHTTPS通信はOSが信頼する証明書なら何でも受け入れますが、SSL Pinningを実装したアプリはBurp SuiteのCA証明書を信頼しないため、通信を傍受しようとすると証明書エラーで弾かれます。
Fridaを使えば、この検証処理を実行時に無効化でき、Burp Suiteで通信内容を解析できるようになります。
| 実装方式 | 対象メソッド/クラス | Fridaでのバイパス難易度 |
| TrustManager(Java標準) | checkServerTrusted() | 低:1メソッドをフックするだけ |
| OkHttp CertificatePinner | CertificatePinner.check() | 低:checkメソッドを空実装に |
| Network Security Config | XMLファイル設定 | 中:TrustManagerを経由 |
| カスタムTrustManager | アプリ固有クラス | 中:クラス名を特定してフック |
| ネイティブ(C/C++)SSL | SSL_CTX_set_verify等 | 高:ネイティブ関数のフックが必要 |
3-2. 段階的なSSL Pinningバイパス
レベル1:TrustManager の完全無効化
// ssl_bypass_l1.js ── Java標準のTrustManager系
Java.perform(function () {
// X509TrustManager の証明書検証を無効化
var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
var SSLContext = Java.use('javax.net.ssl.SSLContext');
var TrustManager = Java.registerClass({
name: 'com.frida.TrustAllManager',
implements: [X509TrustManager],
methods: {
checkClientTrusted: function () {}, // 何もしない → 検証スキップ
checkServerTrusted: function () {}, // 何もしない → 検証スキップ
getAcceptedIssuers: function () { return []; }
}
});
SSLContext.init.implementation = function (keyManagers, trustManagers, secureRandom) {
var trustAll = [TrustManager.$new()];
this.init(keyManagers, trustAll, secureRandom); // 自製TrustManagerで上書き
};
console.log('[SSL Bypass L1] TrustManager overridden.');
});
レベル2:OkHttpのCertificatePinnerをバイパス
// ssl_bypass_l2.js ── OkHttp3 対応
Java.perform(function () {
// OkHttp3 の CertificatePinner.check をバイパス
try {
var CertPinner = Java.use('okhttp3.CertificatePinner');
CertPinner.check.overload('java.lang.String', 'java.util.List')
.implementation = function (hostname, peerCertificates) {
console.log('[CertPinner] Bypassed for: ' + hostname);
// return せずに何もしない → 検証スキップ
};
} catch(e) {
console.log('[CertPinner] OkHttp3 not found: ' + e);
}
});
レベル3:ネイティブ層のOpenSSL/BoringSSLをバイパス
React NativeやFlutterなど、ネイティブコードでHTTPSを実装しているアプリはJava層のフックでは対処できません。ネイティブ関数を直接フックします。
// ssl_bypass_native.js ── BoringSSL(Android標準)対応
var sslVerifyResult = null;
// SSL_CTX_set_custom_verify / SSL_get_error をフックするアプローチ
Interceptor.attach(Module.findExportByName('libssl.so', 'SSL_verify_peer_cert'), {
onEnter: function (args) {
console.log('[Native SSL] SSL_verify_peer_cert called');
},
onLeave: function (retval) {
retval.replace(1); // 強制的に成功(1)を返す
}
});
✅ Objection(Fridaベースのツール)を使えば、ほとんどのSSL Pinning実装を1コマンドでバイパスできます: objection -g com.example.app explore > android sslpinning disable
3-3. プレーンHTTP通信・Socketの傍受
一部のアプリはHTTPSではなく、生のTCPソケット通信を使っています(独自プロトコル・MQTT・WebSocketなど)。Fridaでソケット操作をフックすれば、これらの平文データも取得できます。
// socket_monitor.js ── Javaのソケット送受信を監視
Java.perform(function () {
var OutputStream = Java.use('java.net.Socket');
// OutputStreamのwrite()をフック→送信データ取得
var DataOutputStream = Java.use('java.io.DataOutputStream');
DataOutputStream.write.overload('[B', 'int', 'int')
.implementation = function (buf, offset, count) {
var data = Java.use('java.lang.String').$new(buf, offset, count, 'UTF-8');
console.log('[Socket SEND] ' + data);
return this.write(buf, offset, count);
};
// InputStreamのread()をフック→受信データ取得
var DataInputStream = Java.use('java.io.DataInputStream');
DataInputStream.read.overload('[B').implementation = function (buf) {
var count = this.read(buf);
if (count > 0) {
var data = Java.use('java.lang.String').$new(buf, 0, count, 'UTF-8');
console.log('[Socket RECV] ' + data);
}
return count;
};
});
🔍 診断ポイント:ソケット通信に認証情報・APIキー・個人情報が平文で流れていないか? 独自の暗号化が施されていても、復号後のデータをFridaでキャプチャできる点がミソです。
第4章:認証・認可処理の解析 ── ログイン・トークン・権限チェック
認証・認可の不備はモバイルアプリのセキュリティ問題の中で最も深刻なカテゴリです。Fridaを使えば、認証ロジックをランタイムで直接観察・改ざんできます。
4-1. ルート検出・エミュレーター検出のバイパス
ルート検出(Root Detection)は、アプリがroot化された端末やエミュレーター上で動作しているかを検知し、機能を制限または停止するセキュリティ機構です。しかしFridaを使えばこの検出ロジックを無効化できます。なぜバイパスが重要かというと、多くのセキュリティ診断ツール(Burp Suite連携、frida-serverなど)はroot化・エミュレーター環境が必要なためです。
代表的なルート検出ライブラリとバイパス方法:
// root_bypass.js ── RootBeer / 独自実装を広くカバー
Java.perform(function () {
// ① RootBeer(最も普及したルート検出ライブラリ)
try {
var RootBeer = Java.use('com.scottyab.rootbeer.RootBeer');
RootBeer.isRooted.implementation = function() { return false; };
RootBeer.isRootedWithoutBusyBox.implementation = function() { return false; };
} catch(e) { console.log('[RootBeer] Not found'); }
// ② Build.TAGS の確認(test-keysはルート端末で設定される)
var Build = Java.use('android.os.Build');
Build.TAGS.value = 'release-keys'; // ← test-keysをrelease-keysに偽装
// ③ File存在確認(su バイナリの有無チェック)
var File = Java.use('java.io.File');
File.exists.implementation = function () {
var path = this.getAbsolutePath();
if (path.indexOf('/su') !== -1 || path.indexOf('Superuser') !== -1) {
console.log('[File.exists] Blocked check for: ' + path);
return false; // suが見つからないように偽装
}
return this.exists();
};
// ④ System.getProperty("ro.debuggable") のチェック
var System = Java.use('java.lang.System');
System.getProperty.overload('java.lang.String').implementation = function(key) {
if (key === 'ro.debuggable' || key === 'ro.secure') {
return '0'; // デバッグ無効・セキュア端末のように偽装
}
return this.getProperty(key);
};
console.log('[Root Bypass] All checks patched.');
});
4-2. 生体認証・PIN認証のバイパス
指紋認証・顔認証(BiometricPrompt)や、起動時のPIN認証をバイパスする手法です。診断環境でアプリの深い機能を調査する際に必要になります。
// biometric_bypass.js
Java.perform(function () {
// BiometricPrompt.AuthenticationCallback の成功コールバックを強制呼び出し
var BiometricPrompt = Java.use('android.hardware.biometrics.BiometricPrompt');
BiometricPrompt.authenticate.overload(
'android.os.CancellationSignal',
'java.util.concurrent.Executor',
'android.hardware.biometrics.BiometricPrompt$AuthenticationCallback'
).implementation = function (cancel, executor, callback) {
// 認証ダイアログを表示する代わりに直接 onAuthenticationSucceeded を呼ぶ
var AuthResult = Java.use('android.hardware.biometrics.BiometricPrompt$AuthenticationResult');
callback.onAuthenticationSucceeded(AuthResult.$new(null));
console.log('[Biometric] Bypassed → onAuthenticationSucceeded called');
};
});
💡 AndroidX Biometricライブラリ(androidx.biometric)を使っているアプリは対象クラスが異なります。jadxでデコンパイルし、Biometricを呼び出しているクラスを特定してから同様のフックを書きます。
4-3. JWTトークンの実行時改ざん
前章のBurp Suiteと組み合わせる手法です。アプリがJWTを組み立てる瞬間をFridaでフックし、ペイロードを改ざんして権限昇格を試みます。
// jwt_manipulator.js
Java.perform(function () {
// Base64エンコード処理をフックしてJWTの組み立てを監視
var Base64 = Java.use('android.util.Base64');
Base64.encodeToString.overload('[B', 'int').implementation = function (input, flags) {
var decoded = Java.use('java.lang.String').$new(input, 'UTF-8');
// JWTのペイロード部分({で始まるJSON)を検出
if (decoded.startsWith('{') && decoded.indexOf('role') !== -1) {
console.log('[JWT Payload] Original: ' + decoded);
// roleをadminに書き換えて試す
var tampered = decoded.replace('"role":"user"', '"role":"admin"');
console.log('[JWT Payload] Tampered: ' + tampered);
input = Java.use('[B').$new(tampered.getBytes('UTF-8'));
}
return this.encodeToString(input, flags);
};
});
⚠️ 署名検証が正しく実装されたJWTは、ペイロードを改ざんしても署名不一致でサーバーに弾かれます。この手法で改ざんが「通る」場合は、サーバー側の署名検証に深刻な欠陥があります。
第5章:データ保存の解析 ── 機密情報の平文保存を発見する
スマートフォンに保存されたデータは、端末を紛失した場合や、ルート化された端末での解析によって流出する可能性があります。Fridaでデータ保存の処理を監視し、機密情報が平文で保存されていないかを確認します。
5-1. SharedPreferencesの監視
AndroidのSharedPreferencesはXMLファイルとして保存される軽量なキー・バリュー型ストアです。セッショントークンやパスワードをここに平文保存してしまうアプリが依然として存在します。
// shared_prefs_monitor.js
Java.perform(function () {
var SharedPreferences = Java.use('android.content.SharedPreferences$Editor');
// putString → 文字列値の保存を監視
SharedPreferences.putString.implementation = function (key, value) {
console.log('[SharedPrefs.putString]');
console.log(' Key : ' + key);
console.log(' Value : ' + value);
// パスワード・トークン・秘密鍵っぽい値を警告
var dangerKeys = ['password','token','secret','key','auth','credential'];
for (var i = 0; i < dangerKeys.length; i++) {
if (key.toLowerCase().indexOf(dangerKeys[i]) !== -1) {
console.log(' ⚠️ SENSITIVE KEY DETECTED: ' + key);
}
}
return this.putString(key, value);
};
// getString → 読み出し時も監視
var SharedPreferencesImpl = Java.use('android.app.SharedPreferencesImpl');
SharedPreferencesImpl.getString.implementation = function (key, defValue) {
var result = this.getString(key, defValue);
if (result !== null && result.length > 0) {
console.log('[SharedPrefs.getString] ' + key + ' = ' + result);
}
return result;
};
});
5-2. SQLiteデータベースの操作を監視する
アプリのローカルDBに機密データが平文で保存されているケースも多いです。SQLite操作をFridaでフックして、どんなデータが保存・取得されているかを把握します。
// sqlite_monitor.js
Java.perform(function () {
var SQLiteDatabase = Java.use('android.database.sqlite.SQLiteDatabase');
// execSQL → スキーマ変更・INSERT/UPDATE等
SQLiteDatabase.execSQL.overload('java.lang.String').implementation = function (sql) {
console.log('[SQLite.execSQL] ' + sql);
return this.execSQL(sql);
};
// rawQuery → SELECT文を監視
SQLiteDatabase.rawQuery.overload('java.lang.String', '[Ljava.lang.String;')
.implementation = function (sql, args) {
console.log('[SQLite.rawQuery] ' + sql);
if (args !== null) {
for (var i = 0; i < args.length; i++) {
console.log(' Args[' + i + ']: ' + args[i]);
}
}
return this.rawQuery(sql, args);
};
});
🔍 診断ポイント:暗号化されていないSQLiteDBに保存された認証トークンやメッセージ内容は、ルート化端末からそのまま抽出できます。SQLCipherのような暗号化DBライブラリを使っているか確認しましょう。
5-3. ファイルI/Oの監視
アプリが書き込むファイルのパスと内容をすべてログします。証明書・設定ファイル・キャッシュなどに機密情報が保存されていないかを確認します。
// file_io_monitor.js
Java.perform(function () {
var FileOutputStream = Java.use('java.io.FileOutputStream');
FileOutputStream.$init.overload('java.lang.String').implementation = function (path) {
console.log('[FileOutputStream] Writing to: ' + path);
// /sdcard/ や外部ストレージへの書き込みは要注意
if (path.indexOf('/sdcard/') !== -1 || path.indexOf('/storage/') !== -1) {
console.log(' ⚠️ EXTERNAL STORAGE WRITE: ' + path);
}
return this.$init(path);
};
});
第6章:実践ワークフロー ── 診断の進め方
6-1. Frida診断の全体フロー
実際のモバイルアプリセキュリティ診断でFridaをどのように使うか、標準的なフローをまとめます。
Phase 1:環境準備(30分)
- Androidエミュレーター(AVD)を起動 ※Google Play非搭載イメージ推奨
- frida-serverをエミュレーターに配置・起動
- Burp SuiteのCA証明書をエミュレーターにインストール
- エミュレーターのWi-FiプロキシをBurp(127.0.0.1:8080)に設定
Phase 2:アプリの偵察(1時間)
- jadxでAPKをデコンパイルし、全クラス一覧・設定ファイルを把握
- frida-traceで暗号化・ネットワーク・認証関連クラスをトレース
- アプリを操作しながらどんな処理が呼ばれるかログを収集
Phase 3:SSL Pinningバイパス → Burp連携(30分)
- Objectionでsslpinning disableを実行
- BurpでHTTPS通信が傍受できることを確認
- API一覧をBurpのSite mapで整理
Phase 4:個別脆弱性の検証(2〜4時間)
- 暗号化処理フック → アルゴリズム・鍵・平文を確認
- SharedPreferences・SQLiteフック → 機密データの平文保存を確認
- 認証処理フック → バイパスの成否を確認
- BurpのRepeaterと組み合わせてAPIレベルの問題も検証
6-2. Pythonスクリプトで診断を自動化する
複数のフックスクリプトを組み合わせた自動化フレームワークをPythonで構築できます。以下はFridaのPython APIを使った診断スクリプトの骨格です。
# frida_audit.py ── 診断用統合スクリプト
import frida, sys, json
# 複数のフックスクリプトを読み込む
scripts = [
open('ssl_bypass_l1.js').read(),
open('ssl_bypass_l2.js').read(),
open('root_bypass.js').read(),
open('crypto_hook.js').read(),
open('shared_prefs_monitor.js').read(),
]
combined_script = '\n'.join(scripts)
def on_message(message, data):
if message['type'] == 'send':
print('[FRIDA]', message['payload'])
elif message['type'] == 'error':
print('[ERROR]', message['stack'])
device = frida.get_usb_device(timeout=5)
pid = device.spawn(['com.example.targetapp'])
session = device.attach(pid)
script = session.create_script(combined_script)
script.on('message', on_message)
script.load()
device.resume(pid)
print('[*] Frida audit running. Press Ctrl+C to stop.')
sys.stdin.read()
6-3. 実践チェックリスト
暗号化処理
- □ AES/DES/RSA等の暗号化が正しいアルゴリズムで行われているか
- □ 鍵がハードコードされていないか(コード中・リソースファイルに埋め込まれた鍵)
- □ MD5・SHA-1など脆弱なハッシュがパスワード処理に使われていないか
- □ IV(初期化ベクトル)がランダムに生成されているか(固定IVは危険)
SSL/TLS通信
- □ SSL Pinningが実装されているか
- □ バイパスされた場合でも通信内容に暗号化が施されているか
- □ 証明書の有効期限・失効確認が適切に行われているか
- □ 平文のHTTP通信(非HTTPS)が存在しないか
認証・認可
- □ ルート検出・エミュレーター検出が実装されているか(ある場合バイパス可能か)
- □ 生体認証・PIN認証をバイパスした場合、機能へのアクセスが制限されるか
- □ セッショントークンの検証がクライアントとサーバー双方で行われているか
データ保存
- □ SharedPreferencesに機密情報(トークン・パスワード)が平文保存されていないか
- □ SQLiteに暗号化なしで機密データが保存されていないか
- □ ログ出力(Logcat)に機密情報が含まれていないか
- □ 外部ストレージ(/sdcard/)に機密ファイルが書き込まれていないか
まとめ:Fridaで「見るべき処理」の優先順位
Fridaは強力なツールですが、「何でも見る」のではなく「最も重要な処理から優先的に見る」ことが実践の鍵です。
| 優先度 | 監視すべき処理 | 代表的な脆弱性 |
| 🔴 最優先 | SSL Pinningの検証処理 | バイパスでBurp連携が可能に |
| 🔴 最優先 | 暗号化の鍵取得・doFinal | ハードコード鍵・弱い暗号 |
| 🔴 最優先 | 認証トークンの検証 | バイパスで不正認証 |
| 🟠 高優先 | SharedPreferences/SQLite書き込み | 機密情報の平文保存 |
| 🟠 高優先 | ルート検出・エミュレーター検出 | 検出バイパスで診断環境確立 |
| 🟡 中優先 | ネットワークSocket通信 | 独自プロトコルの平文通信 |
| 🟡 中優先 | 生体認証コールバック | 認証バイパスで機能へのアクセス |
| 🟢 低優先 | ファイルI/O全般 | 外部ストレージへの機密書き込み |
| 🟢 低優先 | ログ出力(Log.d等) | Logcatへの機密情報漏洩 |
Fridaを習得すると、アプリが「ユーザーには見せない」処理を可視化できるようになります。これは防御側にとっても非常に有用で、「自社アプリに弱点がないか」を開発段階で確認するセキュアコーディングの観点でも活用できます。
学習環境としては、OWASP公式のInsecureBankv2(https://github.com/dineshshetty/Android-InsecureBankv2)やDVIA(Damn Vulnerable iOS App)など、意図的に脆弱に作られたアプリで練習することを推奨します。
本記事は教育・学習目的で作成されました。すべての解析は適切な許可のもと、自己管理下の環境でのみ実施してください。


コメント