アクセスキーが1本漏れれば、それが侵入の入口になります。2026年10月16日に発表された日本経済新聞社の不正アクセスでは、同社がシステム開発に利用するクラウドサービスの認証情報が盗まれ、約183万件の個人情報が漏えいしました。
連載「事故から逆算するWebセキュリティ」の第7回は、この事案を入口に、長く有効なアクセスキーをやめて「漏れても使えない・すぐ気づける」形にする手順をまとめます。例はAWSで書きますが、考え方はほかのクラウドでも同じです。
WHAT TO REPLACE何を置き換えるか
漏れて困るのは自分で消すまで有効な鍵
長期のアクセスキー
IAM ユーザーの AKIA で始まる鍵
- 無効にするまで使える
- 端末・CI・イメージに写しが残る
- 漏れに気づくまで使われ続ける
一時的な認証情報
SSO・OIDC・ロールが都度発行(ASIA)
- 期限が来ると使えない
- 保存しないので写しが残りにくい
- 誰が発行したかが記録に残る
30秒でわかる(2026年10月17日時点)
- ・問題:IAMユーザーのアクセスキー(AKIAで始まる)は、自分で無効にするまで使える。端末・CI・イメージに写しが残る
- ・対策:人はIAM Identity Center、CIはOIDC、サーバーはロールで一時的な認証情報にする。開発と本番はアカウントを分ける
- ・確認:キーは消しても履歴に残る。AWSの文書の例のキーはgitleaksの既定設定では検出されない(当サイトで実行)
- ・漏れたら:削除より先に無効化。CloudTrailをキーIDで引き、作られたものを消してから取り替える
事案のタイムラインは次のとおりです(日経不正アクセスで183万件漏えい|システム開発に利用するクラウドの認証情報が入口、対象者と開発チームの点検 の整理から)。
| 日時(日本時間) | 出来事 |
|---|---|
| 2026-10-07 未明〜朝 | 盗まれた認証情報で、日経がシステム開発に利用するクラウドサービスに不正アクセス |
| 10-11 | 個人情報保護委員会に報告 |
| 10-16 | 約183万件が漏えいしたと公表。使われた認証情報は無効化済み |
どのクラウドサービスか、開発環境かどうか、認証情報がどう盗まれたかは公表されていません。本記事は日経で何が起きたかを推測せず、同じ入口を自分の環境で塞ぐ方法に絞ります。事案の読み方の全体像は サプライチェーン攻撃とは|手口・防御ツール比較・npm 12の新機構まで実践解説 にまとめています。
日経だけの話ではありません。ラックは10月15日の注意喚起で、7月以降に相次ぐ Web システムからの漏えいについて、クラウドのアクセスキーや API キーが長期間ローテーションされていない事例を確認し、管理不備が侵入の足がかりになっていると書いています。
アクセスキー漏洩はどこから起きるか:開発用の鍵が残る6つの場所
開発用の鍵は、作った人の手を離れて写しが増えていきます。点検するのは次の6か所です。
・Gitの履歴:設定ファイルに書いて、後のコミットで消したもの
・CIのログと設定:デバッグで環境変数を表示した行、リポジトリのシークレットに置いた長期キー
・コンテナイメージ:イメージに入れた .env やビルド引数
・開発者の端末:~/.aws/credentials に何年も残るキー、バックアップ
・チャットとチケット:エラーの相談で貼った設定やログ
・AIコーディングツールの文脈:ツールに読ませた設定ファイルや貼り付けたログ
OWASP の Secrets Management Cheat Sheet は、CI/CD の出力がシークレットを漏らさないこと、コミット前に検出する仕組み(pre-commit フックなど)を開発者の手元に置くことを挙げています。場所が多いほど、すべてを見張るのは難しくなります。だから「漏れない」より先に「漏れても使えない」を目指します。
長く有効な鍵が問題になる理由:認証情報の種類と漏れたときの影響
AWSのアクセスキーIDは、接頭辞で種類が分かります。IAM ユーザーガイドの一意 ID の表では、AKIA が長期のアクセスキー、ASIA が AWS STS の一時的なアクセスキーです。長期のキーは、自分で無効にするまで使えます。漏れてから気づくまでの時間が、そのまま攻撃者の持ち時間になります。
| 認証情報 | 有効な期間 | 漏れたときの影響 | 置き換え先 |
|---|---|---|---|
| IAMユーザーのアクセスキー(AKIA) | 無効化・削除するまで | 気づくまで使われ続ける | 人はIAM Identity Center、ワークロードはロール |
| CIのシークレットに置いた長期キー | 同上 | リポジトリやワークフローの侵害で持ち出される | GitHub Actions の OIDC |
| GetSessionToken の一時的な認証情報(ASIA) | 900秒〜最長36時間 | 期限までは使える | 必要な時間に短く絞る |
| ロール・SSO・OIDCで得た一時的な認証情報(ASIA) | 発行時に決めた期限まで | 期限が来れば使えない | (これが置き換え先) |
| Google Cloud のサービスアカウントキー(JSON) | 長期(README の表現) | 長期キーと同じ | Workload Identity Federation |
GetSessionToken の上限129,600秒(36時間)は、botocore 1.43.62 の STS のモデルで確かめました。一時的な認証情報でも、漏れた時点から期限までは使えます。短くするほど被害の時間は縮みます。
アクセスキー漏洩の対策:長期キーを一時的な認証情報に置き換える
AWSのIAMのベストプラクティスは、最初の2項目で「人はIDプロバイダーとのフェデレーションで一時的な認証情報を使う」「ワークロードはIAMロールの一時的な認証情報を使う」ことを求めています。長期のキーは、ロールを使えない外部のツールなど例外の用途に限ります。
人:IAM Identity Center で都度ログインする
開発者の端末から ~/.aws/credentials の長期キーをなくし、IAM Identity Center(旧AWS SSO)でログインして一時的な認証情報を受け取ります。AWS CLI v2 には aws configure sso と aws sso login があります(aws-cli の v2 ブランチのソースで確認。当サイトは Identity Center の環境が無く未検証)。
CI:GitHub Actions は OIDC にする
GitHub の文書は、OIDC を使うとクラウドの認証情報を長期のシークレットとして GitHub に複製せずに済み、発行される短期のトークンは1つのジョブの間だけ有効で自動で失効すると説明しています。ワークフローには id-token: write の権限が要ります。AWS 側のロールの信頼ポリシーでは token.actions.githubusercontent.com:sub を条件にして、どのリポジトリ・ブランチ・環境が引き受けられるかを絞ります。2026年7月15日より後に作られたリポジトリ(と、オプトインしたもの)は、sub にオーナーとリポジトリの不変IDが入るので、信頼ポリシーの書き方を合わせます。CIの権限設計は GitHub Actionsセキュリティ|2026年連鎖攻撃と新ロードマップ完全ガイド にまとめています。
Google Cloud なら、google-github-actions/auth の README が Workload Identity Federation をサービスアカウントキーより勧めています。理由は、長期の認証情報を書き出さずに済むからです。
サーバー:インスタンスとタスクにロールを付ける
EC2 や ECS で動く処理は、.env にキーを書かず、インスタンスやタスクのロールから一時的な認証情報を受け取ります。
届く範囲を絞る:アカウント分離と権限の境界
BLAST RADIUS鍵が届く範囲
開発用の鍵が漏れても本番と権限の作成には届かないようにする
開発用アカウントの境界
- DEV開発用の資源 必要な操作だけ開発アカウントのS3・関数
- PROD本番のデータ アカウントを分ける本番アカウントの利用者データ
- IAMIAMの作成 権限の境界で止めるユーザー・鍵・ロール
- DATA個人情報 合成データにする本番からの複製
置き換えた後も、鍵が届く範囲を絞ります。開発と本番はAWSアカウントを分けます。開発者にロールを作らせるなら、IAMのベストプラクティスにある「権限の境界(permissions boundary)」で、作れる権限の上限を決めます。開発環境に本物の個人情報を複製しないことも、日経の事案から逆算できる点です。
手元で確かめる:履歴と端末に残ったAWSアクセスキーを探す
自システム確認コマンドを、使い捨てのリポジトリで陽性対照と陰性対照をつけて実行しました(2026-10-17、git 2.43.0、gitleaks v8.30.1、AWS CLI 1.46.1)。リポジトリのルートで次を実行します。
# 今のファイルだけを探す(消したキーは出ない)
git grep -nE 'A(KIA|SIA)[A-Z2-7]{16}'
# 全ブランチの履歴から、キーを足した・消したコミットを出す(終了コードは常に0なので出力で判断)
git log --all -G 'A(KIA|SIA)[A-Z2-7]{16}' --format='%h %ad %s' --date=short
# gitleaks で履歴を走査する(値は伏せて表示)
gitleaks git --redact -v .
検体は3つです。キーを足したコミットと消したコミットを積んだリポジトリ2つと、一度も入れていないリポジトリ1つです。
| 検体 | git grep(今のファイル) | git log -G(履歴) | gitleaks |
|---|---|---|---|
AWSの文書の例のキー AKIAIOSFODNN7EXAMPLE |
0件 | 2コミット | 0件 |
| 形式どおりの架空のキー(例ではない) | 0件 | 2コミット | 1件(aws-access-token) |
| キーを入れていない(陰性対照) | 0件 | 0件 | 0件 |
1行目の0件は、gitleaks の既定の規則が .+EXAMPLE$ に一致する値を除外しているためです(v8.30.1 の config/gitleaks.toml で確認)。検出器の動作確認に文書の例のキーを使うと、動いていないように見えます。陽性対照には例ではない値を使います。シークレットスキャナの選び方は Betterleaks徹底解説|Gitleaks原作者の新シークレットスキャナと98.6%の数字の正体 で比べています。
端末側は、長期キー(AKIA)が残っていないかと、CLIがどこから認証情報を読んでいるかを見ます。
grep -rnE 'AKIA[A-Z2-7]{16}' ~/.aws
aws configure list
長期キーを置いた仮のホームでは1件ヒットし、aws configure list の Type 列が shared-credentials-file でした。SSOの設定と一時的な認証情報(ASIA)のキャッシュだけを置いた仮のホームでは0件でした。
ここまでのコマンドは、リポジトリと端末にキーが残っているかの確認で、漏れたかどうかの判定ではありません。0件でも、CIのログ・コンテナイメージ・チャットなど走査していない場所に写しがあれば安全とは言えず、漏れて使われたかは次の節の最終使用日と CloudTrail で確かめます。
漏れたことに気づく:CloudTrail・GuardDuty・最終使用日
使っていないキーを先に消す
GetAccessKeyLastUsed は、キーを最後に使った日時・サービス・リージョンを返します(2015年4月22日から記録)。IAM Access Analyzer の未使用アクセスの検出結果には、UnusedIAMUserAccessKey・UnusedIAMRole・UnusedPermission があります(いずれも botocore 1.43.62 のモデルで確認)。使っていないキーは、漏れる前に消せます。
いつもと違う呼び出しを見る
CloudTrail の LookupEvents は、リージョンごとに過去90日の管理イベントを AccessKeyId で絞り込めます。普段使わないリージョン、CreateUser・CreateAccessKey・RunInstances のような呼び出しが目印です。
GuardDuty の UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS(既定の重大度は High)は、EC2 のインスタンスに発行された一時的な認証情報が AWS の外から使われたときに出ます。別の AWS アカウントから使われた場合は .InsideAWS です。名前のとおりインスタンスの認証情報が対象で、IAMユーザーの長期キーの漏れを拾う候補は、CredentialAccess:IAMUser/AnomalousBehavior などの異常検知と、悪意のあるIPからの呼び出しの検出です。
アクセスキー漏洩に気づいた最初の1時間
FIRST HOUR最初の1時間
消す前に止めて、記録を引いてから取り替える
-
鍵を無効にする
削除せず Inactive に。発行済みの一時的な認証情報は別に止める
-
CloudTrail をキー ID で引く
AccessKeyId で 90 日分。全リージョンを見る
-
作られたものを消す
新しい IAM ユーザー・鍵・ロール、EC2、Lambda
-
置き換えて元の鍵を消す
一時的な認証情報へ移し、履歴と置き場所も掃除
OWASP の Cheat Sheet は、漏れたシークレットへの対応を「失効 → 取り替え → 削除」の順に挙げています。AWSでは次の順にします。
・無効にする:削除ではなく Inactive にする。必要なら戻せる
・記録を引く:CloudTrail をキーIDで、使っているリージョンすべてで引く
・作られたものを消す:IAMユーザー・アクセスキー・ロール・ポリシー、EC2・Lambda・請求の急増
・置き換える:一時的な認証情報に移し、履歴・ログ・イメージに残った値も消す
キーを無効にしても、そのキーで発行済みの一時的な認証情報は止まりません。STSが発行した一時的な認証情報は期限まで有効で、取り消せないと IAM ユーザーガイドにあります。止めるには権限の側で拒否します。ロールなら「Revoke active sessions」が AWSRevokeOlderSessions というインラインポリシーで古いセッションを拒否します。IAMユーザーなら、全拒否のポリシーを付けます(AWSセキュリティブログの手順)。
公開された場所でキーが見つかると、AWS は管理ポリシー AWSCompromisedKeyQuarantineV3 をそのユーザーに付けます。AWSのリファレンスは、このポリシーを自分で外さず、サポートケースの指示に従うよう書いています。管理ポリシーを記録している zoph-io/MAMIP の写しでは、既定の版 v3 は2026-03-16付で、21サービスの99操作を拒否します。iam:CreateUser・iam:CreateAccessKey・ec2:RunInstances・s3:GetObject・sts:GetSessionToken は含みますが、DynamoDB・RDS・Secrets Manager の操作はありません。付いたことを安全の印にしないでください。
影響範囲を決めるのは、漏れたキーの権限です。開発用のキーで本番のデータが読めたなら、被害は本番と同じです。
本記事で確かめていないこと
・IAM Identity Center での aws sso login と、GitHub Actions の OIDC で AWS に入る流れは、実際のアカウントで動かしていない
・GuardDuty の検出結果は文書で名前を確かめただけで、発生させていない
・AWSCompromisedKeyQuarantineV3 の中身は第三者のリポジトリの写しで、AWS の画面では見ていない
参照ソース
- ラック「国内で相次ぐWebシステムからの情報漏えい~ラックの観測から見える変化と、企業が今とるべき対策」(2026-10-15)
- AWS IAM ユーザーガイド「Security best practices in IAM」(awsdocs/iam-user-guide のアーカイブ(最終更新2023-06-15)の best-practices.md・reference_identifiers.md・id_credentials_temp_control-access.md・id_roles_use_revoke-sessions.md で確認)
- Amazon GuardDuty「IAM finding types」(OutsideAWS は awsdocs/amazon-guardduty-user-guide のアーカイブ(2023-06-15)で確認)
- AWS Managed Policy Reference「AWSCompromisedKeyQuarantineV3」
- AWS Security Blog「What to Do If You Inadvertently Expose an AWS Access Key」(全拒否ポリシーの手順)
- zoph-io/MAMIP「AWSCompromisedKeyQuarantineV3」(AWS管理ポリシーを記録する第三者のリポジトリ。2026-10-17取得)
- botocore(AWS SDK for Python のサービス定義)(1.43.62 の STS・CloudTrail・IAM・Access Analyzer のモデルを読んだ)
- GitHub Docs「OpenID Connect」と「Configuring OpenID Connect in Amazon Web Services」(github/docs の原稿を2026-10-17に取得)
- google-github-actions/auth README(2026-10-17取得)
- OWASP Secrets Management Cheat Sheet(OWASP/CheatSheetSeries の原稿を2026-10-17に取得。§8 Detection・§9 Incident Response)
- gitleaks v8.30.1 の既定設定 config/gitleaks.toml





