æ¬ããã°ã¯ 2026 幎 8 æ 26 æ¥ã«å
¬éããã AWS Blog â Detecting multi-stage attacks on AWS: A guide to cross-service signal correlation â ã翻蚳ãããã®ã§ãã 1 ã€ã®ã»ãã¥ãªãã£ãµãŒãã¹ããå±ãã¢ã©ãŒãåäœã§ãããã®ã¯ãäœããèµ·ãããšããäºå®ã ãã§ãããã®ã·ã°ãã«ãä»ã®ãµãŒãã¹ã®ã¢ã¯ãã£ããã£ãã客æ§ã®ããžãã¹ã³ã³ããã¹ããšåãããŠèªã¿è§£ãããšã§ãããã倿®µéæ»æã®äžéšãã©ããã倿ã§ããŸãã æ¬¡ã®ãããªçãäžé£ã®æµããèããŠã¿ãŸããããããã¢ã€ãã³ãã£ãã£ãããããŸã§äœ¿çšããããšã®ãªãéä¿¡å
ã¢ãã¬ã¹ãã GetCallerIdentity ãåŒã³åºããŸããæ°å以å
ã«ãåãã¢ã€ãã³ãã£ãã£ãè€æ°ã®ãµãŒãã¹ã«ããã£ãŠ List åŒã³åºããš Describe åŒã³åºããéäžçã«å®è¡ãããã®äžéšã AccessDenied ã§å€±æããŸãããã®çŽåŸãå
é±ç»é²ãããã°ããã®ãã¡ã€ã³ã«åããŠã倧éã®ããŒã¿ãç°å¢å€ãžéåºãããŸãã Amazon GuardDuty ã¯ããªãã¿ã®ãªãéä¿¡å
ããã®åµå¯ãªã©ããã®æµãã®äžéšã Recon:IAMUser/* ã Discovery:S3/* ãªã©ã®æ€åºçµæã¿ã€ãã§æ¢ã«æ€åºããŠããå¯èœæ§ããããŸããåèŠçŽ ãçžé¢ä»ããããšã§ãã客æ§ã®ããžãã¹ã³ã³ããã¹ããšçµã³ä»ããäžé£ã®æµãã®å
šäœåãææ¡ã§ããŸããããã«ãããæ€åºçµæã 1 ä»¶ãã€ããªã¢ãŒãžããã®ã§ã¯ãªããå
šäœãšããŠå¯ŸåŠã§ããããã«ãªããŸãã ãã®èšäºã¯ã Amazon Web Services (AWS) ã®æ€åºãµãŒãã¹ãéçšããŠãããèªèº«ã®ç°å¢ã«åºæã®ãã¿ãŒã³ããšããããã»ãã¥ãªãã£ãšã³ãžãã¢ãšã»ãã¥ãªãã£ãªãã¬ãŒã·ã§ã³ããŒã ã察象ãšããŠããŸããAWS ã®æ€åºæ©èœãšããžãã¹ã³ã³ããã¹ããã©ã®ããã«çµã¿åãããã®ãããããŠãã®ã³ã³ããã¹ããæŽ»çšããçžé¢åæãã©ã®ããã«æ§ç¯ããã®ãã説æããŸããäŸã¯ãããã Amazon CloudWatch Logs Insights ã§å®è¡ã§ããã®ã§ãããã«è©ŠããŸããæåŸã®ã»ã¯ã·ã§ã³ã§ã¯ãããããèªååããããã€ãã©ã€ã³ãžçºå±ãããæ¹æ³ã説æããŸãããããã®ã¯ãšãªã®åææ¡ä»¶ã¯ããã®èšäºã®åŸåã®ãŠã©ãŒã¯ã¹ã«ãŒã«èšèŒããŠããŸãã AWS ã®æ€åºãµãŒãã¹ããå§ãã ãŸã㯠AWS ã®æ€åºãµãŒãã¹ã掻çšããŸãããããããã®ãµãŒãã¹ã¯å€ãã®ã客æ§ã«å
±éããè
åšãã«ããŒããŠããããã®èšäºã®å
容ããã¹ãŠããããåºç€ãšããŠããŸãã Amazon GuardDuty ã¯ã AWS CloudTrail ã Amazon Virtual Private Cloud (Amazon VPC) ãããŒãã°ãDNS ã¯ãšãªãã°ã Amazon Simple Storage Service (Amazon S3) ããŒã¿ã€ãã³ããªã©ã®ã¢ã¯ãã£ããã£ãåæãã远å èšå®ãªãã§ä¿¡é ŒåºŠã®é«ãæ€åºçµæãçæããŸãã Amazon Detective (ãªãœãŒã¹ãšæ€åºçµæã®é¢ä¿ãå¯èŠåããã»ãã¥ãªãã£èª¿æ»ãµãŒãã¹) ã䜿çšãããšããµãŒãã¹ãã¢ã«ãŠã³ãããŸããã ã°ã©ãããŒã¹ã®ã³ã³ããã¹ãã§æ€åºçµæã調æ»ã§ããŸãã AWS Security Hub ã¯ãã»ãã¥ãªãã£ã®æ€åºçµæãéçŽããåªå
é äœä»ããããåäžã®ããã·ã¥ããŒãã«è¡šç€ºããŸãã Amazon Security Lake ã¯ãã»ãã¥ãªãã£ããŒã¿ãå°çšã®ããŒã¿ã¬ã€ã¯ã«äžå
åããé·æçãªåæã«åã㊠Open Cybersecurity Schema Framework (OCSF) 圢åŒã§ä¿åããŸãã Amazon Inspector (ã¯ãŒã¯ããŒãã®ãœãããŠã§ã¢ã®è匱æ§ãã¹ãã£ã³ããè匱æ§ç®¡çãµãŒãã¹) ã¯ãè匱æ§ããŒã¿ãã¯ãŒã¯ããŒãã®ã³ã³ããã¹ããšçžé¢ä»ããŸãã ç¬èªã®ä»çµã¿ãæ§ç¯ããåã«ããããã®ãµãŒãã¹ãæå¹ã«ããŠãã¥ãŒãã³ã°ããŠãã ãããããã§ãããã¥ãŒãã³ã°ãšã¯ãç°å¢ã«åãããŠæåºŠã調æŽããŠèª€æ€ç¥ãæžããããšãåãµãŒãã¹ãç£èŠããããŒã¿ãœãŒã¹ãéžæããããšãæ¢ç¥ã®æ£åžžãªãã¿ãŒã³ã«å¯Ÿããæ€åºçµæãæå¶ããããšãæããŸãã GuardDuty ã倿®µéæ»æãèªåçã«çžé¢ä»ãã æäœæ¥ã§äœããæ§ç¯ããåã«ãGuardDuty ãæ¢ã«äœãããŠãããã®ãã確èªããŸãããã Amazon GuardDuty æ¡åŒµè
åšæ€åº ã¯ã AWS CloudTrail ãAmazon S3 ããŒã¿ã€ãã³ããRuntime Monitoringã Amazon Elastic Kubernetes Service (Amazon EKS) ã®ç£æ»ãã°ãªã©ãè€æ°ã®ããŒã¿ãœãŒã¹ã«ãããã·ã°ãã«ãçžé¢ä»ããŸãããããŠå€æ®µéã®ãã¿ãŒã³ãæ€åºãããšãé倧床ããé倧ãã®æ»æã·ãŒã±ã³ã¹æ€åºçµæã 1 ã€çºè¡ããŸããèªèšŒæ
å ±ã®äŸµå®³ã«ç¶ãããŒã¿æã¡åºã (ãšã¯ã¹ãã£ã«ãã¬ãŒã·ã§ã³) ãªã©ã®ã·ãŒã±ã³ã¹ãèªèãããããã MITRE ATT&CK ã®æŠè¡ã«ãããã³ã°ããããã§ãã¿ã€ã ã©ã€ã³ãšä¿®åŸ©ã¬ã€ãã³ã¹ãæ·»ä»ããŸããçŸåš GuardDuty ãæå¹ã«ããŠããå ŽåãGuardDuty æ¡åŒµè
åšæ€åºã¯ããã©ã«ãã§æ¢ã«æå¹ã«ãªã£ãŠãããã¯ãšãªãäœæããå¿
èŠã¯ãããŸãããGuardDuty ã®æéã®é©ç𿹿³ã®è©³çްã«ã€ããŠã¯ãã Amazon GuardDuty ã®æé ããåç
§ããŠãã ããã åé ã®äŸã§ç€ºããèªèšŒæ
å ±ã®äŸµå®³ã·ãŒã±ã³ã¹ã¯ããŸãã« GuardDuty æ¡åŒµè
åšæ€åºãæ€åºå¯Ÿè±¡ãšããæ®éçãªãã¿ãŒã³ã§ãããã®ãããªãã¿ãŒã³ã®æ€åºã¯ GuardDuty æ¡åŒµè
åšæ€åºã«ä»»ããŠãã ãããæ»æã·ãŒã±ã³ã¹æ€åºçµæã¯ GuardDuty ã³ã³ãœãŒã«ã§ä»ã®æ€åºçµæãšäžŠãã§è¡šç€ºãããä»ã®æ€åºçµæãšåãããã« Security Hub ã察å¿ã¯ãŒã¯ãããŒã«ã«ãŒãã£ã³ã°ãããŸãã GuardDuty ã察åŠããã®ã¯ãã©ã®ã¢ã«ãŠã³ãã§ãåãããã«èŠããè
åšã§ããäžæ¹ã§ GuardDuty ã«ã¯ãããæäœãã客æ§ã®ã¢ã«ãŠã³ãã§ã¯äžå¯©ã ãšå€æããããã®ã³ã³ããã¹ãããããŸããããã®ã³ã³ããã¹ããæäŸããã®ãã客æ§ã®åœ¹å²ã§ãã ããžãã¹ã³ã³ããã¹ãã远å ãã ããžãã¹ã³ã³ããã¹ããšã¯ãã客æ§ã®ç°å¢ã«ã€ããŠã客æ§ã ããç¥ã£ãŠããæ
å ±ã§ããäŸãã°ãã©ã®ãã±ããã«æ©å¯ããŒã¿ãä¿åãããŠããããã©ã®ããªã³ã·ãã«ãã©ã®ãªãœãŒã¹ã«ã¢ã¯ã»ã¹ããæ£åœãªçç±ãæã£ãŠããããããªã·ãŒã§ã©ã®ããŒã«ãã§ãŒã³ãèš±å¯ãããŠããããæ¬çªç°å¢ã®å€æŽãŠã£ã³ããŠããã€ããšãã£ãæ
å ±ã§ããGuardDuty æ¡åŒµè
åšæ€åºã¯å€ãã®ã客æ§ã«å
±éãããã¿ãŒã³ããåŠç¿ããŸãããããããç°å¢åºæã®åãã«ã¯çããããŸãããããããçžé¢åæãšããŠè¡šçŸããããšã§ãã客æ§ã®ç°å¢ã«åãããŠãã¥ãŒãã³ã°ãããæ€åºã¬ã€ã€ãŒã远å ã§ããŸãã以äžã® 4 ã€ã®ãã¿ãŒã³ã§ã¯ãããããäºå®ããããã 1 ã€ãã€ã¯ãšãªã«èœãšã蟌ã¿ãŸãã ãããã®ã¯ãšãªã¯ãAWS ãããžã¡ã³ãã³ã³ãœãŒã«ã§ CloudWatch ãéãã [ãã°] ã [ãã°ã®ã€ã³ãµã€ã] ã®é ã«éžæããŠã CloudWatch Logs Insights ã®ã¯ãšãªèšèª ã§å®è¡ããŸããã»ãšãã©ã®ã¯ãšãªã¯ã 蚌跡ã®é
ä¿¡å
ã§ãã CloudWatch Logs ãã°ã°ã«ãŒããã CloudTrail ã€ãã³ããèªã¿åããŸãã蚌跡ã®åºåå
ã Amazon S3 ã®ã¿ã®å Žåã¯ã蚌跡㫠CloudWatch Logs ãžã®é
ä¿¡ã远å ãããã Amazon Athena (SQL ã䜿çšã㊠Amazon S3 ã®ããŒã¿ãåæãããµãŒããŒã¬ã¹ã®ã¯ãšãªãµãŒãã¹) ã§åçã®ã¯ãšãªãå®è¡ããŠãã ããã æ³š : ãã®èšäºã®ã¯ãšãªãšã³ãŒãã§ã¯ããã¬ãŒã¹ãã«ããŒå€ã䜿çšããŠããŸããå®è¡åã«ã your-sensitive-bucket (S3 ãã±ããå)ã your-key-id (AWS KMS ã㌠ID)ã region (us-east-1 ãªã©ã® AWS ãªãŒãžã§ã³)ã account-id (12 æ¡ã® AWS ã¢ã«ãŠã³ã ID)ã aws-cloudtrail-logs-my-trail (CloudTrail ãã°ã°ã«ãŒãå) ãå®éã®å€ã«çœ®ãæããŠãã ããã ãã«ãã¢ã«ãŠã³ãç°å¢ã«ã€ããŠãè£è¶³ããŠãããŸãã AWS Organizations ã§ã¯ã çµç¹ã®èšŒè·¡ ããã¹ãŠã®ã¢ã«ãŠã³ãã®ã€ãã³ãã 1 ã€ã®ãã°ã°ã«ãŒãã«é
ä¿¡ããŸãããã®ããããããã®ã¯ãšãªã¯ãã®ãŸãŸæ©èœããŸãããè€æ°ã¢ã«ãŠã³ãã«ãŸãããçµæãè¿ãããŸããã¢ã«ãŠã³ãåäœã§ç¢ºèªããã«ã¯ã recipientAccountId ã§ãã£ã«ã¿ãªã³ã°ããŠãã ãããçµç¹ã®èšŒè·¡ã䜿çšããŠããªãå Žåã¯ãã¢ã«ãŠã³ãããšã«ã¯ãšãªãå®è¡ãããã Amazon Security Lake ãäžå
çãªã¯ãšãªã®åºç€ãšããŠäœ¿çšããŠãã ããã AWS ãµãŒãã¹ã«ãããã³ã°ããæ»æãã§ãŒã³ 倿®µéæ»æã¯ 5 ã€ã®ãã§ãŒãºãçµãŠé²è¡ãããã§ãŒãºããšã«ç°ãªããµãŒãã¹ã«ã·ã°ãã«ãæ®ããŸãããããã®ã·ã°ãã«ã¯ã次㮠3 ã€ã®ãã°ãœãŒã¹ã«çŸããŸããã¢ã«ãŠã³ãå
ã® API ã¢ã¯ãã£ããã£ãèšé²ãã CloudTrailããããã¯ãŒã¯æ¥ç¶ã®ã¡ã¿ããŒã¿ããã£ããã£ãã Amazon VPC ãããŒãã°ããã㊠VPC ããã® DNS ã¯ãšãªãèšé²ãã Amazon Route 53 Resolver ã¯ãšãªãã°ã§ãã åæã¢ã¯ã»ã¹ â çãŸããèªèšŒæ
å ±ãç°å¢å
ã§äœ¿çšãããŸããCloudTrail ã«ã¯ããªãã¿ã®ãªãéä¿¡å
ããã® GetCallerIdentity ã GetSessionToken ããŸã㯠AssumeRole ãèšé²ãããŸãã æ¢çŽ¢ â è
åšã¢ã¯ã¿ãŒã¯ List ã Describe ã Get ã®åŒã³åºãã§ãªãœãŒã¹ãåæããŸãããã®éãå€ãã®å Žå AccessDenied ã¬ã¹ãã³ã¹ãçºçããŸãã æš©éææ Œ â è
åšã¢ã¯ã¿ãŒã¯ããŒã«ãé£éãããããããªã·ãŒãç·šéãããããŸããCloudTrail ã«ã¯ã AssumeRole ã®ã·ãŒã±ã³ã¹ã PutRolePolicy ããŸã㯠CreateAccessKey ãèšé²ãããŸãã ã©ãã©ã«ã ãŒãã¡ã³ã (暪å±é) â è
åšã¢ã¯ã¿ãŒã¯ã¢ã«ãŠã³ãã AWS ãªãŒãžã§ã³ããŸããã§ç§»åããæ®æ®µäœ¿ãããŠããªãå Žæã§ããŒã«ãåŒãåãããããªãœãŒã¹ãäœæãããããŸãã ããŒã¿æã¡åºã â å€§èŠæš¡ãª GetObject åŒã³åºããVPC ãããŒãã°ã«èšé²ããã倧éã®ã¢ãŠãããŠã³ã転éãRoute 53 Resolver ã¯ãšãªãã°ã«èšé²ãããæè¿ç»é²ããããã¡ã€ã³ãžã® DNS ã¯ãšãªãéããŠãããŒã¿ãæã¡åºãããŸãã å³ 1 ã¯ã5 ã€ã®æ»æãã§ãŒãºãšãåãã§ãŒãºãèšé²ãã AWS ã®ãã°ãœãŒã¹ãšã®å¯Ÿå¿ã瀺ããŠããŸãã å³ 1: AWS ãµãŒãã¹ã«ãããã³ã°ããæ»æãã§ãŒã³ GuardDuty æ¡åŒµè
åšæ€åºã¯ããã®ãã§ãŒã³å
šäœãå¯Ÿè±¡ã«æ®éçãªãã¿ãŒã³ãç£èŠããŸãã以äžã® 4 ã€ã®ãã¿ãŒã³ã§ã¯ãããã«ã客æ§ãªãã§ã¯ã®èгç¹ãã€ãŸãããžãã¹ã³ã³ããã¹ãã远å ããŸãã ãã¿ãŒã³ 1: æ³å®å€ã®ããªã³ã·ãã«ã«ããæ©å¯ããŒã¿ãžã®ã¢ã¯ã»ã¹ ãã®æ€åºãæ¯ããã®ã¯ãããŒã¿åé¡ãšéåžžã®ã¢ã¯ã»ã¹ãã¿ãŒã³ã§ããäŸãã°ããããã±ããã«ã¯é¡§å®¢èšé²ããå¥ã®ãã±ããã«ã¯å
¬éãŠã§ãã¢ã»ãããä¿åãããŠãããšããŸããã客æ§ã¯ãæ©å¯æ§ã®é«ã顧客èšé²ãèªã¿åãæ£åœãªçç±ãããããªã³ã·ãã«ãã©ãããææ¡ããŠããŸãããã®ç¥èãã«ãŒã«ãšããŠçµã¿èŸŒããšãäžèŠãããµããèªã¿åããã远跡ãã¹ãäºè±¡ã«å€ãããŸãã ããã§ã¯ 3 ã€ã®ã·ã°ãã«ãéãªãåããŸããCloudTrail ã«ã¯ãæ©å¯ãšããŠåé¡ãããã±ããã«å¯Ÿãã倧éã® GetObject ãèšé²ãããŸãããã®ããªã³ã·ãã«ã¯ããã®ãã±ããã®èªã¿åããæ³å®ãããããªã³ã·ãã«ã®ãªã¹ãã«å«ãŸããŠããŸãããããã«ãVPC ãããŒãã°ã«ã¯åãæéæ å
ã«åãéä¿¡å
ããã®å€§éã®ã¢ãŠãããŠã³ã転éãèšé²ãããDNS ã¯ãšãªãã°ã«ã¯æè¿ç»é²ãããå®å
ãã¡ã€ã³ãèšé²ãããŸããããããçµã¿åãããããšã§ãæœåšçãªè
åšãååšãããšãã確信床ãé«ãŸããŸãã CloudTrail ã®ç®¡çã€ãã³ãã«ã¯ GetObject ã¯èšé²ãããŸããã GetObject ããã£ããã£ããã«ã¯ã察象ã®ãã±ããã§ CloudTrail ããŒã¿ã€ãã³ããæå¹ã«ãã å¿
èŠããããŸãã該åœãããã±ããã§ããŒã¿ã€ãã³ããæå¹ã«ãªã£ãŠããªãã£ãããã«ã GetObject ãèŠéããŠããããŒã ã¯å°ãªããããŸããã æ¬¡ã®ã¯ãšãªã¯ãæ©å¯ãã±ããã«å¯Ÿãã倧éã®èªã¿åããããªã³ã·ãã«å¥ã«ã°ã«ãŒãåããŠè¡šç€ºããŸããCloudTrail ãã°ã°ã«ãŒããéžæããç¶æ
ã§ãCloudWatch Logs Insights ã§å®è¡ããŠãã ããã fields @timestamp, userIdentity.arn, requestParameters.bucketName | filter eventSource = "s3.amazonaws.com" and eventName = "GetObject" | filter requestParameters.bucketName = "your-sensitive-bucket" | stats count(*) as objectReads, count_distinct(requestParameters.key) as distinctObjects by userIdentity.arn, bin(10m) | filter objectReads > 100 | sort objectReads desc ãããå€ã® 100 ã¯ãã¬ãŒã¹ãã«ããŒã§ããéåžžæã® 1 é±éåã®ã¢ã¯ãã£ããã£ã«å¯ŸããŠã¯ãšãªãå®è¡ãããã®ãã±ããã®èªã¿åãåæ°ã® 95 ããŒã»ã³ã¿ã€ã«ãæ±ããŠããããäžåãå€ããããå€ã«èšå®ããŠãã ãããæ¬¡ã«ãã¯ãšãªãè¿ããåããªã³ã·ãã«ããèªã¿åããæ³å®ãããããªã³ã·ãã«ã®ãªã¹ããšç
§åããŸãããªã¹ãã«å«ãŸããŠããªãããªã³ã·ãã«ã倧éã«èªã¿åã£ãŠããå Žåãããã調æ»ãã¹ãçµæã§ãã è£ä»ããåãã«ã¯ã察å¿ããã¢ãŠãããŠã³ã転éãæ¢ããŸãããã°ã°ã«ãŒãã®éžæã VPC ãããŒãã°ã®ãã°ã°ã«ãŒãã«åãæ¿ããŠã次ã®ã¯ãšãªãå®è¡ããŠãã ããã fields @timestamp, srcAddr, dstAddr, bytes | filter action = "ACCEPT" # exclude RFC 1918 private ranges so only external destinations remain | filter dstAddr not like /^10\./ and dstAddr not like /^192\.168\./ and dstAddr not like /^172\.(1[6-9]|2[0-9]|3[0-1])\./ | stats sum(bytes) as totalBytes by srcAddr, dstAddr, bin(10m) | filter totalBytes > 1000000000 | sort totalBytes desc Amazon S3 ã®ã¯ãšãªã¯ããªã³ã·ãã«ãè¿ããŸããããããŒãã°ã®ã¯ãšãªã¯ IP ã¢ãã¬ã¹ã察象ãšãããããããªã³ã·ãã«ã IP ã¢ãã¬ã¹ã«å€æããå¿
èŠããããŸãããã®å€æã®è©³çްã¯ããã®èšäºã®åŸåã®å®è·µäŸã§èª¬æããŸãã ã¬ããŒãçšãã±ããã 1 æ¥äžèªã¿åã£ãŠããåæããŒã«ãæ³åããŠã¿ãŠãã ãããããæ¥ã®ååŸããã®ããŒã«ãã¬ããŒãçšãã±ããã§ã¯ãªã顧客èšé²ãã±ãããã 1,000 åã®ãªããžã§ã¯ããèªã¿åã£ããšããŸããGuardDuty ã¯åå¿ããŸãããèªèšŒæžã¿ã®ããŒã«ãæå¹ãª GetObject åŒã³åºããè¡ãããšèªäœã¯ãä»ã®ç°å¢ã§ã¯äžå¯©ãšã¿ãªãããªãããã§ããäžæ¹ãã客æ§ã®ã¯ãšãªã¯ãããæ€åºããŸãããã®ããŒã«ãããã®ãã±ããã®èªã¿åããæ³å®ãããããªã³ã·ãã«ã®ãªã¹ãã«å«ãŸããŠããªãããã§ããã客æ§ãé©çšããåé¡ããããäœãèµ·ããŠããªãããã«èŠããç¶æ³ãã·ã°ãã«ã«å€ããã®ã§ãã å³ 2 ã¯ãCloudTrail ã«èšé²ãããæ©å¯ãã±ããããã®å€§éã®èªã¿åããVPC ãããŒãã°ã«èšé²ããã倧éã®ã¢ãŠãããŠã³ã転éãRoute 53 Resolver ãã°ã«èšé²ãããç»é²ãããŠéããªããã¡ã€ã³ã®åå解決ã瀺ããŠããŸãã å³ 2: åäžã®æéæ å
ã§éãªãåããããŒã¿æã¡åºãã瀺ã 3 ã€ã®ã·ã°ãã« ãã¿ãŒã³ 2: ã¢ã¯ã»ã¹ããªã·ãŒãéžè±ããããŒã«ãã§ãŒã³ ãã«ãã®ããã« 1 ã€ç®ã®ããŒã«ãåŒãåããç¶ããŠãªãªãŒã¹ã®ããã« 2 ã€ç®ã®ããŒã«ãåŒãåãããããã€ãæ³åããŠã¿ãŠãã ãããããããªã³ã·ãã«ã«ãšã£ãŠããã® 2 ãããã® AssumeRole ãã§ãŒã³ã¯æ¥åžžçãªãã®ã§ãããå¥ã®ããªã³ã·ãã«ã«ãšã£ãŠã¯ããªã·ãŒéåã«ãªããŸãããã®ãã¿ãŒã³ã®åæãšãªãã®ã¯ãçµç¹ãèš±å¯ãããã§ãŒã³ãã€ãŸãä¿¡é ŒããããžãŒã§ãããã®ç¥èãã¯ãšãªã«çµã¿èŸŒã¿ãŸãããã ãã®ãã¿ãŒã³ã§ã¯ã次㮠3 ã€ã®æ¡ä»¶ãæºãããã®ãæ€åºããŸãã CloudTrail ã«ãçãæéæ å
ã§åãéä¿¡å
ããã®è€æ°ã® AssumeRole åŒã³åºããèšé²ãããŠãã ãã§ãŒã³ã CreateAccessKey ã PutRolePolicy ã AttachUserPolicy ãªã©ã®ã»ãã¥ãªãã£äžéèŠãªã¢ã¯ã·ã§ã³ã§çµãã èµ·ç¹ãšãªãã¢ã€ãã³ãã£ãã£ããããªã·ãŒäžããã®ãã§ãŒã³ãå®è¡ããäž»äœãšããŠæ³å®ãããŠããªã CloudWatch Logs Insights ã§ CloudTrail ãã°ã°ã«ãŒããéžæãã2 ããã以äžã®ãã§ãŒã³ãæœåºããæ¬¡ã®ã¯ãšãªãå®è¡ããŠãã ããã fields @timestamp, userIdentity.arn, requestParameters.roleArn, sourceIPAddress | filter eventName = "AssumeRole" | stats count(*) as assumeCount, count_distinct(requestParameters.roleArn) as rolesAssumed by sourceIPAddress, bin(5m) | filter assumeCount >= 2 and rolesAssumed >= 2 | sort assumeCount desc ãã§ãŒã³ã¯æå°ã§ 2 ãããã§ããç°å¢å
ã§ããŒã«ãé »ç¹ã«é£éãããŠããå Žåã¯ãã«ãŠã³ããåŒãäžããŠãã ããããããã€ãã€ãã©ã€ã³ã¯ 1 æéã«è€æ°ã®ããŒã«ãåŒãåããããšãå€ããAWS Security Hub ãªã©ã® AWS ãµãŒãã¹ããªã³ã·ãã«ãåæ§ã§ãããã€ãã©ã€ã³ããŒã«ãæ¢ç¥ã® AWS ãµãŒãã¹ããªã³ã·ãã«ãªã©ãè€æ°ã®ããŒã«ãåŒãåããããšãæ³å®ãããã¢ã€ãã³ãã£ãã£ã¯é€å€ããŠãã ãããæ®ã£ããã®ã調æ»å¯Ÿè±¡ã§ããäŸãã°ã人ãéåžžãšã¯ç°ãªãæé垯ã«è€æ°ã®ããŒã«ãåŒãåããæçµçã«æ°ããã¢ã¯ã»ã¹ããŒãäœæããŠããã±ãŒã¹ãªã©ã§ãããã®åºå¥ã¯ããŒã¿ãšããŠç®¡çããŠãã ãããã€ãŸããæ£åžžãšã¿ãªãã¢ã€ãã³ãã£ãã£ãšã¢ã¯ã·ã§ã³ããªã¹ãåãããã®ãªã¹ãããå€ãããã§ãŒã³ã確èªããŸãã ãã¿ãŒã³ 3: ããŒãææããã¯ãŒã¯ããŒã以å€ã§äœ¿çšãããæå·åã㌠ããã§ã®ã·ã°ãã«ã¯ããªãœãŒã¹ã®ææé¢ä¿ã§ããç¹å®ã® AWS Key Management Service (AWS KMS) ããŒã¯ã¯ãŒã¯ããŒãã®æå·åããŒãäœæããã³ç®¡çãããã®ã§ã1 ã€ã®ããŒã¯æ±ºæžãµãŒãã¹ãªã© 1 ã€ã®ã¯ãŒã¯ããŒãå°çšã§ããã¹ãã§ããããŒã«å¯Ÿãã Decrypt åŒã³åºãã¯æå¹ãã€èªå¯ããã API ã¢ã¯ã·ã§ã³ãªã®ã§ãåŒã³åºãèªäœã«äžå¯©ãªç¹ã¯ãããŸãããå¥ã®ããªã³ã·ãã«ã«ãããã®ããŒã®äœ¿çšããæ¹ããŠç¢ºèªãã¹ãäºè±¡ã«å€ããã®ã¯ãã客æ§ãå®ããææã«ãŒã«ã§ãã ãã®ãã¿ãŒã³ã¯ã1 ã€ã®ã¯ãŒã¯ããŒãã«éå®ãããã«ã¹ã¿ããŒãããŒãžãããŒã«ã®ã¿é©çšãããŸããAWS ãããŒãžãã㌠( alias/aws/* ) ããæå³çã«è€æ°ã®ãµãŒãã¹éã§å
±æããŠããã«ã¹ã¿ããŒãããŒãžãããŒã«ã¯é©çšãããŸããããã®ã«ãŒã«ããããã€ããåã«ãããŒããªã·ãŒã® Principal ãããã¯ã§ãããŒãåäžã®ã¯ãŒã¯ããŒãåãã§ããããšã確èªããŠãã ããã æ¬¡ã® 2 ã€ã®æ¡ä»¶ããããå Žåã¯ãäžæ£äœ¿çšã®å¯èœæ§ããããŸãã CloudTrail ã«ã1 ã€ã®ã¯ãŒã¯ããŒãã«é¢é£ä»ããããããŒã«å¯Ÿãã Decrypt ãŸã㯠GenerateDataKey ã®åŒã³åºããèšé²ãããŠãã åŒã³åºãå
ã®ããªã³ã·ãã«ãããã®ã¯ãŒã¯ããŒããææããããŒã«ã§ã¯ãªã CloudTrail ãã°ã°ã«ãŒãã«å¯ŸããŠæ¬¡ã®ã¯ãšãªãå®è¡ããç¹å®ã®ããŒã«å¯Ÿã㊠API ãåŒã³åºããããªã³ã·ãã«ãäžèŠ§è¡šç€ºããŸãã fields @timestamp, userIdentity.arn, eventName | filter eventSource = "kms.amazonaws.com" | filter eventName in ["Decrypt", "GenerateDataKey", "Encrypt"] | filter resources.0.ARN = "arn:aws:kms:region:account-id:key/your-key-id" | stats count(*) as keyUses by userIdentity.arn, eventName | sort keyUses desc è¿ãããçµæããæ³å®ããŠãã 1 ã€ã®ã¯ãŒã¯ããŒãããŒã«ãšæ¯èŒããŠãã ããããã®ããŒã䜿çšããæ³å®å€ã®ããªã³ã·ãã«ãèŠã€ããã°ããããã·ã°ãã«ã§ããããŒã®äžæ£äœ¿çšã¯ããŒã¿çªåã®åææ®µéã«èŠãããè¡åã§ããããã®çžé¢åæã§ã¯ãææé¢ä¿ãææ¡ããŠããã客æ§ã«ããæ€åºã§ããªãã¢ã¯ãã£ããã£ããšãããããŸãã æ±ºæžããŒã¿ããŒã¹ãæå·åããŠããããŒãäŸã«èããŠã¿ãŸããããéåžžã®éçšã§ã¯æ±ºæžãµãŒãã¹ã®ããŒã«ããã®ããŒã«å¯Ÿã㊠API ãåŒã³åºãããã以å€ã®ããŒã«ãåŒã³åºãããšã¯ãªãã¯ãã§ããéçºè
ããŒã«ãæ°ããäœæãããããŒã«ããã®ããŒã«å¯Ÿã㊠Decrypt ãå®è¡ããå ŽåãåŒã³åºãã¯æåããåç¬ã§èŠãã°éåžžã®æäœã«ããèŠããŸããããããåé¡ãšããŠæ±ãæ ¹æ ã¯ãã客æ§ãé ã®äžã§ææ¡ããŠããææã«ãŒã«ã§ããããã®ã¯ãšãªã¯ãããææåãããã®ã§ãã ãã¿ãŒã³ 4: 倿ŽãŠã£ã³ããŠå€ã§ã®ç¹æš©ã¢ã¯ã·ã§ã³ ãŸãã¯ãšãªã確èªãããã®ããã§æå³ãèªã¿è§£ããŠãããŸãããã fields @timestamp, userIdentity.arn, eventName, sourceIPAddress | filter eventName in ["PutRolePolicy", "AttachRolePolicy", "CreateAccessKey", "AuthorizeSecurityGroupIngress", "PutBucketPolicy"] | stats count(*) as sensitiveChanges by userIdentity.arn, eventName, sourceIPAddress | sort sensitiveChanges desc ãã®ã¯ãšãªã¯ CloudTrail ãã°ã°ã«ãŒãã«å¯ŸããŠå®è¡ããŸããã¹ã±ãžã¥ãŒã«å®è¡ããéã¯å¯Ÿè±¡æéãæ¥åæéå€ã«çµã蟌ã¿ã倿ŽãŠã£ã³ããŠå€ã®ã¢ã¯ãã£ããã£ã ããè¿ãããããã«ããŸããããã§äœãæ£åžžãšã¿ãªããã¯ãã客æ§ã®å€æŽããã»ã¹ã«ãã£ãŠæ±ºãŸããŸããæ¬çªç°å¢ã®ã»ãã¥ãªãã£ãã¢ã€ãã³ãã£ãã£ã«é¢ãã倿Žã¯ãå®ããããæé垯ã«ãã€ãã©ã€ã³ãéããŠãæ¢ç¥ã®ã¢ã¯ã¿ãŒã«ãã£ãŠå®è¡ãããŸããåå 2 æã«ã³ã³ãœãŒã«ããè¡ãããããªã·ãŒå€æŽãããã€ãã©ã€ã³ã§ã¯ãªã人ã«ãããã®ã§ããã°ãããããæ³å®ã«ã¯åœãŠã¯ãŸããŸãããã·ã°ãã«ãšãªãã®ã¯ã PutRolePolicy ã AuthorizeSecurityGroupIngress ãªã©ã®ã»ãã¥ãªãã£äžéèŠãªå€æŽãããŠã£ã³ããŠå€ã«ããã€ãã©ã€ã³ããŒã«ã§ã¯ãªã人ã«ãã£ãŠè¡ãããå Žåã§ãã æ³å®ãããã¢ã¯ã¿ãŒã¯é€å€ããŠãã ãããäŸãã°ããããã€ãã€ãã©ã€ã³ããŒã«ããããèªååããŒã«ã AWS CloudFormation ã AWS Systems Manager ãªã©ã® AWS ãµãŒãã¹ããªã³ã·ãã«ã§ããæ®ãã®ã¯ãããã»ã¹å€ã§è¡ãããç¹æš©çãªå€æŽã§ããããã¯æ»æè
ãã¢ã¯ã»ã¹ãæ°žç¶åããããã«è¡ãè¡åã§ãããšåæã«ãã客æ§èªèº«ã®å€æŽç®¡çã®èŠåŸã«ç
§ãããŠèµ·ããã¹ãã§ã¯ãªãäºè±¡ã§ããããŸãã ãã€ãã©ã€ã³ã¯ãå¹³æ¥ã®ååŸã«æ¯æ¥å®è¡ããããããã€ã®äžã§ã»ãã¥ãªãã£ã°ã«ãŒãã«ãŒã«ãéæŸããããšããããŸããäžæ¹ã鱿«ã®æ·±å€ã«äººãã»ãã¥ãªãã£ã°ã«ãŒãã«ãŒã«ãéæŸããå Žåã¯ãåã API ã³ãŒã«ã§ãæå³ããŸã£ããç°ãªããŸããäž¡è
ãåºå¥ããã®ã¯ãã¹ã±ãžã¥ãŒã«ãšã¢ã¯ã¿ãŒãšãããã©ã¡ããã客æ§ãå®çŸ©ããäºå®ã§ãã æåã®çžé¢ã«ãŒã«ãæ§ç¯ãã 以äžã®ãŠã©ãŒã¯ã¹ã«ãŒã§ã¯ããã¿ãŒã³ 1 ãäŸã«ãæåããæåŸãŸã§ã®å®è£
æé ã瀺ããŸããä»ã® 3 ã€ã®ãã¿ãŒã³ããããããã®ã¯ãšãªãçšããŠåãèšèšã«åŸããŸãã åææ¡ä»¶ ãã®ãŠã©ãŒã¯ã¹ã«ãŒã®ã¯ãšãªã«å¿
èŠãªããŒã¿ãååŸããã«ã¯ã以äžã®åææ¡ä»¶ãæºããå¿
èŠããããŸããéå§ããåã«ãããããã確èªããŠãã ããã 管çã€ãã³ãã CloudWatch Logs ãã°ã°ã«ãŒãã«èšé²ãã CloudTrail 蚌跡ãããããš æ©å¯æ§ã®é«ã S3 ãã±ããã§ CloudTrail ããŒã¿ã€ãã³ããæå¹ã«ãªã£ãŠããããš GuardDuty ãæå¹ã§ãä¿è·ãã©ã³ãšæ¡åŒµè
åšæ€åºãæå¹ã«ãªã£ãŠããããš VPC ãããŒãã° ãæ¬çª VPC ã§æå¹ã«ãªã£ãŠããããš Amazon Route 53 Resolver ã¯ãšãªãã°èšé² ãæå¹ã«ãªã£ãŠããããš CloudTrailãGuardDutyãVPC ãããŒãã°ãRoute 53 Resolver ã¯ãšãªãã°èšé²ã¯ãçžé¢åæã§çµã³ä»ããçã®ã·ã°ãã«ãæäŸããŸããããããæå¹ã«ãªã£ãŠããªãå Žåããã®èšäºã®ã¯ãšãªã¯ç©ºã®çµæãè¿ããŸãã ã¹ããã 1: ãã±ãããšããã®èªã¿åããæ³å®ãããããªã³ã·ãã«ãèšé²ãã ç£èŠå¯Ÿè±¡ãšããæ©å¯ãã±ããã 1 ã€éžã³ããã®ãã±ããã®èªã¿åããèš±å¯ãããããªã³ã·ãã«ãæžãçããŸãããã®ãªã¹ãã¯ãããŒãžã§ã³ç®¡çãããèšå®ãã¡ã€ã«ã Amazon DynamoDB ããŒãã« (ãããŒãžã NoSQL ããŒã¿ããŒã¹) ãªã©ãèªååã®ä»çµã¿ããã¢ã¯ã»ã¹ã§ããå Žæã«ä¿åããŠãã ããã { "customer-records-prod": [ "arn:aws:iam::123456789012:role/AnalyticsPipeline", "arn:aws:iam::123456789012:role/ComplianceAudit" ], "financial-data-archive": [ "arn:aws:iam::123456789012:role/FinanceReporting" ] } ãã®äŸã§ã¯ããããããããåªå
ããŠãªã¹ããããŒãã³ãŒãããŠããŸããæ¬çªç°å¢ã§ã¯ãåãããã€ããã«æŽæ°ã§ããããã«ãDynamoDB ããŒãã«ã Parameter Store ãããªã¹ããèªã¿èŸŒãã§ãã ããã ã¹ããã 2: ãããå€ãèšå®ããåã«ããŒã¹ã©ã€ã³ãææ¡ãã éåžžæã® 1 é±éåã®ã¢ã¯ãã£ããã£ã«å¯ŸããŠãã¿ãŒã³ 1 ã®ã¯ãšãªãå®è¡ããŸãããã®ãã±ããã®èªã¿åãåæ°ã® 95 ããŒã»ã³ã¿ã€ã«ãæ±ãããããã倧ããå€ãã¢ã©ãŒãã®ãããå€ãšããŠäœ¿çšããŸãããã®ã¹ããããèžãããšã§ãæ£åœãªå€§éã¢ã¯ã»ã¹ãåŸã§èª€æ€ç¥ãåŒãèµ·ããã®ãé²ããŸãã ã¹ããã 5 ã§é¢æ°ãèšå®ããéã«ããã®å€ã THRESHOLD_READS ç°å¢å€æ°ã«èšå®ããŸãã ã¹ããã 3: ã¢ã¯ã»ã¹ã¯ãšãªãå®è¡ãã CloudWatch ã³ã³ãœãŒã«ã§ãæ¬¡ã®æäœãè¡ããŸãã [ãã°] ã [ãã°ã®ã€ã³ãµã€ã] ã®é ã«éžæããŸãã [ãã°ã°ã«ãŒãã®éžæ] ããããããŠã³ã§ãCloudTrail ãã°ã°ã«ãŒããéžæããŸãã æéç¯å²ã [3h] (éå» 3 æé) ã«èšå®ããŸãã ã¯ãšãªãšãã£ã¿ã«ãã¿ãŒã³ 1 ã®ã¯ãšãªã貌ãä»ããŸãã your-sensitive-bucket ããã±ããåã«çœ®ãæããŸãã [ã¯ãšãªã®å®è¡] ãéžæããŸãã çµæããŒãã«ã«è¡šç€ºãããããªã³ã·ãã«ã確èªããŸãã åããªã³ã·ãã«ããã¹ããã 1 ã§èšé²ããèªã¿åããæ³å®ãããããªã³ã·ãã«ã®ãªã¹ããšç
§åãããªã¹ãã«å«ãŸããŠããªããã®ã«ãã©ã°ãä»ããŸãã åçµæã«ã¯ããªã³ã·ãã«ãå«ãŸããŠããŸããã¹ããã 4 ã§ã¯ããã®ããªã³ã·ãã«ã IP ã¢ãã¬ã¹ã«å€æããŸãã ã¹ããã 4: ãããã¯ãŒã¯ã¢ã¯ãã£ããã£ãšçžé¢ä»ãã CloudTrail 㯠AWS Identity and Access Management (IAM) ããªã³ã·ãã«åäœã§ã¢ã¯ã·ã§ã³ãèšé²ããVPC ãããŒãã°ã¯ IP ã¢ãã¬ã¹åäœã§ãã©ãã£ãã¯ãèšé²ããŸãã2 ã€ã®ã·ã°ãã«ãçµã³ä»ããã«ã¯ãããªã³ã·ãã«ã察å¿ãã IP ã¢ãã¬ã¹ã«å€æããŸãã ããŒã«ã Amazon Elastic Compute Cloud (Amazon EC2) ã€ã³ã¹ã¿ã³ã¹ã«ã¢ã¿ãããããŠããå Žåã userIdentity.principalId ãã£ãŒã«ãã®ã³ãã³ã®åŸãã«ã€ã³ã¹ã¿ã³ã¹ ID ãå«ãŸããŸãã圢åŒã¯ AROAEXAMPLE:i-1234567890abcdef0 ã§ãããã®ã€ã³ã¹ã¿ã³ã¹ ID ãã³ããŒãããã©ã€ããŒã IP ã¢ãã¬ã¹ã調ã¹ãŸãã aws ec2 describe-instances \ --instance-ids i-1234567890abcdef0 \ --query "Reservations[0].Instances[0].PrivateIpAddress" \ --output text ä»ã®ã³ã³ãã¥ãŒãã£ã³ã°ã¿ã€ãã§ã¯æ¹æ³ãç°ãªããŸããVPC ã«æ¥ç¶ããã AWS Lambda 颿°ã¯ããµããããå
ã® Elastic Network Interface ãçµç±ããŠãã©ãã£ãã¯ãéä¿¡ããããããããã®ã€ã³ã¿ãŒãã§ã€ã¹ã®ã¢ãã¬ã¹ã§çžé¢ä»ããŸãã Amazon Elastic Container Service (Amazon ECS) ã¿ã¹ã¯ã®å Žåããããã¯ãŒã¯ã€ã³ã¿ãŒãã§ã€ã¹ã¯ã¿ã¹ã¯ã¡ã¿ããŒã¿ã«èšé²ãããŸããã€ã³ã¹ã¿ã³ã¹ã䌎ããªãéåžžã®ããŒã«åŒãåãã»ãã·ã§ã³ã®å Žåã¯ãCloudTrail ã® sourceIPAddress ãã£ãŒã«ãã«åŒã³åºãå
ã®ã¢ãã¬ã¹ãæ¢ã«èšé²ãããŠãããããããã䜿ã£ãŠçŽæ¥çžé¢ä»ããŸãã ãã¿ãŒã³ 1 ã®ãããŒãã°ã®ã¯ãšãªãå®è¡ãã srcAddr ããã®ã¢ãã¬ã¹ã§ãã£ã«ã¿ãªã³ã°ããŠãAmazon S3 ã®èªã¿åãã¿ã€ã ã¹ã¿ã³ããã 10 å以å
ã®ç¯å²ã«çµã蟌ã¿ãŸããäžèŽããçµæãããã°ãåãæéæ å
ã«ãåãéä¿¡å
ãæ©å¯ããŒã¿ã®èªã¿åããšå€§éã®å€éšè»¢éã®äž¡æ¹ãè¡ã£ãŠããããšã«ãªããŸããCloudTrail ã€ãã³ãã CloudWatch Logs ã«å°éããã®ã¯ API ã³ãŒã«ã® 5ïœ15 ååŸãªã®ã§ãã¯ãšãªæå»ã§ã¯ãªã eventTime ã§çžé¢ä»ããŠãã ããããŸããã¯ãšãªã®ã«ãã¯ããã¯æéã¯çžé¢ä»ãã®æéæ ãããåºãåããŸããäŸãã°ã30ïœ60 ååãŸã§ããã®ãŒã£ãŠã¯ãšãªãå®è¡ãã€ã€ãçžé¢ä»ã㯠10 åéã® eventTime ã®æéæ ã§è¡ããŸããã¹ããã 3 ãš 4 ã¯æåã«ããæ€èšŒã§ãã¹ããã 5 ã§ããããèªååããŸãã å³ 2 ã§ã¯ãDNS ã®åå解決ã 3 ã€ç®ã®è£ä»ãã·ã°ãã«ãšããŠç€ºãããŠããŸãããã®ãŠã©ãŒã¯ã¹ã«ãŒã§å®è£
ããã®ã¯ãCloudTrail ãš VPC ãããŒãã°ã®çžé¢åæã§ããDNS ã远å ããã«ã¯ãåã run_query() ã®ãã¿ãŒã³ã Route 53 Resolver ã¯ãšãªãã°ã®ãã°ã°ã«ãŒãã«é©çšããŠãã ããã ã¹ããã 5: ãã§ãã¯ãèªååãã ã¯ãšãªã Lambda 颿° (ãµãŒããŒã管çããã«ã³ãŒããå®è¡ã§ãããµãŒããŒã¬ã¹ã³ã³ãã¥ãŒãã£ã³ã°) ã«ç§»è¡ããçµæãéç¥ãã£ãã«ã«éä¿¡ããŠã宿çã«å®è¡ãããããã«ã¹ã±ãžã¥ãŒã«ãèšå®ããŸãã以äžã®ãµãæé ãé ã«å®è¡ããŠãã ããã éç¥ãã£ãã«ãäœæããã«ã¯ Amazon Simple Notification Service (Amazon SNS) ã³ã³ãœãŒã«ãéããŸããAmazon SNS ã¯ããµãã¹ã¯ã©ã€ããŒã«éç¥ãé
ä¿¡ãããããŒãžãã¡ãã»ãŒãžã³ã°ãµãŒãã¹ã§ãã ããã²ãŒã·ã§ã³ãã€ã³ã§ã [ãããã¯] ãéžæããŸãã [ãããã¯ã®äœæ] ãéžæããŸãã [ã¿ã€ã] ã§ [ã¹ã¿ã³ããŒã] ãéžæããŸãã [åå] ã« security-correlation-alerts ãšå
¥åããŸãã [ãããã¯ã®äœæ] ãéžæããŸãã ãããã¯ã®è©³çްããŒãžã®äžéšã«è¡šç€ºããããããã¯ã® Amazon ãªãœãŒã¹ããŒã (ARN) ãæžãçããŠãããŸãããã® ARN ã¯é¢æ°ã§äœ¿çšããŸãã [ãµãã¹ã¯ãªãã·ã§ã³ã®äœæ] ãéžæããŸãã [ãããã³ã«] ã§ [E ã¡ãŒã«] ãéžæããŸãã [ãšã³ããã€ã³ã] ã«ã E ã¡ãŒã« ã¢ãã¬ã¹ãŸãã¯ã€ã³ã·ãã³ã管çã®ãšã³ããã€ã³ããå
¥åããŸãã [ãµãã¹ã¯ãªãã·ã§ã³ã®äœæ] ãéžæããAWS ããå±ã E ã¡ãŒã« ã§ãµãã¹ã¯ãªãã·ã§ã³ã確èªããŸãã EventBridge Scheduler ã®å®è¡ããŒã«ãäœæããã«ã¯ ã¹ã±ãžã¥ãŒã«ã«ã¯é¢æ°ãåŒã³åºãããã®ããŒã«ãå¿
èŠã§ãããŸãããã®ããŒã«ã®ä¿¡é Œããªã·ãŒã«ã¯ãããŒã«ã®å©çšãã客æ§ãææããã¹ã±ãžã¥ãŒã«ã«éå®ããæ¡ä»¶ãå¿
èŠã§ãããããã®æ¡ä»¶ããªããšãã¹ã±ãžã¥ãŒã©ãµãŒãã¹ã«ã¢ã¯ã»ã¹ã§ããå¥ã®ã¢ã«ãŠã³ãããçè«äžãã®ããŒã«ãåŒã³åºããŠããŸããŸããããã¯ã æ··ä¹±ãã代çåé¡ ããšããŠç¥ãããäžæ£äœ¿çšã®äžçš®ã§ãã 1. scheduler-trust-policy.json ãšããååã®ä¿¡é Œããªã·ãŒãã¡ã€ã«ãäœæããŸãã { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "scheduler.amazonaws.com" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "aws:SourceAccount": "ACCOUNT-ID" }, "ArnLike": { "aws:SourceArn": "arn:aws:scheduler:REGION:ACCOUNT-ID:schedule/*/s3-access-correlation-hourly" } } } ] } 2. ããŒã«ãäœæãã颿°ãåŒã³åºãããã®ã¢ã¯ã»ã¹èš±å¯ãã¢ã¿ããããŸãããã®ããŒã«ã§æå®ãã颿°ä»¥å€ãåŒã³åºããªãããã«ã Resource ã¯ç¹å®ã®é¢æ° ARN ã«éå®ããŠãã ããã aws iam create-role \ --role-name EventBridgeSchedulerRole \ --assume-role-policy-document file://scheduler-trust-policy.json aws iam put-role-policy \ --role-name EventBridgeSchedulerRole \ --policy-name LambdaInvokePolicy \ --policy-document '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:REGION:ACCOUNT-ID:function:CorrelationFunction" } ] }' 颿°ãäœæãããšãLambda ã«ãã£ãŠå®è¡ããŒã«ãèªåçã«äœæãããŸãããã®é¢æ°ã«å¿
èŠãªã¢ã¯ã»ã¹èš±å¯ã¯ãåŸã®æé ã§ãã®ããŒã«ã«ã¢ã¿ããããŸãã çžé¢é¢æ°ããããã€ããã«ã¯ Lambda ã³ã³ãœãŒã« ãéããŸãã [颿°ã®äœæ] ãéžæããŸãã [颿°å] ã« CorrelationFunction ãšå
¥åããŸãã [ã©ã³ã¿ã€ã ] ã§ãææ°ã® Python ã©ã³ã¿ã€ã ãéžæããŸãã [颿°ã®äœæ] ãéžæããŸãã [ã³ãŒã] ã¿ãã§ãããã©ã«ãã®ã³ãŒããæ¬¡ã®é¢æ°ã«çœ®ãæãã [ãããã€] ãéžæããŸãã import os import time import logging import boto3 from botocore.exceptions import ClientError logger = logging.getLogger() logger.setLevel(logging.INFO) logs = boto3.client("logs") sns = boto3.client("sns") ec2 = boto3.client("ec2") CLOUDTRAIL_LOG_GROUP = os.environ["CLOUDTRAIL_LOG_GROUP"] FLOWLOGS_LOG_GROUP = os.environ["FLOWLOGS_LOG_GROUP"] SNS_TOPIC = os.environ["SNS_TOPIC_ARN"] BUCKET = os.environ["SENSITIVE_BUCKET"] THRESHOLD = int(os.environ.get("THRESHOLD_READS", "100")) # Expected readers per bucket EXPECTED_READERS = { "customer-records-prod": [ "arn:aws:iam::123456789012:role/AnalyticsPipeline", "arn:aws:iam::123456789012:role/ComplianceAudit", ], } def run_query(log_group, query, start, end): """Start a Logs Insights query and wait for it to finish.""" started = logs.start_query( logGroupName=log_group, startTime=start, endTime=end, queryString=query, ) query_id = started["queryId"] while True: outcome = logs.get_query_results(queryId=query_id) if outcome["status"] in ("Complete", "Failed", "Cancelled"): break time.sleep(1) if outcome["status"] != "Complete": raise RuntimeError(f"Query did not complete: {outcome['status']}") return [{f["field"]: f["value"] for f in row} for row in outcome["results"]] def private_ip_for_principal(principal_id): """Resolve an EC2 instance role principalId to its private IP.""" if ":" not in principal_id: return None instance_id = principal_id.split(":", 1)[1] if not instance_id.startswith("i-"): return None reservations = ec2.describe_instances(InstanceIds=[instance_id]) for reservation in reservations["Reservations"]: for instance in reservation["Instances"]: return instance.get("PrivateIpAddress") return None def egress_bytes(src_addr, start, end): """Sum external egress bytes for one source address.""" query = f""" fields srcAddr, dstAddr, bytes | filter action = "ACCEPT" and srcAddr = "{src_addr}" | filter dstAddr not like /^10\\./ and dstAddr not like /^192\\.168\\./ and dstAddr not like /^172\\.(1[6-9]|2[0-9]|3[0-1])\\./ | stats sum(bytes) as totalBytes """ rows = run_query(FLOWLOGS_LOG_GROUP, query, start, end) if rows and rows[0].get("totalBytes"): return int(rows[0]["totalBytes"]) return 0 def lambda_handler(event, context): try: # 1-hour lookback absorbs CloudTrail's 5-15 min delivery latency; # correlation happens on eventTime via 10-min bins in the query below. end = int(time.time()) start = end - 3600 # 1 hour lookback allowed = EXPECTED_READERS.get(BUCKET, []) access_query = f""" fields userIdentity.arn, userIdentity.principalId | filter eventSource = "s3.amazonaws.com" and eventName = "GetObject" | filter requestParameters.bucketName = "{BUCKET}" | stats count(*) as objectReads by userIdentity.arn, userIdentity.principalId, bin(10m) | filter objectReads > {THRESHOLD} """ for row in run_query(CLOUDTRAIL_LOG_GROUP, access_query, start, end): principal = row.get("userIdentity.arn") if not principal or principal in allowed: continue message = ( f"Principal {principal} read {row.get('objectReads')} " f"objects from {BUCKET}." ) ip = private_ip_for_principal(row.get("userIdentity.principalId", "")) if ip and egress_bytes(ip, start, end) > 1_000_000_000: message += ( f" The same source ({ip}) also sent a large volume of " f"data to external destinations in the same window." ) sns.publish( TopicArn=SNS_TOPIC, Subject="Unexpected S3 access detected", Message=message, ) except ClientError as error: logger.error(f"AWS API error: {error}") raise except Exception as error: logger.error(f"Unexpected error: {error}") raise finally: logger.info("Correlation check completed") [èšå®] ã¿ãã§ [äžè¬èšå®] ãéžæãã [ç·šé] ãéžæããŸãã [ã¿ã€ã ã¢ãŠã] ã 5 å (300 ç§) ã«èšå®ããŸãã CloudWatch Logs Insights ã®ã¯ãšãªã¯éåæã§å®è¡ãããå€§èŠæš¡ãªãã°ã°ã«ãŒãã§ã¯ 30ïœ60 ç§ãããããšããããŸãã [ä¿å] ãéžæããŸãã [èšå®] ã¿ãã§ [ç°å¢å€æ°] ãéžæãã [ç·šé] ãéžæããŠã CLOUDTRAIL_LOG_GROUP ã FLOWLOGS_LOG_GROUP ã SNS_TOPIC_ARN ã SENSITIVE_BUCKET ã THRESHOLD_READS ã远å ããŸãã [èšå®] ã¿ãã§ [ã¢ã¯ã»ã¹æš©é] ãéžæããå®è¡ããŒã«ãéããŠãæ¬¡ã®æå°æš©éã®ããªã·ãŒãã¢ã¿ããããŸãã { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["logs:StartQuery", "logs:GetQueryResults"], "Resource": [ "arn:aws:logs:REGION:ACCOUNT-ID:log-group:aws-cloudtrail-logs-my-trail:*", "arn:aws:logs:REGION:ACCOUNT-ID:log-group:vpc-flow-logs:*" ] }, { "Effect": "Allow", "Action": "ec2:DescribeInstances", "Resource": "*" }, { "Effect": "Allow", "Action": "sns:Publish", "Resource": "arn:aws:sns:REGION:ACCOUNT-ID:security-correlation-alerts" } ] } REGION ã ACCOUNT-ID ãããã³ãã°ã°ã«ãŒãåãå®éã®å€ã«çœ®ãæããŠãã ããã ec2:DescribeInstances ã¢ã¯ã·ã§ã³ã¯ãªãœãŒã¹ã¬ãã«ã®ã¢ã¯ã»ã¹èš±å¯ããµããŒãããŠããªãããããã®ã¹ããŒãã¡ã³ãã«ã¯ Resource: "*" ãå¿
èŠã§ãããã®ä»ã®ã¹ããŒãã¡ã³ãã¯ãç¹å®ã® ARN ã«éå®ããŠããŸãã èªåå®è¡ãã¹ã±ãžã¥ãŒã«ããã«ã¯ Amazon EventBridge (ã€ãã³ãã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ãæ¥ç¶ãããµãŒããŒã¬ã¹ã®ã€ãã³ããã¹) ã¯ãã¹ã±ãžã¥ãŒã«ã«åŸã£ãŠã¿ãŒã²ãããå®è¡ã§ããŸããå
ã»ã©äœæããããŒã«ã䜿çšããŠãã³ãã³ãã©ã€ã³ããã¹ã±ãžã¥ãŒã«ãäœæããŸãã aws scheduler create-schedule \ --name s3-access-correlation-hourly \ --schedule-expression "rate(1 hour)" \ --target "Arn=arn:aws:lambda:REGION:ACCOUNT-ID:function:CorrelationFunction,RoleArn=arn:aws:iam::ACCOUNT-ID:role/EventBridgeSchedulerRole" \ --flexible-time-window "Mode=OFF" ã¹ããã 6: ãšã³ãªããã¡ã³ãçšã®ã³ã³ããã¹ãã远å ãã (ãªãã·ã§ã³) ãšã³ãªããã¡ã³ãã¯ç¬ç«ããã·ã°ãã«ã远å ããããšã§ããªã¢ãŒãžã®æéãççž®ããŸãããçžé¢åæã®åäœã«å¿
é ã§ã¯ãããŸããããªãããã®ã¹ãããã§ã¯ã³ã¹ããçºçããŸããå°çäœçœ®æ
å ±ãããã€ããŒã« API ã³ãŒã«ã®æéãæ¯æãå¿
èŠãããã»ããLambda ã®å®è¡æéãå»¶ã³ãåãLambda ã®æéãå¢å ããŸããIP ã®å°çäœçœ®æ
å ±ã远å ããã«ã¯ãå°çäœçœ®æ
å ± API ã«ãµã€ã³ã¢ããããæ¬¡ã®é¢æ°ãã³ãŒãã«è¿œå ããŠããã³ãã©ãŒã IP ã解決ããç®æã§åŒã³åºããŸãã import urllib.request import json def geo_context(ip_address): """Enrich an IP address with geolocation data from your provider.""" try: url = f"https://your-geolocation-api.example/json/{ip_address}" with urllib.request.urlopen(url, timeout=5) as response: data = json.load(response) return { "country": data.get("country_name"), "city": data.get("city"), "org": data.get("org"), } except Exception as error: logger.warning(f"Geolocation lookup failed for {ip_address}: {error}") return None ãã³ãã©ãŒã®ã«ãŒãå
ã§ ip ã解決ããåŸã«ãã¢ã©ãŒãã«äœçœ®æ
å ±ã远å ããŸãã if ip: geo = geo_context(ip) if geo: message += ( f" Source location: {geo['city']}, " f"{geo['country']} ({geo['org']})." ) ã¹ããã 7: 远å ã®ãã¿ãŒã³ãšã¢ã«ãŠã³ããžæ¡åŒµãã çžé¢ã«ãŒã«ã®ã©ã€ãã©ãªã倧ãããªã£ãŠããããEventBridgeãLambdaã AWS Step Functions (è€æ°ã®ãµãŒãã¹ãã¯ãŒã¯ãããŒãšããŠé£æºããããµãŒããŒã¬ã¹ã®ãªãŒã±ã¹ãã¬ãŒã·ã§ã³ãµãŒãã¹) ã䜿çšããŠããžãã¯ãèªååããããã€ãã©ã€ã³ã«ç§»è¡ããçžé¢åæã®çµæã Security Hub ã®æ€åºçµæãšäžŠã¹ãŠè¡šç€ºããŸããå€§èŠæš¡ãªãµãŒãã¹æšªæã®çžé¢åæã«ã¯ãCloudWatch ã®çµ±åããŒã¿ããã³ãã¬ã¡ããªæ©èœã掻çšã§ããŸãããã®æ©èœã§ã¯ãã»ãã¥ãªãã£ãšã³ã³ãã©ã€ã¢ã³ã¹ã®ããŒã¿ã OCSF 圢åŒã«å€æããCloudTrailãVPC ãããŒãã°ãDNS ãã°ãªã©ã®ãœãŒã¹ã 1 ã€ã®ã€ã³ã¿ãŒãã§ã€ã¹ããã¯ãšãªã§ããŸããé·æçãªåæã«ã¯ãSecurity Lake ãš Athena ã®çµã¿åãããæåãªéžæè¢ã§ããä¿ææéãšã¯ãšãªã®èŠä»¶ã«åã£ãã¯ãšãªåºç€ãéžæããŠãã ããã å³ 3 ã¯ãEventBridgeãLambdaãStep FunctionsãAWS Security Hub ãªã©ã® AWS ãµãŒãã¹ã§æ§ç¯ããçžé¢åæãã€ãã©ã€ã³ã瀺ããŠããŸãããã®ãã€ãã©ã€ã³ã§ã¯ãããŒã¿ãœãŒã¹ããã¹ã±ãžã¥ãŒã«ãããã¯ãšãªãšãšã³ãªããã¡ã³ããçµãŠãèªå察å¿ãšäžå
çãªå¯èŠæ§ã®ç¢ºä¿ãžãšã€ãªãããŸãã å³ 3: AWS ãµãŒãã¹ã§æ§ç¯ããçžé¢åæãã€ãã©ã€ã³ ãŸãšã ãã®èšäºã§ã¯ãGuardDuty æ¡åŒµè
åšæ€åºã«ããžãã¹ã³ã³ããã¹ããéãåãããã客æ§ã®ç°å¢ã«åºæã®æ»æããšããã 4 ã€ã®çžé¢åæãã¿ãŒã³ã玹ä»ããŸãããã©ã®çžé¢åæãæ§ç¯ããå Žåã«ãå
±éããååãããã€ããããŸãã ã¢ã€ãã³ãã£ãã£ãäž»èŠãªçžé¢ããŒ: åãããªã³ã·ãã«ãè€æ°ã®ãµãŒãã¹ã«ããã£ãŠè¿œè·¡ããŸãã æéæ ãéèŠ (ãã ããæ»æã®çš®é¡ã«ãã£ãŠç°ãªã): èªååãããé«éãªã·ãŒã±ã³ã¹ã§ã¯ãæ°å以å
ã«çºçããã€ãã³ãã¯éåžžé¢é£ããŠããŸãããã®èšäºã§äœ¿çšãã 10 åéã®ãã³ã¯ããã®ãããªãã¿ãŒã³ã«é©ããŠããŸããäžæ¹ãæéããããŠè¡ãããåµå¯ãæåã®åµå¯ã¯æ°æéããæ°æ¥ã«ãããããšããããããèªååããããã¿ãŒã³ãšã¯ç°ãªãããã£ãããšé²ãããããã¿ãŒã³ã®å Žåã¯ãæéæ ãåºããŠãã ããã ã³ã³ããã¹ãã¯ã客æ§ã远å ãããã®: ããŒã¿åé¡ãéåžžã®ã¢ã¯ã»ã¹ãã¿ãŒã³ããªãœãŒã¹ã®ææé¢ä¿ã倿ŽãŠã£ã³ããŠã¯ãã客æ§ãæ€åºã«å ããã·ã°ãã«ã§ãã 1 ã€ã®ã«ãŒã«ããå§ãã: é©åã«ãã¥ãŒãã³ã°ããã 1 ã€ã®çžé¢åæã®ã»ãããçžé¢ä»ããããŠããªã倧éã®ã¢ã©ãŒãããããéèŠãªã¢ã¯ãã£ããã£ãç確ã«ãšãããããŸãã GuardDuty æ¡åŒµè
åšæ€åºã¯ãå€ãã®ã客æ§ã«å
±éãã倿®µéã®ãã¿ãŒã³ã«å¯ŸåŠããŸãããã®èšäºã®çžé¢åæã¯ãã客æ§ã®ããžãã¹ã³ã³ããã¹ãã§ããæäŸã§ããªãã¬ã€ã€ãŒã远å ãããã®ã§ããä»é±ãŸã 1 ã€ã®ãã¿ãŒã³ããå§ããŠã客æ§èªèº«ã®ãã©ãã£ãã¯ã§æ€èšŒããä¿¡é Œæ§ã確èªã§ãããæ¬¡ã®ãã¿ãŒã³ã远å ããŠãã ããã åèè³æ Amazon GuardDuty æ¡åŒµè
åšæ€åº â GuardDuty ã倿®µéæ»æã®ãã¿ãŒã³ãèªåçã«çžé¢ä»ããä»çµã¿ CloudWatch Logs Insights ã®ã¯ãšãªæ§æ â ãã®èšäºã§äœ¿çšããŠããã¯ãšãªèšèªã®ãªãã¡ã¬ã³ã¹ AWS CloudTrail ã«ããããŒã¿ã€ãã³ãã®ãã°èšé² â ãã¿ãŒã³ãäŸåãã Amazon S3 ããŒã¿ã€ãã³ããæå¹ã«ãã CloudWatch Logs ãžã® CloudTrail ã€ãã³ãã®éä¿¡ â ã¯ãšãªå¯èœãªãã°ã°ã«ãŒãã«èšŒè·¡ãé
ä¿¡ãã çµç¹ã®èšŒè·¡ã®äœæ â AWS Organizations å
ã®ãã¹ãŠã®ã¢ã«ãŠã³ãã®ã€ãã³ããåäžã®ãã°ã°ã«ãŒãã«é
ä¿¡ãã VPC ãããŒãã° â ãããã¯ãŒã¯ãã©ãã£ãã¯ã®ã·ã°ãã«ã«é¢ãããã£ãŒã«ããªãã¡ã¬ã³ã¹ Amazon Route 53 Resolver ã¯ãšãªãã°èšé² â è£ä»ãã«äœ¿çšãã DNS ã·ã°ãã«ããã£ããã£ãã MITRE ATT&CK â æ»æã®æŠè¡ãšææ³ã«é¢ããæ¥çãã¬ãŒã ã¯ãŒã¯ Open Cybersecurity Schema Framework (OCSF) â Security Lake ã䜿çšããã¹ããŒã Nisha Kashyap Nisha Kashyap 㯠AWS ã® Senior Support Security Engineer ã§ããè
åšæ€åºãšã»ãã¥ãªãã£éçšãæ
åœããŠããŸããã客æ§ãã»ãã¥ãªãã£ã€ãã³ãã調æ»ããè€æ°ã® AWS ãµãŒãã¹ã«ãŸãããã·ã°ãã«ãçµã³ä»ããŠã客æ§èªèº«ã®ç°å¢ãåæ ããæ€åºã®ä»çµã¿ãæ§ç¯ã§ããããæ¯æŽããŠããŸãã æ¬ããã°ã¯ Security Solutions Architect ã® äžå³¶ ç« å ã翻蚳ããŸããã