コンテンツへスキップ
DedicatedPHP 接触

PHPのセキュリティログに記録すべき内容と機密データを漏らさない方法

PHPで調査可能なセキュリティイベントを定義し、記録する内容と除外する内容、ログの保護方法、障害を隠さず網羅性を検証する方法を解説します。

機密データを含めず、実行者、操作、結果、相関情報を記録するPHPアプリケーションのセキュリティイベントの構成図

セキュリティログは、誰が、いつ、どのリソースに対して何を試み、どのような結果になったかを再構成するためのものです。すべてのリクエストのコピーでも、例外のダンプでもありません。目的は、調査に必要な最小限のデータを使い、不審なアクセスや操作を調べるための有用な証拠を提供することです。また、ログ自体が情報漏えいの原因にならないよう、適切な管理策も必要です。

PHPでセキュリティログを設計する際は、まず重要なイベントとその用途(検知、調査、運用監査、社内ポリシーへの準拠など)を定義します。次に共通フォーマットを定め、ログを閲覧できる人を決め、記録から利用までの一連の流れを検証します。ログが存在していても、イベントを時系列に並べられず、結果を特定できず、試行と完了した操作を区別できないのであれば、調査の要件を満たせません。

技術ログ、アクティビティログ、セキュリティイベントを分ける

技術ログ、アクティビティログ、セキュリティイベントを分ける — guía visual de DedicatedPHP

技術ログは、エラー、例外、レイテンシ、接続障害、設定上の問題など、アプリケーションの動作を記録します。可用性や挙動の診断に役立ちます。アクティビティログは、請求書の編集やアカウント情報の変更など、ユーザーに帰属する業務上の操作を記録します。一方、セキュリティイベントは、ID、権限、リソース、アクセス制御に関わる重要な事実に焦点を当てます。

これらの分類は重なることがありますが、互換性のあるものではありません。ロールの変更は業務上のアクティビティであると同時にセキュリティイベントでもあります。データベース例外は通常、技術的な問題ですが、機密性の高い操作で失敗が続く場合は、セキュリティアラートの対象となることがあります。目的を定義すれば、根拠のない情報の重複を避け、適切な保持期間、アクセス権、フォーマットを割り当てられます。

セキュリティログを無期限の監査データベースや、メトリクスおよびトレースの代わりとして使わないでください。また、イベントを記録することと検知することは同じではありません。アラートを生成するには、ルール、しきい値、対応責任者が必要です。それぞれのデータをどのシステムが生成し、どのチームが利用するのかを文書化してください。

調査に役立つ操作とコンテキストを選ぶ

アプリケーションに関係する操作と脅威を洗い出すことから始めます。検討対象となることが多いイベントには、ログイン失敗、アカウントロック、認証情報の変更、権限の付与・取り消し、設定変更、機密データのエクスポート、管理操作などがあります。対象は製品の特性に合わせてください。ページの閲覧をすべて記録するとノイズが増える一方、権限変更を記録しなければ、不正アクセスの経緯を再構成できなくなります。

イベントごとに、何を明らかにできる必要があるかを定義します。たとえば権限変更の調査では、実行者、影響を受けたユーザーまたはリソース、変更前後の権限、結果、発生時刻を特定できることが重要です。認証失敗では、ポリシーに応じて正規化または仮名化したアカウント識別子が、結果や、収集が正当化される場合のリクエスト元情報とともに必要になることがあります。共有IPアドレスから個人を特定したと推定しないでください。

試行、判定、結果を区別してください。拒否されたリクエストは、完了した変更ではありません。受理されたリクエストも、永続化の前に失敗することがあります。実際の結果を記録し、調査に必要であれば到達した段階も記録します。また、denied、failed、succeededなどの値が何を意味するかを定義し、コンポーネントごとに矛盾した使い方をしないようにしてください。

一貫性があり相関付け可能なスキーマを使う

通常はJSONなどの構造化フォーマットを使うと、運用ツールでイベントを絞り込み、相関付けしやすくなります。基本項目として、次のフィールドを検討してください。

  • イベント識別子:authorization.permission_changedのような、安定したバージョン管理対象の名前。
  • 発生時刻:適切な精度のUTC日時。システム間で時計を同期させます。
  • 実行者:内部識別子または仮名。プロセスや自動タスクも明示的に表します。
  • 操作とリソース:実行された操作、および影響を受けたリソースの種類と識別子。リソースの内容は含めません。
  • 結果:成功、拒否、失敗のいずれか。機密情報を含まない分類済みの理由も記録します。
  • 相関情報:リクエスト全体をダンプせずにイベントを関連付けるためのリクエストIDまたは操作ID。
  • コンテキスト情報:イベントを発行したサービスまたはコンポーネント。正当な理由がある場合は、ネットワーク上の発信元に関する限定的な情報も含めます。

フィールド名と型は安定させてください。リクエストIDはインフラストラクチャが生成または検証する必要があります。任意のIDを検証せずに受け入れると、衝突や混乱を招くおそれがあります。ヘッダー全体、HTTPボディ、パラメーターを無差別に含めないでください。コンテキストは処理対象のデータをすべて複製するのではなく、イベントの順序を再構成するのに役立つものであるべきです。

秘密情報を除外し、個人データを最小限にする

パスワード、アクセストークン、APIキー、セッションシークレット、リカバリーコードなど、認証に使える値は決して記録しないでください。内部識別子で十分な場合は、個人データ全体を記録することも避けてください。メールアドレス、電話番号、住所などの項目について、保存が不可欠か、マスキングできるか、仮名化した参照情報を使うべきかを判断します。判断は目的、リスク、適用される義務に基づいて行います。

イベントがプロセスの外に出る前にデータをマスキングしてください。集約先の後段フィルターだけに頼ってはいけません。PHPでは、機密値を含む可能性のあるリクエストオブジェクト、ヘッダー、例外をそのままシリアライズしないでください。許可するフィールドを明示したオブジェクトまたは配列を作成します。新しいフィールドが追加されると破綻しやすいため、禁止項目のリストに頼る方法は脆弱です。ユーザーが制御できる値の長さも検証・制限し、ログへの行挿入、ノイズ、過剰なリソース消費を抑えてください。

パラメーターやエラーメッセージに秘密情報が含まれるケースをテストし、ログの保存先に届かないことを確認してください。サニタイズ後も、調査に十分な情報(たとえばエラー分類)は残してください。ただし、認証情報を含む可能性がある場合は、メッセージ全体を保持しないでください。

アクセス、完全性、ライフサイクルを保護する

ログにも機密情報が含まれます。書き込み、読み取り、エクスポート、保持期間の管理ができる人を制限してください。これらの機能には別々の権限が必要となる場合があります。インフラストラクチャに適した管理策で転送と保存を保護し、アプリケーションの侵害されたアカウントが履歴全体を痕跡なく削除・改ざんできないようにします。リスクに応じて、追記専用ストレージや検証可能な完全性管理策を使い、その限界も文書化してください。

イベントの種類ごとに明確な保持期間を定めます。無期限に保存すると、漏えいリスクとコストが増加します。一方、早すぎる削除は調査を妨げる可能性があります。ポリシーでは、バックアップ、エクスポート、テスト環境、個人データに影響する削除要求も考慮してください。運用担当者によるログ自体へのアクセスを記録して見直し、特にエクスポートやポリシー変更を確認します。

保存先の停止、ストレージ上限、シリアライズエラーなどにより、ログ記録が失敗することがあります。それぞれの場合に何をするかを、重要度に応じて決めてください。ログシステムの停止によって、リスクの高い操作が気付かれないまま完了する経路を作らないでください。一方で、ログ記録の例外によって操作結果が不整合になったり、トランザクションが重複したりすることも避ける必要があります。重要な操作では、outboxパターンなどのトランザクション戦略を使い、イベントの書き込みと変更を同時に確実に行う必要がある場合があります。キューを使う場合は、再試行、重複排除、保留イベントの処理方法を定義してください。

イベントの記録と安全性を検証する

テストでは、ログ記録関数が呼び出されたことだけでなく、それ以上を確認します。アクセス拒否、権限付与、権限取り消し、機密性の高い変更の成功・失敗など、代表的なシナリオを一通り実行してください。イベントに実行者、リソース、結果、発生時刻、相関情報が含まれること、結果が実際に起きたことと一致すること、パスワードやトークン、不要なデータが含まれないことを確認します。

ログの保存先が利用できない場合のテストも加え、主処理の状態が一貫しているか、代替の通知が生成されるか、エラーが運用担当者に見えるかを確認してください。機密性の高い操作では、変更が永続化されていないのに成功と報告されないことを確認します。また、ユーザーが制御できる値に含まれる改行など、上限や細工された入力を試し、ロールごとの読み取り権限も検証してください。業務ユーザーがイベントの保存先にデフォルトでアクセスできてはなりません。

実装レビュー用チェックリスト

実装レビュー用チェックリスト — guía visual de DedicatedPHP
  • 各イベントの目的、責任者、保持ポリシーが定義されていますか?
  • 試行、拒否、失敗、完了した操作を区別していますか?
  • スキーマから実行者、操作、リソース、結果、発生時刻を特定できますか?
  • リクエストの内容全体を記録せずに相関付けできますか?
  • 送信前に秘密情報を除外し、個人データを最小限にしていますか?
  • アクセス、転送、保存、削除が適切に管理されていますか?
  • 保存先の停止、操作の完全性、読み取り権限をテストしましたか?

まず、アカウント、権限、影響の大きい操作を保護するイベントを優先してください。次にスキーマを標準化し、記録するデータを限定して、ログに秘密情報が入った場合に失敗する自動テストを導入します。こうすることで、PHPのセキュリティログは、機密情報の第二のデータベースになることなく、調査に活用できる証拠を提供します。

これらのアイデアをあなたのプロジェクトに活用してみませんか?あなたのPHPプラットフォームについて話し合いましょう。
関連サービスを見る