アクセスキー漏えいの初動|Gitにpush・チャットに貼ったときの順番

秘密情報を漏らしたと気づいたら、消すより先に止めます。無効化から再発防止までの順番と、報告の文面例を説明します。

漏れた認証情報は消すより先に無効化する。止める・知らせる・調べる・消す・防ぐの順番
漏れた認証情報は消すより先に無効化する。止める・知らせる・調べる・消す・防ぐの順番

.env をうっかりコミットした、ログを貼ったらトークンが写っていた、手順書に本番のパスワードを書いたまま共有した。秘密情報の漏えいは、操作 1 回で誰にでも起こります。気づいた直後は「早く消さなきゃ」と考えがちですが、ベテランが最初に手を付けるのは削除ではありません。漏れた認証情報を使えなくすることです。この記事では、気づいてから再発防止までの順番と、その順番になる理由を説明します。

「消せば大丈夫」が誤りである理由

認証情報は、文字列を知っている人なら誰でも使えます。一度どこかに出た文字列は、元の場所から消しても、すでに読んだ人や保存した仕組みの手元に残ります。公開リポジトリは第三者のツールによって常に走査されており、push から短時間で悪用されることがあります。よくある思い込みと、それが通らない理由を整理します。

思い込み実際に起きていること
コミットを消したから大丈夫push 済みなら、他の人のクローンや CI のキャッシュに残っている。消しただけではキーは有効なまま
force push で履歴を書き換えたから大丈夫GitHub ではフォーク、プルリクエストの参照、コミットの SHA を指定した表示から見えることがある
private リポジトリだから大丈夫閲覧権限のある全員と、連携した外部サービスに渡っている。将来の公開や権限の付け間違いでも広がる
チャットの投稿を削除したから大丈夫参加者の通知、端末、検索インデックス、エクスポートに残った可能性がある
数分で気づいたから大丈夫使われていないことは確認するまで分からない。時間の短さは無効化しない理由にならない
削除は無効化の代わりにならない

GitHub の公式ドキュメントも、秘密情報を消す前の最初の手順として、その認証情報の無効化やローテーションを求めています。無効化が済めば、その文字列ではもうアクセスできません。履歴からの削除は、その後に必要かどうかを判断する作業です。

初動の順番は「止める・知らせる・調べる・消す・防ぐ」

  1. 止める:漏れた認証情報を無効化し、必要なら新しいものを発行して差し替える。
  2. 知らせる:上長やセキュリティの担当者に、隠さずすぐ報告する。
  3. 調べる:監査ログ、請求、不審なリソースから、使われた形跡がないかを確かめる。
  4. 消す:リポジトリやチャットから秘密情報を取り除く。
  5. 防ぐ:同じ漏えいが起きない仕組みを入れる。

止めることと知らせることは、ほぼ同時に進めてかまいません。自分に無効化の権限がない場合や、本番のアプリが使っているキーで止めると障害になる場合は、先に報告して判断を仰ぎます。迷っているあいだもキーは有効なままなので、一人で抱え込まないことが一番の近道です。

1. 漏れた認証情報をすぐ無効化する

AWS の IAM ユーザーのアクセスキーは、まず状態を Inactive にします。無効にしたキーは後から有効に戻せるので、影響を確かめてから削除できます。本番で使っているキーなら、新しいキーを発行してアプリの設定を差し替え、古いキーを無効にする順で進めます。AWS が公開されたキーを検知して通知を送ってくることもありますが、それを待つ必要はありません。

aws iam list-access-keys --user-name dev-tanakaaws iam update-access-key --user-name dev-tanaka --access-key-id AKIAEXAMPLE123 --status Inactive# 影響が無いことを確かめてから削除するaws iam delete-access-key --user-name dev-tanaka --access-key-id AKIAEXAMPLE123
IAM ユーザーのアクセスキーを確認して無効化する

ほかの認証情報も考え方は同じです。GitHub の個人用アクセストークンは設定画面から削除し、外部サービスの API キーは管理画面で再発行します。DB のパスワードは変更し、そのパスワードを使っているアプリの設定も更新します。同じパスワードを別のシステムで使い回しているなら、そちらも変える必要があります。

2. 隠さず、早く報告する

漏えいを報告するのは気が重いものです。しかし、報告が遅れるほど調べる範囲が広がり、悪用されていた場合の被害も大きくなります。周りの人は責めるためではなく、止める権限や調べる手段を持っているから知らせてほしいのです。報告には、何が、どこに、いつから出ていて、今どこまで対応したかを書きます。

【報告】検証用 AWS アクセスキーを公開リポジトリに push しました・対象:IAM ユーザー dev-tanaka のアクセスキー(ID 末尾 E123)・場所:github.com/example/sample-app の main ブランチ、.env ファイル・期間:10/17 10:05 に push、10:40 に気づきました・対応済み:10:45 にキーを無効化しました。本番では使っていないキーです・これから:CloudTrail でこのキーの操作を確認します。履歴の削除はまだです・相談:他のリージョンの確認と、履歴削除の要否を相談させてください
報告の文面例(秘密情報そのものは書かない)

報告にキーの値そのものを書くと、漏えいの範囲を自分で広げてしまいます。アクセスキー ID の末尾や、ユーザー名、ファイルの場所で特定できるようにします。分かっていないことは「未確認」と書き、推測で「使われていません」と言い切らないようにします。

3. 使われた形跡がないかを確かめる

AWS では、CloudTrail のイベント履歴で、過去 90 日分の管理イベントを追加の設定なしで見られます。属性にアクセスキー ID を指定すると、そのキーで行われた操作だけに絞り込めます。イベント履歴はリージョンごとなので、普段使わないリージョンも含めて確認します。攻撃者は目立たないリージョンでインスタンスを起動することがあるためです。

aws cloudtrail lookup-events --region ap-northeast-1 --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=AKIAEXAMPLE123aws cloudtrail lookup-events --region us-east-1 --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=AKIAEXAMPLE123
アクセスキー ID で CloudTrail のイベント履歴を絞り込む
  • CreateUser や CreateAccessKey など、別の認証情報を作る操作がないか。IAM のようなグローバルサービスの操作は us-east-1 のイベント履歴に記録される。作られていれば、それも無効化する。
  • GetSessionToken や AssumeRole で一時的な認証情報が作られていないか。一時的な認証情報は元のキーを無効にしても期限まで使えるため、作られていれば拒否ポリシーの付与やセッションの取り消しを担当者と相談する。
  • RunInstances など、身に覚えのないリソースを作る操作がないか。
  • 請求ダッシュボードで、普段と違うサービスやリージョンの料金が出ていないか。
  • S3 の読み取りなどのデータイベントは既定では記録されないため、記録がないことを「使われていない」と読まない。

Google Cloud では Cloud Audit Logs、Azure ではアクティビティ ログが同じ役割を持ちます。不審なリソースは、何が作られたかを記録で把握してから止めます。調べる前に手当たり次第に削除すると、被害の範囲が分からなくなります。

4. 履歴やチャットから取り除く

無効化が済んだら、秘密情報を残しておかないために取り除きます。push 前に気づいたなら、コミットをやり直すだけで済みます。push 後に Git の履歴から消す場合は、GitHub のドキュメントが git-filter-repo を使う手順を案内しています。履歴を書き換えるとコミットのハッシュが変わり、共同作業者は古いクローンを捨てて取り直す必要があります。古いクローンから push されると、秘密情報が戻ってくるためです。

GitHub 上のキャッシュされた表示やプルリクエストの参照は、GitHub Support に削除を依頼できます。ただし、認証情報の無効化でリスクを抑えられる場合は対応しない、と GitHub は案内しています。フォークに残ったものは、フォークの持ち主に依頼するしかありません。チャットに貼った場合は、投稿を削除してもらい、同じ情報を転記したメモやチケットがないかも確認します。どの作業も「漏れた事実」を消すものではないことを、改めて意識してください。

5. 同じ漏えいを仕組みで防ぐ

再発防止は「次から気をつける」ではなく、間違えても止まる仕組みで考えます。まず .env や鍵のファイルを .gitignore に書き、値を抜いた .env.example だけをリポジトリに置きます。次に、コミットの前に秘密情報を検知するツールを入れます。AWS Labs の git-secrets や gitleaks は、コミット時にキーらしい文字列を見つけて止められます。

git secrets --installgit secrets --register-awsgit secrets --scan-history
git-secrets でコミット前に AWS のキーを検知する

GitHub の push protection は、push に含まれた秘密情報を検知して push 自体を止めます。個人アカウント向けの push protection は既定で有効で、公開リポジトリへの push を対象にしています。リポジトリ単位の push protection は GitHub Secret Protection が必要で、既定では無効なので、管理者に有効化を相談します。

最も確実なのは、漏れる長期のキーをそもそも持たないことです。クラウドの各サービスには、鍵を保存せずに短期の認証情報を受け取る仕組みがあります。

動かす場所長期キーの代わりに使うもの
AWS の EC2・Lambda などIAM ロールを付与し、一時的な認証情報を自動で受け取る
GitHub Actions などの CIOIDC で短期の認証情報に交換する(Google Cloud では Workload Identity 連携、AWS では IAM ロールの引き受け)
Google Cloud の VM・Cloud Run必要なロールだけを持つサービスアカウントを関連付ける
Azure の App Service・VMマネージド ID を有効にし、必要なロールを割り当てる

秘密情報の漏えいは、隠したり消したりで終わらせようとすると被害が広がり、止めて知らせれば多くの場合は小さく収まります。下の問題で、漏えいに気づいたときの順番を確かめてみてください。

問題で確かめる

この記事の内容を、制限時間つきの問題で確かめられます。

参考

よくある質問

アクセスキーを push したらコミットを消すだけでいい?

いいえ。push した時点で他の人のクローンやキャッシュに写しが残るため、まずキーを無効化します。履歴からの削除は無効化の後に行う作業で、無効化の代わりにはなりません。

private リポジトリに push した場合も無効化が必要?

必要です。閲覧権限のある全員や連携サービスに渡っており、将来の公開や権限の付け間違いでさらに広がることもあるため、漏えいとして扱って無効化します。

チャットに貼ったパスワードは投稿を消せば大丈夫?

投稿を消しても、参加者の通知や端末、履歴のエクスポートに残った可能性があります。投稿の削除に加えて、パスワードを変更して漏れた値を使えなくします。

漏れたキーが使われたかはどう調べる?

AWS なら CloudTrail のイベント履歴をアクセスキー ID で絞り込み、リージョンごとに確認します。あわせて請求の変化や、身に覚えのない IAM ユーザーやインスタンスがないかを見ます。

報告の前に自分で直してから伝えてもいい?

無効化をすぐできるなら先に行ってかまいませんが、報告は並行して早く出します。権限がない場合や本番に影響する場合は、直す前に報告して判断を仰ぎます。