detecting-compromised-cloud-credentials について
クラウドセキュリティ分析担当者向けのマルチクラウド認証情報侵害検出スキルです。AWS、Azure、GCPの不審な活動を調べ、クラウド間の相関分析から封じ込め、永続化の確認まで扱います。
主な機能
- 01AWS、Azure、GCPの不正利用指標の確認
- 02IDサインインと監査ログの分析
- 03SIEMでのクラウド横断シグナル相関
- 04認証情報侵害の封じ込め
- 05攻撃者による永続化の確認
活用シーン
- 01不慣れな場所からのクラウドAPI活動の調査
- 02クラウド事業者からの認証情報漏えい通知への対応
- 03クラウド横断の認証情報不正利用検出ルールの構築
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill detecting-compromised-cloud-credentialsインストール後、Claude Code で/detecting-compromised-cloud-credentialsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSEreferences/api-reference.mdscripts/agent.py詳細
クラウド認証情報の侵害を検出する
使用する場面
- 見慣れない場所からの不審なクラウド API アクティビティに関するアラートを調査する場合
- クラウド環境全体での認証情報の窃取や不正使用を検出するルールを作成する場合
- クラウドプロバイダーから認証情報の漏えいに関する通知を受けて対応する場合
- クラウド ID に対するクレデンシャルスタッフィングやブルートフォース攻撃を監視する場合
- 初回検出後に認証情報侵害の範囲を評価する場合
次の用途には使用しないでください。認証情報の侵害を防止する場合(MFA、認証情報のローテーション、シークレット管理を使用してください)、アプリケーションレベルの認証情報窃取を検出する場合(アプリケーションセキュリティ監視を使用してください)、またはエンドポイントでの認証情報窃取を検出する場合(EDR ツールを使用してください)。
前提条件
- すべてのアカウントとリージョンで AWS GuardDuty が有効になっていること
- Azure Defender for Identity と Entra ID Protection が設定されていること
- Event Threat Detection が有効な GCP Security Command Center があること
- CloudTrail、Azure Activity Log、GCP Audit Log が分析用に一元化されていること
- クラウド間で認証情報不正使用の兆候を相関分析するための SIEM 統合があること
- 既知の悪意のある IP アドレス範囲に関する脅威インテリジェンスフィードがあること
ワークフロー
ステップ 1:AWS で認証情報侵害の兆候を検出する
認証情報の不正使用を示す GuardDuty の検出結果と CloudTrail の異常を監視します。
# List GuardDuty credential-related findings
aws guardduty list-findings \
--detector-id $(aws guardduty list-detectors --query 'DetectorIds[0]' --output text) \
--finding-criteria '{
"Criterion": {
"type": {
"Eq": [
"UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS",
"UnauthorizedAccess:IAMUser/MaliciousIPCaller",
"UnauthorizedAccess:IAMUser/MaliciousIPCaller.Custom",
"UnauthorizedAccess:IAMUser/TorIPCaller",
"UnauthorizedAccess:IAMUser/ConsoleLoginSuccess.B",
"Recon:IAMUser/MaliciousIPCaller",
"Recon:IAMUser/MaliciousIPCaller.Custom",
"InitialAccess:IAMUser/AnomalousBehavior",
"CredentialAccess:IAMUser/AnomalousBehavior",
"Persistence:IAMUser/AnomalousBehavior"
]
},
"service.archived": {"Eq": ["false"]}
}
}' --output json
# Check for console logins from new locations
aws logs start-query \
--log-group-name cloudtrail-logs \
--start-time $(date -d "7 days ago" +%s) \
--end-time $(date +%s) \
--query-string '
fields @timestamp, userIdentity.userName, sourceIPAddress, responseElements.ConsoleLogin
| filter eventName = "ConsoleLogin"
| filter responseElements.ConsoleLogin = "Success"
| stats count() by userIdentity.userName, sourceIPAddress
| sort count desc
'
# Detect impossible travel (same user from geographically distant IPs within short time)
aws logs start-query \
--log-group-name cloudtrail-logs \
--start-time $(date -d "24 hours ago" +%s) \
--end-time $(date +%s) \
--query-string '
fields @timestamp, userIdentity.arn, sourceIPAddress, eventName
| filter userIdentity.type = "IAMUser"
| stats earliest(@timestamp) as first_seen, latest(@timestamp) as last_seen,
count_distinct(sourceIPAddress) as unique_ips by userIdentity.arn
| filter unique_ips > 3
'
ステップ 2:Azure で認証情報の不正使用を検出する
侵害された認証情報を示す Entra ID のサインインログと Defender for Identity のアラートを監視します。
# Check for risky sign-ins
az rest --method GET \
--url "https://graph.microsoft.com/v1.0/auditLogs/signIns?\$filter=riskLevelDuringSignIn ne 'none' and createdDateTime ge 2026-02-16T00:00:00Z&\$top=50" \
--query "value[*].{User:userPrincipalName,Risk:riskLevelDuringSignIn,IP:ipAddress,Location:location.city,App:appDisplayName,Status:status.errorCode}" \
-o table
# Check for sign-ins from anonymous or Tor IPs
az rest --method GET \
--url "https://graph.microsoft.com/v1.0/auditLogs/signIns?\$filter=riskEventTypes_v2/any(r:r eq 'anonymizedIPAddress') and createdDateTime ge 2026-02-22T00:00:00Z" \
--query "value[*].{User:userPrincipalName,IP:ipAddress,Location:location.city}" \
-o table
# List users flagged as compromised by Identity Protection
az rest --method GET \
--url "https://graph.microsoft.com/v1.0/identityProtection/riskyUsers?\$filter=riskLevel eq 'high'" \
--query "value[*].{User:userPrincipalName,RiskLevel:riskLevel,RiskState:riskState,LastDetected:riskLastUpdatedDateTime}" \
-o table
# Check for suspicious application consent grants
az rest --method GET \
--url "https://graph.microsoft.com/v1.0/auditLogs/directoryAudits?\$filter=activityDisplayName eq 'Consent to application' and activityDateTime ge 2026-02-16T00:00:00Z" \
--query "value[*].{Activity:activityDisplayName,User:initiatedBy.user.userPrincipalName,App:targetResources[0].displayName}" \
-o table
ステップ 3:GCP で認証情報の不正使用を検出する
GCP の監査ログと SCC の検出結果を照会し、認証情報侵害の兆候を確認します。
# Check SCC Event Threat Detection findings
gcloud scc findings list ORG_ID \
--filter="state=\"ACTIVE\" AND (category=\"ANOMALOUS_CALLER_LOCATION\" OR category=\"SUSPICIOUS_LOGIN\" OR category=\"CREDENTIAL_ACCESS\")" \
--format="table(finding.category, finding.severity, finding.resourceName, finding.eventTime)"
# Query audit logs for service account key usage from unusual IPs
gcloud logging read '
protoPayload.authenticationInfo.principalEmail:*@*.iam.gserviceaccount.com
AND protoPayload.requestMetadata.callerIp!=("10." OR "172." OR "192.168.")
AND timestamp>="2026-02-22T00:00:00Z"
' --limit=100 --format="table(timestamp, protoPayload.authenticationInfo.principalEmail, protoPayload.requestMetadata.callerIp, protoPayload.methodName)"
# Detect API calls from Tor exit nodes
gcloud logging read '
protoPayload.requestMetadata.callerIp:("185." OR "198." OR "45.")
AND protoPayload.authenticationInfo.principalEmail:*@company.com
AND timestamp>="2026-02-22T00:00:00Z"
' --limit=50 --format=json
# Check for new service account keys created (persistence indicator)
gcloud logging read '
protoPayload.methodName="google.iam.admin.v1.CreateServiceAccountKey"
AND timestamp>="2026-02-16T00:00:00Z"
' --format="table(timestamp, protoPayload.authenticationInfo.principalEmail, protoPayload.request.name)"
ステップ 4:クラウド間の相関ルールを作成する
クラウドプロバイダー間で認証情報不正使用の兆候を相関させる SIEM ルールを作成します。
# siem_correlation.py - Cross-cloud credential abuse detection
import json
from datetime import datetime, timedelta
def detect_impossible_travel(events):
"""Detect same identity used from distant locations in short timeframe."""
user_events = {}
for event in events:
user = event.get('principal', '')
ip = event.get('source_ip', '')
ts = event.get('timestamp', '')
cloud = event.get('cloud_provider', '')
key = f"{user}_{cloud}"
if key not in user_events:
user_events[key] = []
user_events[key].append({'ip': ip, 'timestamp': ts, 'cloud': cloud})
alerts = []
for user_key, accesses in user_events.items():
accesses.sort(key=lambda x: x['timestamp'])
for i in range(1, len(accesses)):
time_diff = (datetime.fromisoformat(accesses[i]['timestamp']) -
datetime.fromisoformat(accesses[i-1]['timestamp']))
if time_diff < timedelta(hours=1) and accesses[i]['ip'] != accesses[i-1]['ip']:
alerts.append({
'type': 'IMPOSSIBLE_TRAVEL',
'user': user_key,
'ip_1': accesses[i-1]['ip'],
'ip_2': accesses[i]['ip'],
'time_gap_minutes': time_diff.total_seconds() / 60,
'severity': 'HIGH'
})
return alerts
def detect_credential_stuffing(events, threshold=10):
"""Detect multiple failed logins followed by success."""
user_attempts = {}
for event in events:
user = event.get('principal', '')
success = event.get('success', False)
key = user
if key not in user_attempts:
user_attempts[key] = {'failures': 0, 'success_after_failures': False}
if not success:
user_attempts[key]['failures'] += 1
elif user_attempts[key]['failures'] >= threshold:
user_attempts[key]['success_after_failures'] = True
return [{'user': u, 'failures': d['failures'], 'severity': 'CRITICAL'}
for u, d in user_attempts.items() if d['success_after_failures']]
ステップ 5:確認済みの認証情報侵害に対応する
認証情報の侵害が確認された場合、封じ込め措置を実行します。
# AWS: Deactivate access key immediately
aws iam update-access-key --user-name COMPROMISED_USER \
--access-key-id AKIA_COMPROMISED --status Inactive
# AWS: Invalidate temporary role credentials by updating role trust policy
aws iam update-assume-role-policy --role-name COMPROMISED_ROLE \
--policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Deny","Principal":"*","Action":"sts:AssumeRole"}]}'
# AWS: Revoke all sessions for an IAM user
aws iam put-user-policy --user-name COMPROMISED_USER \
--policy-name RevokeOldSessions \
--policy-document '{
"Version":"2012-10-17",
"Statement":[{
"Effect":"Deny",
"Action":"*",
"Resource":"*",
"Condition":{"DateLessThan":{"aws:TokenIssueTime":"2026-02-23T10:00:00Z"}}
}]
}'
# Azure: Revoke all sign-in sessions
az rest --method POST \
--url "https://graph.microsoft.com/v1.0/users/COMPROMISED_USER_ID/revokeSignInSessions"
# Azure: Force password reset
az ad user update --id COMPROMISED_USER_ID --force-change-password-next-sign-in true
# GCP: Disable service account
gcloud iam service-accounts disable COMPROMISED_SA_EMAIL
# GCP: Delete service account keys
gcloud iam service-accounts keys delete KEY_ID --iam-account=COMPROMISED_SA_EMAIL
主な概念
| 用語 | 定義 |
|---|---|
| 不可能な移動 | 物理的な移動では到達不可能な時間内に、同じ認証情報が地理的に離れた場所から使用されたことを検出するもの |
| クレデンシャルスタッフィング | データ侵害で盗まれたユーザー名とパスワードの組み合わせを使い、複数のクラウドサービスへのログインを試みる攻撃 |
| インスタンス認証情報の流出 | EC2 インスタンスロールの認証情報が、想定される AWS ネットワークの外部から使用されていることを示す GuardDuty の検出結果 |
| 異常な振る舞い | プリンシパルについて確立されたベースラインから大きく逸脱する API 呼び出しパターンを、機械学習に基づいて検出するもの |
| セッションの無効化 | 侵害されたプリンシパルのすべてのアクティブな認証セッションを無効にし、新しい認証情報での再認証を強制すること |
| 永続化の兆候 | 新しいアクセスキーやサービスアカウントキーの作成など、初回侵害後もアクセスを維持するために攻撃者が行う操作 |
ツールとシステム
- AWS GuardDuty:認証情報の侵害や不正アクセスに特化した検出タイプを備える、機械学習ベースの脅威検出サービス
- Microsoft Entra ID Protection:サインインの異常、侵害された認証情報、リスクのあるユーザー行動を検出する ID リスク検出サービス
- GCP Event Threat Detection:GCP 環境における異常な API 使用や認証情報の不正使用を検出する SCC コンポーネント
- CloudTrail / Activity Log / Audit Log:認証情報侵害の調査に使用する生データを提供する API 監査ログ
- SIEM(Splunk、Elastic、Sentinel):クラウド間で認証情報不正使用の兆候を相関分析する一元化プラットフォーム
よくあるシナリオ
シナリオ:フィッシングによって漏えいしたアクセスキーの検出
背景:開発者が AWS コンソールの認証情報を窃取するフィッシングメールを受信します。攻撃者は海外の IP アドレスからログインし、新しいアクセスキーを作成してアカウントの列挙を開始します。
対応手順:
- GuardDuty が、通常とは異なる国からのログインに対して
UnauthorizedAccess:IAMUser/ConsoleLoginSuccess.Bを検知します - SOC が検出結果を確認し、メールセキュリティチームからのフィッシング報告と照合します
- CloudTrail を検索して、侵害されたユーザーが攻撃者の IP アドレスから実行したすべての操作を特定します
- 攻撃者が新しいアクセスキーを作成し、IAM の列挙コマンドを実行したことを確認します
- 直ちにユーザーのすべてのアクセスキーを無効化し、アクティブなセッションを取り消します
- パスワードのリセットを強制し、MFA を再登録します
- 永続化の痕跡がないか確認します:新しい IAM ユーザー、ロール、Lambda 関数、または EC2 インスタンスが作成されていないか調べます
- 永続化に使われた痕跡をすべて削除し、インシデントのタイムラインを記録します
注意点:パスワードを変更するだけでは、既存のアクセスキーやアクティブなセッションは無効になりません。アクセスキーをすべてローテーションし、インシデントの検知前に発行されたトークンに対する全拒否ポリシーを追加して、一時認証情報を取り消す必要があります。攻撃者は、最初の認証情報が無効化される前に、永続化のための新しい IAM ユーザーやロールを作成する場合があります。
出力形式
Cloud Credential Compromise Detection Report
===============================================
Detection Date: 2026-02-23
Scope: Multi-cloud (AWS, Azure, GCP)
Period: 2026-02-16 to 2026-02-23
ACTIVE COMPROMISE INDICATORS:
[CRED-001] AWS Console Login from Unusual Location
User: [email protected]
Source IP: 185.x.x.x (Russia)
Normal Location: US-East
GuardDuty Finding: UnauthorizedAccess:IAMUser/ConsoleLoginSuccess.B
Severity: HIGH
Status: Credential deactivated
[CRED-002] Azure Impossible Travel Detection
User: [email protected]
Location 1: New York, US (09:00 UTC)
Location 2: Beijing, CN (09:15 UTC)
Risk Level: HIGH
Status: Sessions revoked, under investigation
DETECTION METRICS (Last 7 Days):
Impossible travel detections: 5
Anomalous API activity alerts: 12
Failed login attempts > threshold: 3
New credentials from unusual IPs: 2
Total compromises confirmed: 2
CONTAINMENT ACTIONS TAKEN:
AWS access keys deactivated: 3
Azure sessions revoked: 2
GCP service accounts disabled: 1
Passwords force-reset: 4
MFA re-enrolled: 4