Hello there, ('ω')ノ
✅ よくあるNG設計から学ぶセキュア設計の原則
❌ ありがちNG設計の例①
認証フローが画面側で完結している
// ローカルDBからログイン状態を確認 if (sharedPref.getBoolean("isLoggedIn", false)) { moveToMainPage(); }
→ 認証状態がクライアントだけで管理されており、改ざんやセッション偽装が可能に。
✅ どうあるべきか?
- 認証情報はサーバーで管理し、トークンを都度検証
- ローカルに状態を持たせる場合も、暗号化されたストレージを使う
- アプリ起動時には「トークンの有効性確認API」を呼び出す設計にする
❌ NG設計②
すべての画面が他アプリから呼び出せる
<activity android:name=".PaymentActivity" android:exported="true" />
→ インテント経由で画面を起動され、未認証で支払い画面にアクセス可能というリスクが生まれる。
✅ どうあるべきか?
exported="false"をデフォルトにし、外部公開が必要な画面だけtrueにする- 画面遷移前にユーザー認証の確認ロジックを入れる(例:JWTの検証)
❌ NG設計③
APIキーやシークレットがアプリ内に埋め込まれている
private static final String API_KEY = "abcd1234..."; // 解析されたらおしまい
✅ どうあるべきか?
- APIキーやシークレットはアプリには埋め込まず、起動後にサーバーから一時的に取得
- Google Play App Signing や Android Keystore で機密情報の保護レイヤーを加える
🧠 安全なアプリ設計に必要な“5つの視点”
| 視点 | 設計のポイント |
|---|---|
| 1. 最小権限 | 不要な権限や公開コンポーネントを排除 |
| 2. 信頼境界の明確化 | どこからのアクセスを信じるかを設計段階で定義 |
| 3. データの保護 | 保存・送信時の暗号化、セキュアな保存先の利用 |
| 4. 例外処理の丁寧さ | 想定外動作のログ出力やクラッシュで情報漏洩しない設計 |
| 5. 更新を見越した構造 | ライブラリ脆弱性やポリシー変更に柔軟に対応できる構造 |
📦 サンプル:安全なアーキテクチャの一例
[UI層] → 認証チェック → [ViewModel/UseCase] → API呼び出し(HTTPS, JWT)
↓
[認証トークン] は暗号化してEncryptedSharedPreferencesに保管
- アプリ層では認証状態を直接保持しない
- ネットワーク層で通信ごとにトークンをヘッダに付与
- アクティビティの起動時に、認証済み状態かを必ず検証
✅ 設計レビュー時に使えるチェックリスト
- [ ] 外部から呼び出せる画面は適切に制限されているか?
- [ ] 認証/認可はアプリ内に閉じず、サーバーで担保されているか?
- [ ] 通信はHTTPSで、必要ならSSLピンニングが施されているか?
- [ ] アプリに含まれる秘密情報は最小限か?暗号化されているか?
- [ ] 例外発生時にログや画面に機密情報が表示されないか?
✅ まとめ
- アプリの安全性は「設計段階」で7割決まる
- よくある実装ミスは、そもそもの構成や責任の分離が曖昧なことが原因
- 「攻撃されないコード」ではなく、「攻撃されても突破できない構造」を意識する
- 診断者の立場からも、設計レベルの指摘と助言ができると一段上の支援が可能
Best regards, (^^ゞ