世界を動かす技術を、日本語で。

ログから秘密を排除する (2024)

概要

  • ログにおける機密情報漏洩 は、単一の解決策では防げない複雑な問題。
  • 多層的な対策(lead bullets) を組み合わせることで、現実的な防御力を確保。
  • 原因は多岐にわたり、直接的なログ記録から設計や設定ミス、ユーザー入力まで様々。
  • インシデントの影響範囲は広く、信頼性や法的リスクにも直結。
  • 本記事は実践的な対策と考え方 を10の観点から紹介。

ログから機密情報を守るには:銀の弾丸は存在しない

  • 単一の解決策(銀の弾丸)は存在しない 問題であり、様々な対策(lead bullets)の組み合わせが必要。
  • 80/20ルールが通用しない 難しさ。SQLインジェクションのように一つの対策で大半を防ぐことはできない。
  • ログに機密情報が混入する原因 は多様で、予想外の場所や方法で発生。
  • 原因を知り、対策の枠組みを持つこと が、再発防止やインシデント対応の第一歩。
  • 本記事では10の具体的なlead bullets (実践的な対策)を紹介。

ログに機密情報が混入する主な原因

  • 🤦 直接的なログ記録

    • デバッグやテスト目的で 意図せず機密情報をログに記録 するケース。
    • コードレビューやgrepで発見しやすいが、ヒューマンエラーが根本原因。
  • 🚰 キッチンシンク問題

    • エラーオブジェクトやレスポンス全体を丸ごとログ に出力し、意図せず機密情報も含まれる。
    • 型安全な言語や型定義を活用すれば検出しやすくなる。
  • 🔧 設定変更による副作用

    • ログレベルや設定の変更により、本来出力されないはずの情報がログに流出。
    • 低レイヤーやグローバルな設定変更が原因になりやすい。
  • 🥧 埋め込み型の機密情報

    • URLやRPC、リクエストパラメータ など、設計段階で機密情報が一般データに埋め込まれている。
    • ログ以外の層(例:HTTPアクセスログ)でも漏洩リスク。
  • 📡 テレメトリ・モニタリング

    • エラーモニタリングや分析ツール が、意図せず機密情報を収集・保存。
    • ログパイプライン外の経路に注意が必要。
  • 🕺🏻 ユーザー入力

    • ユーザーが意図せず機密情報を不適切なフィールドに入力 し、ログに残る。
    • UIやユーザー教育だけでなく、入力値の扱い全般に注意。

ログにおける機密情報漏洩の影響

  • 被害範囲の広さ

    • 内部APIキーなどすぐにローテーション可能なものから、 PIIや顧客パスワード のように回収困難なものまで幅広い。
    • 法的・規制上のリスクや、 信頼性の低下 に直結。
  • 対策をすり抜ける特性

    • データベース暗号化やアクセス制御 など、他のセキュリティ対策をログが無効化してしまう危険性。
    • ログ=データの最終出口 として、特別な注意が必要。
  • 規模や成熟度を問わず発生

    • 大企業・成熟したセキュリティ体制でも 完全防御は困難
    • 公開事例も多く、透明性のある対応が重要。

まとめと今後の展開

  • 単一の解決策は存在せず、多層防御(defense-in-depth)が現実的なアプローチ。
  • 原因を正しく理解し、各層でlead bulletsを配置 することが有効。
  • 次回以降、 具体的な10のlead bullets(実践的対策) について解説予定。

(次回に続く場合は、「ログから機密情報を守る10のlead bullets」などの新しいセクションタイトルで整理してください。)

Hackerたちの意見

いい読み物だった。

「人々がコードを書いて、うっかり機密データをログに入れてしまうことはあるけど、そういう人たちが報告して、対応して、修正するんだよね。これが最後のポイントじゃなくて、最初のポイントであるべきだと思う。」

著者の結論に賛成か反対かに関わらず、これは素晴らしいリソースだよ。問題を分解して、よく説明されていて、提案された修正の技術的な説明もちゃんとついてるからね(その修正に対する意見は別として)。問題領域にアプローチして明確にする方法の素晴らしい例だと思う。

JavaにはGuardedStringの実装があるよ。 https://docs.oracle.com/en/middleware/idm/identity-governanc...

ログから秘密を守りたい気持ちはわかるけど、ログ自体も秘密と見なされるべきじゃない? 完全にサニタイズされたログでも、敵に共有したくないようなプロダクション環境のデータがたくさん含まれてると思うよ(例えば、ピーク使用時間とか)。

ログはサポートチームや、姉妹チームのオンコール、全ての開発者に公開される必要があると思う。だから、秘密にアクセスする必要がある人よりも、はるかに多くの人がログにアクセスすることになる。ログに秘密が含まれていると、内部の脅威のリスクが広がるし、フィッシングされた人から高い権限に移行するのがずっと簡単になる。監査記録がある場合、秘密にアクセスするのはログにアクセスするのとは別に記録しておきたいよね。

そうだね、でも防御は深く考えよう。競合他社に移るチームメンバーがピーク使用時間を教えることはできるけど、全ての顧客のパスワードを教えるべきじゃないよね。

敵からの秘密と、内部の区分けがあるよね。ルーターのsyslogを見なきゃいけないビジネスニーズがある人が何百人もいるかもしれないけど、管理者ユーザーのログイン情報にアクセスするべき人はほとんどいないし、自動化ロールアカウントの情報にアクセスできる人も数十人程度だと思う。

PIIは独自情報とは違うよ。顧客のメールアドレス?PIIだね。マスクしなきゃ。コードのスタックトレース?独自情報だよ。従業員はそれを見てトラブルシューティングできるから。

ランタイムの露出防止については、インバンドシグナルの方がアウトオブバンドよりもこの問題には効果的かもしれないね。言及された汚染チェック技術のように、ソースで機密文字列に何か魔法の文字列(例えば、認識できるプレフィックス + ランダムに生成されたUUID)を挿入して、シンクでそれを取り除くって感じ。 (または、秘密をその魔法の文字列で包むとか。)その後、その魔法の文字列を含む文字列が永続データ、ログに入らないようにブロックまたはマスクする。露出ポイントは、seal()/unseal()関数を呼び出すところにあるから、特定するのも簡単だよ。

このアプローチが適切になる状況や理由について詳しく教えてもらえる?一見すると、この記事の技術の複雑で劣った近似に見えるんだけど、自動的に使い捨てじゃないし、静的チェックもされてないし、正しい秘密の使い方に対してはエラーが出やすいし、善意のバカが秘密を誤って抽出したり「洗浄」したり漏らしたりするのを防げてない気がする。ログから秘密を危険なタイミングで削除することで漏洩の可能性もあるし。

うわ、マジか - ちょうど1ヶ月前に職場でその問題が出たんだ。開発システムはテスト用だから、すごくシンプルなユーザー名とパスワードを使ってたんだけど、その中の一つが「秘密」を含んでたせいで、全部消されちゃった。これについてはすごく強い意見があって、要するに「お前ら、なんで全部ログ取ってるの?怠け者かよ」ってことと、「秘密を別のツールに入れて、ログでスキャンするために追加するなんて、漏洩のリスクを増やすだけじゃん」ってこと。特に、秘密が単語の一部でも検閲されるってことは、たぶんハッシュ化もされてなかったってことだし。でもセキュリティツールだから、そのまま残るんだよね。カッサンドラみたいな気分だけど、将来的にこれや同じ機能を持つ他のツールで大きなセキュリティ問題が起こるのは予測できる気がする。Xを防ぐためのソフトウェアがXに脆弱であってはいけないはずなのに、なぜかしばしば脆弱になっちゃうっていう、まさに盲点みたいなもんだよね。

なんで全部ログ取るのが怠けてるって考えられるの?

特に気をつけるべきなのはコアダンプだね。前の職場では、コアがダンプされるときに実行されるスマートなgdbスクリプトを使って、パスワードを取り除くようにしてた。読みやすい場所に書き込まれる前にね。このスクリプトを書くことで、最初にパスワードを抽出する方法も示せたし。

スタックトレースもそうだよね。重いJavaの職場で働いてたとき、ほとんどすべての機密情報がどこかでスタックトレースに出ちゃってた。

大きな問題は、秘密が文字列のどこにでも存在する可能性があって、入力をコントロールできない場合なんだよね(例えば、ライブラリのスタックトレースやHTTPレスポンス、JSONの文字列化されたものとか)。秘密をロガーに渡して、削除できるようにする必要があるけど、これは開発者に大きく依存してて、レビューのときに忘れがちなんだよね。正確な一致だけが問題じゃなくて、ある開発者が末尾を削除して、別の開発者が先頭を削除したら、十分なログがあれば秘密を再構成できちゃう。

一つの方向性としては、すべてのノードでrsyslogを実行して、正規表現を使って既知のパターンにマッチさせることかな。さまざまなプラグインやアドオンを使って、すべてのアプリケーションをローカルのrsyslogインスタンスに送信するためのローカルスプーラーを使って、rsyslogを中央のログサーバーに暗号化して送るんだ。rsyslogはスプーラーを使うことができるから、上流のサーバーが何らかの理由でオフラインのときも、ログはローカルにスプールされて、上流がオンラインになったら再開される。ログの正規表現マッチングは遅いけど、すべてのノードで行えばCPU負荷が分散されるし、上流でやるよりも効率的だよ。構成管理で正規表現ルールをすべてのノードにプッシュできるし、未知の未知には役立たないけど、ピアレビューの後に構成管理で迅速に追加できる。rsyslogはログストリームの暗号化もサポートしてるから、秘密の漏洩を送信ノードと中央ノードに制限できるし、いくつかの要件を満たしてる。もう一つの助けになるのは、警告以上のものだけを上流に送信して、ローカルノードにエージェントを使って、情報からデバッグまでの範囲でキーワードを監視して、誰かにノードのログを確認するように知らせること。SOC1/SOC2/PCI/FEDRAMPのログ保持要件がある中央サーバーには、無駄なものが少なくなるし、最初に送信しなければ漏洩することはないからね。

これは問題の素晴らしいまとめだね。新卒やブートキャンプ出身の新入社員は、ここでのリスクについて全く意識がないことが多い。時には、何年も経験があるエンジニアでも、キャリアの中で運用のメンターシップを受けていない場合もある。特にキッチンシンクの例は、人をつまずかせることがある。ライブラリが失敗のエッジケースをどう扱うかの具体的な情報を知らないと、油断してしまうことがある(例えば、axiosのエラーにAPIキーのヘッダーが含まれているとか)。こういった問題の多くは、秘密が単に署名やIDを使うのではなく、ワイヤー上を流れるアーキテクチャから来ている。でも、サードパーティのプラットフォームを使わざるを得ない場合は、選択肢がないことが多い。

この「リードバレット」のフレーミング、特に汚染チェックやスキャナー、前処理/サンプリングログの部分がめっちゃ好きだった!「センシティブデータスキャナー」のセクションに実用的な追加点があるとしたら、検証かな。実際にどの候補が生きたクレデンシャルか分かる?私たちは、クラウドや一般的なSaaS向けに、素早い検出(Hyperscan + Tree-Sitter)と生の検証を組み合わせたオープンソースツール「Kingfisher」を開発中なんだ。これを使えば、誤検知を減らして、本当に重要な秘密に集中できるよ。この投稿で提案されているチョークポイント、CIやリポジトリ/組織のスイープ、Vector/rsyslogのホップ後のサンプリングログアーカイブ(stdin/S3)に接続できる。例えば、こんな感じで使えるよ:kingfisher scan /path/to/app.log --only-valid、kingfisher scan --s3-bucket my-logs --s3-prefix prod/2025/09/。ベースラインを設定することで、時間とともにノイズを減らせるし。リポジトリはこちら:https://github.com/mongodb/kingfisher(Apache-2.0)。開示:私はKingfisherのメンテナンスを手伝ってるよ。