LESSON 30分

ストーリー

高橋アーキテクト
脅威を特定して優先度をつけた。次は”何を守るか”を明確にしよう

高橋アーキテクトが要件定義書のテンプレートを開きました。

高橋アーキテクト
脅威モデリングの結果を、実装可能なセキュリティ要件に落とし込む。これがないと、開発者は何をどこまで対策すればいいのか分からない
あなた
機能要件と同じように定義するんですか?
高橋アーキテクト
そうだ。テスト可能で、計測可能なセキュリティ要件を書く。曖昧な”セキュリティを確保する”ではなく、具体的な基準を示す

セキュリティ要件の分類

セキュリティ要件は以下の4つに分類されます。

分類説明
認証要件ユーザーの本人確認に関する要件パスワードポリシー、MFA
認可要件アクセス制御に関する要件RBAC、リソースの所有者チェック
データ保護要件データの機密性・完全性に関する要件暗号化、マスキング
運用要件セキュリティ運用に関する要件ログ、監視、インシデント対応

セキュリティ要件の書き方

SMART原則で書く

セキュリティ要件も、SMART(Specific, Measurable, Achievable, Relevant, Time-bound)に書きます。

// 悪い例:曖昧な要件
// 「パスワードは安全なものを使用すること」

// 良い例:具体的で計測可能な要件
interface PasswordPolicy {
  minLength: 12;                    // 最低12文字
  requireUppercase: true;           // 大文字必須
  requireLowercase: true;           // 小文字必須
  requireNumbers: true;             // 数字必須
  requireSpecialChars: true;        // 特殊文字必須
  maxAge: 90;                       // 90日で有効期限切れ
  historyCount: 5;                  // 過去5回と同じパスワード不可
  lockoutThreshold: 5;             // 5回失敗でアカウントロック
  lockoutDuration: 30;             // ロック時間30分
}

セキュリティ要件テンプレート

interface SecurityRequirement {
  id: string;                  // 要件ID
  category: "認証" | "認可" | "データ保護" | "運用";
  title: string;               // 要件タイトル
  description: string;         // 詳細説明
  strideThreat: string;        // 対応するSTRIDE脅威
  dreadScore: number;          // DREADスコア
  acceptanceCriteria: string[]; // 受け入れ基準
  testMethod: string;          // テスト方法
  priority: "Must" | "Should" | "Could";
}

// 要件定義の例
const securityRequirements: SecurityRequirement[] = [
  {
    id: "SEC-AUTH-001",
    category: "認証",
    title: "アカウントロックアウト",
    description: "連続ログイン失敗時にアカウントを一時的にロックする",
    strideThreat: "S: ブルートフォースによるなりすまし",
    dreadScore: 6.8,
    acceptanceCriteria: [
      "5回連続でログインに失敗した場合、30分間アカウントをロックする",
      "ロック中のログイン試行は理由を明示してエラーを返す",
      "ロック解除後は正常にログインできる",
      "管理者は手動でロックを解除できる",
    ],
    testMethod: "自動テスト + ペネトレーションテスト",
    priority: "Must",
  },
  {
    id: "SEC-AUTHZ-001",
    category: "認可",
    title: "リソースの所有者チェック",
    description: "APIエンドポイントでリソースの所有者を検証する",
    strideThreat: "E: IDOR による他ユーザーのデータアクセス",
    dreadScore: 7.4,
    acceptanceCriteria: [
      "ユーザーは自分が所有するリソースのみ取得・更新・削除できる",
      "他ユーザーのリソースへのアクセスは403 Forbiddenを返す",
      "管理者は全リソースにアクセスできる",
    ],
    testMethod: "自動テスト(異なるユーザーでのアクセス確認)",
    priority: "Must",
  },
  {
    id: "SEC-DATA-001",
    category: "データ保護",
    title: "個人情報の暗号化",
    description: "データベースに保存する個人情報を暗号化する",
    strideThreat: "I: データベースからの個人情報漏洩",
    dreadScore: 8.2,
    acceptanceCriteria: [
      "メールアドレス、電話番号、住所はAES-256で暗号化して保存する",
      "暗号化キーはアプリケーションコードから分離して管理する",
      "暗号化されたデータはアプリケーション経由でのみ復号できる",
    ],
    testMethod: "DBの直接参照で暗号化を確認",
    priority: "Must",
  },
];

セキュリティ要件マトリクス

OWASP ASVSを参考に、セキュリティ要件をレベル別に整理できます。

レベル対象要件例
Level 1全アプリケーション入力バリデーション、HTTPS、パスワードハッシュ化
Level 2機密データを扱うアプリ暗号化、MFA、監査ログ、セッション管理
Level 3高リスクアプリ(金融等)HSM、リアルタイム監視、ペネトレーションテスト
// レベル別のセキュリティ要件チェック
const securityLevelRequirements = {
  level1: {
    authentication: [
      "パスワードは bcrypt/scrypt/argon2 でハッシュ化",
      "HTTPS必須(HTTP→HTTPSリダイレクト)",
      "セッションタイムアウト(30分以内)",
    ],
    authorization: [
      "全エンドポイントに認可チェック",
      "デフォルトdeny(明示的に許可しない限りアクセス拒否)",
    ],
    input: [
      "全入力のバリデーション(ホワイトリスト方式)",
      "SQLインジェクション対策(パラメータ化クエリ)",
      "XSS対策(出力エスケープ)",
    ],
  },
  level2: {
    authentication: [
      "多要素認証(MFA)のサポート",
      "パスワードの複雑性要件(12文字以上)",
      "アカウントロックアウト機能",
    ],
    dataProtection: [
      "保存時暗号化(AES-256)",
      "個人情報のマスキング",
      "バックアップの暗号化",
    ],
    logging: [
      "認証イベントの監査ログ",
      "データアクセスの監査ログ",
      "ログの改ざん防止",
    ],
  },
};

まとめ

ポイント内容
要件分類認証・認可・データ保護・運用の4分類
SMART原則具体的で計測可能な要件を書く
受け入れ基準テスト可能な条件を定義する
レベル別管理アプリのリスクに応じた要件レベル

チェックリスト

  • セキュリティ要件の4つの分類を理解した
  • SMART原則に基づく要件の書き方を学んだ
  • セキュリティ要件テンプレートの使い方を把握した
  • レベル別の要件管理を理解した

次のステップへ

次は「セキュアな設計パターン」を学びます。脅威に対抗するための、実装で使える設計パターンを身につけましょう。


推定読了時間: 30分