Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GuardDutyを使ったサイバー攻撃の検出と分析.pdf

 GuardDutyを使ったサイバー攻撃の検出と分析.pdf

みなさん、SOC(Security Operation Center)という言葉をご存知でしょうか。映画やアニメでよくある怪獣から攻撃を受けた作戦本部をイメージしてください。SOCはサイバー攻撃のアラートを受けるそれのようなものです。しかし、単にアラートを受けるといっても中々ハードルが高いのが現実です。ざっと思いつくだけでも、以下を考えなければいけません。 (1)どのログをとるのか、(2)どうやってログをとるのか、(3)どこにログを収集するのか、(4)どういった条件を満たしたらアラートとなるのか、(5)アラートを何処に飛ばすのか、(6)アラートをどう分析するのか、(7)対応をどう監査するのか、こういったことを自前で考えられる組織は少なく、セキュリティベンダに高額でアウトソースしているところは多いと思います。 昨年のAWS re:inventで発表されたGuardDutyは、そういった面倒な多くの部分を解決してくれるマネージドSOCサービスです。本セッションではGuardDutyがどういった攻撃を検知してくれるか、どういった課題を解決するかといった点をコードと交えて紹介いたします。≥≤                           

406ea2cac59924cedae4629c3c6c84fb?s=128

Kengo Suzuki

July 29, 2018
Tweet

Transcript

  1. AWS GuardDutyΛ࢖ͬͨ αΠόʔ߈ܸͷݕग़ɾ෼ੳ 2018/07/29 by @ken5scal ˜'SPN4PGUXBSF

  2. AWS࢖ͬͯΔਓ!

  3. GuardDuty࢖ͬͯΔਓ!

  4. ·ͣͪ͜ΒΛޚཡ͍ͩ͘͞ IUUQTXXXTMJEFTIBSFOFU"NB[PO8FC4FSWJDFT+BQBOBXTCMBDLCFMUPOMJOF TFNJOBSBNB[POHVBSEEVUZ

  5. ׬

  6. ׬

  7. 1. GuardDuty in nutshell 2. Why GuardDuty? 3. GuardDuty in

    Folio 4. GuardDuty in Future ໨࣍
  8. GuardDuty in NutShell

  9. GuardDuty in nutshell - 2017/11ʹϦϦʔε - ڴҖͷݕ஌ - ػցֶशΛ࢖ͬͨݕ஌ -

    ΫΠοΫσϓϩΠ
  10. GuardDuty in nutshell - 2017/11ʹϦϦʔε - ڴҖͷݕ஌ - ػցֶशΛ࢖ͬͨݕ஌ -

    ΫΠοΫσϓϩΠ
  11. GuardDuty in nutshell - 2017/11ʹϦϦʔε - ڴҖͷݕ஌ - ػցֶशΛ࢖ͬͨݕ஌ -

    IAM΍EC2पΓʹಛԽ - ΫΠοΫσϓϩΠ
  12. ڴҖͷݕ஌

  13. GuardDuty in nutshell - 2017/11ʹϦϦʔε - ڴҖͷݕ஌ - ػցֶशΛ࢖ͬͨݕ஌ -

    IAM΍EC2पΓʹಛԽ - ΫΠοΫσϓϩΠ
  14. ػցֶश - σʔλ in AWS - AWS಺ͷϦιʔε - VPC Flow

    Logs - DNS Logs - CloudTrail Events Logs
  15. ػցֶश - σʔλ from ΠϯςϦδΣϯε - ΦʔϓϯͳΠϯςϦδΣϯεσʔλ - Taxii, STIX,

    OTX - ΠϯςϦδΣϯεσʔλ from αʔϏε - Alien Vault, Fire Eye, Proof Point
  16. GuardDuty in nutshell - 2017/11ʹϦϦʔε - ڴҖͷݕ஌ - ػցֶशΛ࢖ͬͨݕ஌ -

    IAM΍EC2पΓʹಛԽ - ΫΠοΫσϓϩΠ
  17. ΫΠοΫσϓϩΠ - σϓϩΠ in 30sec - ःஅͳͲ͸ͳ͍ͷͰγεςϜతͳӨڹͳ͠ - ۚમతӨڹ͸ݕূՄ

  18. ΫΠοΫσϓϩΠ - σϓϩΠ in 30sec - ःஅͳͲ͸ͳ͍ͷͰγεςϜతͳӨڹͳ͠ - ۚમతӨڹ͸ݕূՄ

  19. None
  20. None
  21. ूத؅ཧ΋Մೳ - ϦʔυλΠϜؚΊͯ30ඵʢ3εςοϓʣ

  22. ΫΠοΫσϓϩΠ - ϦʔυλΠϜؚΊͯ30ඵʢ3εςοϓʣ - γεςϜతͳӨڹͳ͠ - ۚમతӨڹ͸ݕূՄ

  23. ΫΠοΫσϓϩΠ - ϦʔυλΠϜؚΊͯ30ඵʢ3εςοϓʣ - ःஅͳͲ͸ͳ͍ͷͰγεςϜతͳӨڹͳ͠ - ۚમతӨڹ͸ݕূՄ - 30೔ؒແྉ -

    ͦͷޙ: - CloudTrail: 1,000,000events/month - VPC Flow Log, DNC Log: 1GB/month
  24. ֹۚྫ: IUUQTBXTBNB[PODPNKQHVBSEEVUZQSJDJOH

  25. Why GuardDuty?

  26. Why GuardDuty? - AWSͰ͸૝ఆ͢΂͖ڴҖͷछྨ͕૿͑Δ - ैདྷͷݕ஌ϩδοΫͰ͸ෆ଍

  27. ࠓ·ͰͷڴҖݕ஌ in αʔϏε؀ڥ

  28. ैདྷͷߏ੒ 4*&. 8"' -# 8"' -# 'JSFXBMM 'JSFXBMM *%4 1SPYZ

    'JMF *OUFHSJUZ 'JMF *OUFHSJUZ 'JMF *OUFHSJUZ
  29. Firewall - Πϯλʔωοτͱͷڥք๷ޚ - L3~4ϨΠϠʔͷstatefulͳηογϣϯपΓͷݕ஌ - ྫ: ωοτϫʔΫ੍ޚ - ྫ:

    ϙʔτ੍ޚ - ྫ: syn flood߈੍ܸޚ - Untrust΍TrustͳκʔϯΛఆٛ - Juniper Network, Cisco, Yamaha… - ࠓͷ࣌୅ʮͰʁʯͱͳΓ͕ͪ
  30. IDS/IPS - ௨৴಺༰ͷݕ஌ɾγάωνϟϕʔε - ϛυϧ΢ΣΞܥγάωνϟଟΊ - ྫ: σΟϨΫτϦτϥόʔαϧ - ྫ:

    CVEεϖγϑΟοΫ - SnortͳͲ - νϡʔχϯά is େม
  31. WAF - Πϯλʔωοτͱͷڥք๷ޚͦͷ2 - L7ͷHTTP(S)ʹಛԽͨ͠ݕ஌ɾγάωνϟϕʔε - LBʢ࠷ۙ͸CDNʣͱ૊Έ߹ΘͤͰ࢖ΘΕ͕ͪ - 2013೥Ҡߦʹ૿͑࢝Ίͨҹ৅ in

    Japan - BigIP ASM, Imperva, AWS WAF, Fastly, Akamai Kona - νϡʔχϯά is େม
  32. Proxy - Πϯλʔωοτʹग़ΔHTTP(S), SSHͷFQDNݕ஌ - ϗϫΠτϦετ΍ϒϥοΫϦετͷ؅ཧ - SquidͳͲ - ϗϫΠτϦετͳͲͷ؅ཧ

    is େม͔΋
  33. File Integrity - ϑΝΠϧͷෆਖ਼ͳվ͟Μ΍ઃஔΛݕ஌ - TripwireͳͲ - ΤʔδΣϯτͷ؅ཧ is େม

  34. SIEM - Security Information and Event Managementͷུ - ઌड़ͷ੡඼܈ͷϩάΛू໿͠ɺΠϕϯτΛ؅ཧ͢Δ -

    ྫ: ୹࣌ؒͰFirewallʹର͠ɺಉҰૹ৴ݩ͔ΒN݅ͷDeny௨৴͕͋ͬͨ ΒΞϥʔτΛ্͛Δ - ྫ: WAFͰSQL߈ܸγάωνϟʹͻ͔͔ͬΔϦΫΤετʹ200Λฦͨ͠ ΒΞϥʔτΛ্͛Δ - ArchSight, Splunk, Sumo-logic, ELK, Graylog - Eventͷઃఆ is େม
  35. ڴҖͷݕ஌ ͦΕͧΕͷιϦϡʔγϣϯ͕ͲͷΑ͏ͳηΩϡϦςΟϦεΫ

  36. ଟ૚๷ޚ(ݕ஌) IUUQTXXXMPDLIFFENBSUJODPNFOVTDBQBCJMJUJFTDZCFSDZCFSLJMMDIBJOIUNM

  37. ଟ૚๷ޚ(ݕ஌) IUUQTXXXMPDLIFFENBSUJODPNFOVTDBQBCJMJUJFTDZCFSDZCFSLJMMDIBJOIUNM

  38. ଟ૚๷ޚ(ݕ஌) IUUQTXXXMPDLIFFENBSUJODPNFOVTDBQBCJMJUJFTDZCFSDZCFSLJMMDIBJOIUNM

  39. Applicable to AWSʁ        _,,;' '" '' ゛''" ゛' ';;,,       (rヽ,;''"""''゛゛゛'';,

    ノr)       ,;'゛ i _  、_ iヽ゛';,    お前AWSでも同じことできんの?       ,;'" ''| ヽ・〉 〈・ノ |゙゛ `';,       ,;'' "|   ▼   |゙゛ `';,       ,;''  ヽ_人_ /  ,;'_      /シ、  ヽ⌒⌒ /   リ \     |   "r,, `"'''゙´  ,,ミ゛   |     |      リ、    ,リ    |     |   i   ゛r、ノ,,r" i   _|     |   `ー――----┴ ⌒´ )     (ヽ  ______ ,, _´)      (_⌒ ______ ,, ィ       丁           |        |           |
  40. ҟͳΔύϥμΠϜ(AWSʹݶΒͣʣ - ಛੑ্ɺैདྷͷߏ੒Ͱ͸ͳ͔ͬͨ੬ऑੑ͕͋Δ - Ϋϥ΢υαʔϏεͱͯ͠ͷΞΧ΢ϯτ - Ϧιʔεͱݖݶ - ෺ཧతͳ੍໿͕؇͍Ϧιʔε -

    ಈతʹεέʔϧΞ΢τ͢ΔϦιʔε - Pay as you GoͳϦιʔε
  41. ڴҖݕ஌ in GuardDuty

  42. ݕ஌Ͱ͖ΔڴҖ &$ *". #BDLEPPS $SZQUP $VSSFODIZ 1FOUFTU 1FSTJTUFODF 3FDPO #FIBWJPSJBM

    5SB⒏D 7PMVNF 4UFBMUI 5SPKBO 6OBVUIPSJ[FE "DDFTT $POTPMF-PHJO *OTUBODF $SFEFOUJBM &YpMUSBUJPO - Ϧιʔε - ໨త - ڴҖͷछྨ - ୔ࢁ IUUQTEPDTBXTBNB[PODPNHVBSEEVUZMBUFTUVHHVBSEEVUZ@pOEJOHUZQFTIUNMVOBVUIPSJ[FE
  43. ݟग़͠ https://goo.gl/efpZeL

  44. &$ *". #BDLEPPS $SZQUP $VSSFODIZ 1FOUFTU 1FSTJTUFODF 3FDPO #FIBWJPSJBM 5SB⒏D

    7PMVNF 4UFBMUI 5SPKBO 6OBVUIPSJ[FE "DDFTT $POTPMF-PHJO *OTUBODF $SFEFOUJBM &YpMUSBUJPO - Ϧιʔε - ໨త IUUQTEPDTBXTBNB[PODPNHVBSEEVUZMBUFTUVHHVBSEEVUZ@pOEJOHUZQFTIUNMVOBVUIPSJ[FE ݕ஌Ͱ͖ΔڴҖ
  45. શ͕ͯFʹͳΔGʹͳΒͳ͍ - ࠓ·ͰͷڴҖͱݕ஌ is not ϨΨγʔ - ͳͷͰɺͱΓ͋͑ͣΦϯʹ͓ͯ͜͠͏ʂ

  46. Q & A - part 1

  47. GuardDuty࢖ͬͯΔਓ!

  48. GuardDuty in Folio

  49. GuardDuty in Folio - ͍͘Β͔͔ͬͯΔʁ - ޡݕ஌͋Δʁ - Ϣʔεέʔεʁ

  50. GuardDuty in Folio - ͍͘Β͔͔ͬͯΔʁ - ޡݕ஌͋Δʁ - Ͳ͏͍͏෩ʹ࢖ͬͯΔʁ

  51. ͍͘Β͔͔ͬͯΔʁ - 11ΞΧ΢ϯτશ෦ͰonɻϝΠϯ͸ap-northeast1

  52. Ձ֨ EBZ

  53. GuardDuty in Folio - ͍͘Β͔͔ͬͯΔʁ - ޡݕ஌͋Δʁ - Ͳ͏͍͏෩ʹ࢖ͬͯΔʁ

  54. ࠓͷॴ ʢগʣ ͳ͍

  55. ࠓͷॴ ʢগʣ ͳ͍

  56. ࠓ·Ͱͷݕ஌ - Recon:EC2/PortProbeUnprotectedPort - UnauthorizedAccess:IAMUser/UnusualASNCaller - Behavior:EC2/NetworkPortUnusual - Pentest:IAMUser/KaliLinux

  57. ࠓ·Ͱͷݕ஌ - Recon:EC2/PortProbeUnprotectedPort - UnauthorizedAccess:IAMUser/UnusualASNCaller - Behavior:EC2/NetworkPortUnusual - Pentest:IAMUser/KaliLinux

  58. ࠓ·Ͱͷݕ஌ - Recon:EC2/PortProbeUnprotectedPort - UnauthorizedAccess:IAMUser/UnusualASNCaller - Behavior:EC2/NetworkPortUnusual - Pentest:IAMUser/KaliLinux

  59. ࠓ·Ͱͷݕ஌ - Recon:EC2/PortProbeUnprotectedPort - UnauthorizedAccess:IAMUser/UnusualASNCaller - Behavior:EC2/NetworkPortUnusual - Pentest:IAMUser/KaliLinux

  60. ࠓ·Ͱͷݕ஌ - Recon:EC2/PortProbeUnprotectedPort - UnauthorizedAccess:IAMUser/UnusualASNCaller - Behavior:EC2/NetworkPortUnusual - Pentest:IAMUser/KaliLinux

  61. ൑அϙΠϯτ࡟ݮ - ࣗಈArchive - ݕࡧϑΟϧλʔʹʮAuto-archiveΦϓγϣϯʯΛ͚ͭΕ͹͓̺

  62. GuardDuty in Folio - ͍͘Β͔͔ͬͯΔʁ - ޡݕ஌͋Δʁ - Ϣʔεέʔεʁ

  63. Ϣʔεέʔε - ॏཁ౓ʹԠͨ͡Ξϥʔτ - νέοτ؅ཧ։࢝ - ࣗಈForensic४උ

  64. جຊతʹ͸LambdaͰ֦ு { "version": "0", "id": "c8c4daa7-a20c-2f03-0070-b7393dd542ad", "detail-type": "GuardDuty Finding", "source":

    "aws.guardduty", "account": "123456789012", "time": "1970-01-01T00:00:00Z", "region": "us-east-1", "resources": [], "detail": { "schemaVersion": "2.0", "accountId": "123456789012", "region": "ap-northeast-1", "type": "UnauthorizedAccess:EC2/RDPBruteForce", "resource": { "resourceType": "Instance", "instanceDetails": { "instanceId": "i-99999999", "instanceType": "m3.xlarge", "launchTime": "2016-08-02T02:05:06Z", "platform": null, "productCodes": [ { "productCodeId": "GeneratedFindingProductCodeId", "productCodeType": "GeneratedFindingProductCodeType } ], "iamInstanceProfile": { "arn": "GeneratedFindingInstanceProfileArn", "id": "GeneratedFindingInstanceProfileId" }, "networkInterfaces": [ { "ipv6Addresses": [], "networkInterfaceId": "eni-bfcffe88", "privateDnsName": "GeneratedFindingPrivateDnsName",
  65. Slack௨஌

  66. Slack௨஌ func main() { lambda.Start(HandleRequest) } func HandleRequest(request CloudWatchEventForGuardDuty) {

    if err := postOnSlack(request); err != nil { log.Fatal().Err(err).Msg("failed.") } } func mapSeverityToLevel(request CWEvent) (*Severity, error) { severity := request.Detail.Severity s := &Severity{} s.AccountAlias = request.Detail.AccountID if 0 <= severity && severity < 4 { s.Level = "Low" s.Color = "#707070" return s, nil } else if 4 <= severity && severity < 7 { s.Level = "Medium" s.Color = "warning" return s, nil } else if severity < 10 { s.Level = "High" s.Color = "danger" s.Announce = true return s, nil } return nil, errors.New("Severity was not in right range: 0~10.0") }
  67. Slack௨஌ func postOnSlack(request CWevent) error { severity, err := initializeSeverity(request.Detail.Severity)

    if err != nil { return err } pretext := "'" + request.Detail.Type + "' type found." if severity.Announce { pretext = "<!here> " + pretext } attachment := slack.Attachment{ Color: severity.Color, Pretext: pretext, Title: request.Detail.Title, Fields: []slack.AttachmentField{ { Title: "Severity", Value: severity.Level, Short: true, }, { Title: "Account", Value: request.Detail.AccountID, Short: true, }, { Title: "Description", Value: request.Detail.Description, Short: false, }, }, } payload := slack.PostMessageParameters{ Attachments: []slack.Attachment{attachment}, } body, err := json.Marshal(payload) if err != nil { return errors.New("failed to encode payload") } if _, err := http.Post(slackURL, contentType, bytes.NewReader(body) != nil { return errors.New(fmt.Sprintf("posting Slack failed: %v", err)) } return nil }
  68. JIRAνέοτ࡞੒

  69. ݟग़͠ func postOnJira(request CloudWatchEventForGuardDuty, c chan error) { defer close(c)

    body := &JiraIssueCreateRequest{ Fields: struct { Project struct { ID string `json:"id"` } `json:"project"` Summary string `json:"summary"` Description string `json:"description"` IssueType struct { ID string `json:"id"` } `json:"issuetype"` }{ Project: struct { ID string `json:"id"` }{ID: jiraProjectId}, Summary: request.Detail.Title, Description: request.Detail.Description + " in account: " + request.Detail.AccountI IssueType: struct { ID string `json:"id"` }{ID: jiraIssueTypeId}, }, } payload, err := json.Marshal(body) if err != nil { c <- err return } req, _ := http.NewRequest(http.MethodPost, jiraURL, bytes.NewBuffer(payload)) req.Header.Add("Authorization", jiraBasicAuthentication) req.Header.Add("Content-Type", contentType) log.Info().Str("status", "sending a posting a request Jira").Msg("ok") // TODO Handle non 200 case if _, err := http.DefaultClient.Do(req); err != nil { c <- err return } log.Info().Str("status", "finishing a request Jira").Msg("ok") } func HandleRequest(request CloudWatchEventForGuardDuty) (err error) { errJIRAChan, errPDChan := make(chan error), make(chan error) go postOnPagerDuty(request, errPDChan) go postOnJira(request, errJIRAChan) ok1, ok2:= true, true for ok1 || ok2 { select { case err, ok1 = <-errJIRAChan: if err != nil && ok1 { log.Info().Err(err).Str("app", "jira").Msg(err.Error()) } case err, ok2 = <-errPDChan: if err != nil && ok2 { log.Info().Err(err).Str("app", "PagerDuty").Msg(err.Error()) } } } return err } func getAccountAlias(accountId string) string { if v, ok := accountMap[accountId]; ok { return v } return accountId }
  70. PagerDuty࿈ܞ

  71. ݟग़͠ func HandleRequest(request CloudWatchEventForGuardDuty) (err error) { errJIRAChan, errPDChan :=

    make(chan error), make(chan error) go postOnPagerDuty(request, errPDChan) go postOnJira(request, errJIRAChan) ok1, ok2:= true, true for ok1 || ok2 { select { case err, ok1 = <-errJIRAChan: if err != nil && ok1 { log.Info().Err(err).Str("app", "jira").Msg(err.Error()) } case err, ok2 = <-errPDChan: if err != nil && ok2 { log.Info().Err(err).Str("app", "PagerDuty").Msg(err.Error()) } } } return err } func getAccountAlias(accountId string) string { if v, ok := accountMap[accountId]; ok { return v } return accountId } func postOnPagerDuty(request CloudWatchEventForGuardDuty, c chan error) { defer close(c) client := pagerduty.NewClient(pagerDutyToken) priorities, err := client.ListPriorities() if err != nil { c <- err return } var priority string severity := request.Detail.Severity if 0 <= severity && severity < 4 { priority = priorities.Priorities[2].ID } else if 4 <= severity && severity < 7 { priority = priorities.Priorities[1].ID } else if severity < 10 { priority = priorities.Priorities[0].ID } o := pagerduty.CreateIncidentOptions{ Title: request.Detail.Title, Service: pagerduty.APIReference{ ID: pagerDutyServiceId, Type: "service_reference", }, Priority: pagerduty.APIReference{ ID: priority, Type: "priority_reference", }, Body: pagerduty.APIDetails{ Type: "incident_body", Details: request.Detail.Description + " in account: " + getAccountAlias(request.Detail.AccountID), }, } _, err = client.CreateIncident(pagerDutyEmail, &pagerduty.CreateIncident{o}) if err != nil { c <- err return } }
  72. ࣗಈִ཭(Forensic४උʣ TOBQTIPU &#4 ᶃ ᶄ ᶅ ᶆ - "Digital Forensic

    Analysis of Amazon Linux EC2 Instances” by SANSͷҰ෦ΛίʔυԽ AWS FIntech ϦϑΝϨϯεΨΠ υ IUUQTXXXTBOTPSHSFBEJOHSPPNXIJUFQBQFST DMPVEEJHJUBMGPSFOTJDBOBMZTJTBNB[POMJOVYFD JOTUBODFT
  73. Snapshotੜ੒ TOBQTIPU ᶃ

  74. ݟग़͠ // Take SnapShot of suspected EC2 instance for taking

    evidence func (e *EC2Forensic) CreateEvidenceSnapshot() (snapshotId string, err error) { describeEc2AttributeInput := &ec2.DescribeInstanceAttributeInput{ Attribute: aws.String("blockDeviceMapping"), InstanceId: aws.String(e.InstanceId), } createSnapshotInput := &ec2.CreateSnapshotInput{ Description: aws.String("Snapshot taken for forensic purpose"), TagSpecifications: []*ec2.TagSpecification{ { ResourceType: aws.String("snapshot"), Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("forensic-snapshot")}}, }, }, } output, err := e.svc.DescribeInstanceAttribute(describeEc2AttributeInput) if err != nil { return "", err } createSnapshotInput.VolumeId = output.BlockDeviceMappings[0].Ebs.VolumeId snapShot, err := e.svc.CreateSnapshot(createSnapshotInput) if err != nil { return "", err } // Check State var snapShotState string for snapShotState != "completed" { output, err := e.svc.DescribeSnapshots(&ec2.DescribeSnapshotsInput{SnapshotIds: []*string{snapShot.SnapshotId}}) if err != nil { return "", nil } snapShotState = *output.Snapshots[0].State } return *snapShot.SnapshotId, nil }
  75. EBSੜ੒ TOBQTIPU &#4 ᶄ

  76. ݟग़͠ func (e *EC2Forensic) CreateEvidenceEBS(snapshotId string) (volumeId string, err error)

    { input := &ec2.CreateVolumeInput{ //ToDO Dynamically retrieve AZ from subnet-id AvailabilityZone: aws.String("ap-northeast-1a"), SnapshotId: aws.String(snapshotId), TagSpecifications: []*ec2.TagSpecification{ { ResourceType: aws.String("volume"), Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("forensic-ebs-volume")}}, }, }, } output, err := e.svc.CreateVolume(input) if err != nil { return "", err } // Check State var volumeState string if volumeState != "ok" { output, err := e.svc.DescribeVolumeStatus(&ec2.DescribeVolumeStatusInput{ VolumeIds: []*string{output.VolumeId}, }) if err != nil { return "", err } volumeState = *output.VolumeStatuses[0].VolumeStatus.Status } return *output.VolumeId, nil }
  77. Forensic༻EC2ੜ੒ TOBQTIPU &#4 ᶅ

  78. ݟग़͠ func (e *EC2Forensic) StartForensicWorkstation() (workstationId string, err error) {

    input := &ec2.RunInstancesInput{ TagSpecifications: []*ec2.TagSpecification{ { ResourceType: aws.String("instance"), Tags: []*ec2.Tag{ {Key: aws.String("Name"), Value: aws.String("forensic-workstation")}, {Key: aws.String("Target"), Value: aws.String(e.InstanceId)}, }, }, }, MaxCount: aws.Int64(1), MinCount: aws.Int64(1), SecurityGroupIds: []*string{aws.String(forensicSgId)}, SubnetId: aws.String(forensicSubnetId), // Recommended in https://www.sans.org/reading-room/whitepapers/cloud/digital-forensic-analysis-amazon-linux-ec2-instances-38235? InstanceType: aws.String("t2.large"), // Latest(2018/07/15) ami id of Ubuntu Server 16.04 LTS (HVM), SSD Volume Type // Recommended in https://www.sans.org/reading-room/whitepapers/cloud/digital-forensic-analysis-amazon-linux-ec2-instances-38235? ImageId: aws.String("ami-940cdceb"), } output, err := e.svc.RunInstances(input) if err != nil { return "", err } var instanceState string for instanceState != "running" { output, err := e.svc.DescribeInstanceStatus(&ec2.DescribeInstanceStatusInput{ InstanceIds: []*string{output.Instances[0].InstanceId}, IncludeAllInstances: aws.Bool(true), }) if err != nil { return "", err } instanceState = *output.InstanceStatuses[0].InstanceState.Name } return *output.Instances[0].InstanceId, nil }
  79. EBSΞλον TOBQTIPU &#4 ᶆ

  80. ݟग़͠ func (e *EC2Forensic) AttachEvidenceToWorkstation(workstationId, evidenceVolumeId string) (err error) {

    _, err = e.svc.AttachVolume(&ec2.AttachVolumeInput{ InstanceId: aws.String(workstationId), VolumeId: aws.String(evidenceVolumeId), Device: aws.String("/dev/sdf"), }) return } func notify(isFailed bool, isCompleted bool, message string) { var color string var status string if isFailed { color = "warning" status = “failed" } else if isCompleted { color = "good" status = "completed" } else { color = "#707070" status = "completed" } log.Info().Str("duration", returnDuration()).Str("status", message).Msg(status) payload := slack.PostMessageParameters{ Attachments: []slack.Attachment{{ Color: color, Pretext: "Forensic Preparation Status", Title: message, }}, } body, err := json.Marshal(payload) if err != nil { log.Info().Str("status", "failed").Msg("slack notification failed: failed to encode payload") } if _, err := http.Post(slackURL, "application/json", bytes.NewReader(body)); err != nil { log.Info().Str("status", "failed").Msg("slack notification failed: http post failed") }
  81. ͓·͚ &#4

  82. ݁࿦: GuadDuty͸͍͍ͧ!

  83. Future GuardDuty in Folio

  84. ಛఆͷૹ৴ݩIP or ѼઌPort΁ͷDeny௨৴ٸ૿ͷݕ஌ - ߈ܸͷ༧ஹͱͯ͠Α͋͘Δ - ࢓૊Έ্Ͱ͖ͳ͍ - ಉ͡ݕ஌͸ॳճҎ߱ɺ6࣌ؒຖʹCloudWatchʹग़ྗ͞ΕΔ -

    Ξϥʔτͱͯ͠͸্͍͛ͨ
  85. ର৅Ϧιʔεͷ֦ॆ - ʮσʔλ࿙͍͑ʯϦεΫʹඥͮ͘ڴҖ - ීஈͳ͍IP/EC2͔ΒͷRDB΁ͷΞΫηεɺΫΤϦ࣮ߦ - ීஈͳ͍IP/EC2͔ΒͷS3΁ͷҎԼಉจ - ීஈͷNഒͳOutbound VPC

    Flow logͷൃੜ - Macieʹظ଴ʁ
  86. ΞϥʔτʹΑΔεΩʔϚͷ౷Ұ - ݕ஌಺༰ʹΑͬͯJSONεΩʔϚ͕ҟͳΔ - ͦͷࠩ෼ٵऩ - ֤ݕ஌͝ͱͷJSONྫ΄͍͠…

  87. { "version": "0", "id": "c8c4daa7-a20c-2f03-0070-b7393dd542ad", "detail-type": "GuardDuty Finding", "source": "aws.guardduty",

    "account": "123456789012", "time": "1970-01-01T00:00:00Z", "region": "us-east-1", "resources": [], "detail": { "schemaVersion": "2.0", "accountId": "123456789012", "region": "ap-northeast-1", "type": "UnauthorizedAccess:EC2/RDPBruteForce", "resource": { "resourceType": "Instance", "instanceDetails": { "instanceId": "i-99999999", "instanceType": "m3.xlarge", "launchTime": "2016-08-02T02:05:06Z", "platform": null, "productCodes": [ { "productCodeId": "GeneratedFindingProductCodeId", "productCodeType": "GeneratedFindingProductCodeType" } ], { "version": "0", "id": "c8c4daa7-a20c-2f03-0070-b7393dd542ad", "detail-type": "GuardDuty Finding", "source": "aws.guardduty", "account": "123456789012", "time": "1970-01-01T00:00:00Z", "region": "us-east-1", "resources": [], "detail": { "schemaVersion": "2.0", "accountId": "123456789012", "region": "ap-northeast-1", "partition": "aws", "id": "08b1830ad3896e10860152a387a36b00", "arn": "arn:aws:guardduty:ap-northeast-1:123456789012:detector/e6b15a3c39d02cb9287 "type": "UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration", "resource": { "resourceType": "AccessKey", "accessKeyDetails": { "accessKeyId": "GeneratedFindingAccessKey "principalId": "GeneratedFindingPrincipal "userType": "IAMUser", "userName": "GeneratedFindingUserName" } }, "ipAddressV4": "198.51.100.1" } ], "sample": true }, "eventFirstSeen": "2018-04-27T07:51:12.402Z", "eventLastSeen": "2018-05-11T14:07:26.951Z", "archived": true, "count": 37 }, "severity": 8, શવҧ͏ ʢݕ஌ର৅ͷϦιʔεʣ &$PS*".
  88. "service": { "serviceName": "guardduty", "detectorId": "e6b15a3c39d02cb928758a13a65eb04e", "action": { "actionType": "AWS_API_CALL",

    "awsApiCallAction": { "api": "GeneratedFindingAPIName", "serviceName": "GeneratedFindingAPIServiceName", "callerType": "Remote IP", "remoteIpDetails": { "ipAddressV4": "198.51.100.0", "organization": { "asn": "-1", "asnOrg": "GeneratedFindingASNOrg", "isp": "GeneratedFindingISP", "org": "GeneratedFindingORG" }, "country": { "countryName": "GeneratedFindingCountryName" }, "city": { "cityName": "GeneratedFindingCityName" }, "geoLocation": { "service": { "serviceName": "guardduty", "detectorId": "e6b15a3c39d02cb928758a13a65eb04e", "action": { "actionType": "NETWORK_CONNECTION", "networkConnectionAction": { "connectionDirection": "INBOUND", "remoteIpDetails": { "ipAddressV4": "198.51.100.0", "organization": { "asn": "-1", "asnOrg": "GeneratedFindingASNO "isp": "GeneratedFindingISP", "org": "GeneratedFindingORG" }, "country": { "countryName": "GeneratedFindin }, "city": { "cityName": "GeneratedFindingCi }, "geoLocation": { "lat": 0, "lon": 0 } }, શવҧ͏ 5ISFBEͷ"DUJPOʣ &$PS*".
  89. Confidence

  90. ϚελʔΞΧ΢ϯτ΁ͷ৘ใू໿ - Bill৘ใ΋ϚελʔΞΧ΢ϯτʹू໿͍ͨ͠ - Region·͍ͨͰ΋ू໿͍ͨ͠ - ֤ΠϕϯτͷCloudTrail΁ͷϦϯΫ΋΄͍͠

  91. ଞͷAWSηΩϡϦςΟϦιʔεͱͷ࿈ܞ - ࣗಈతʹCloudTrailͱඥ෇͚Δ - Config΁ͷઃఆ௥Ճਪ঑Λ͢Δ - ͳͲ

  92. GuardDuty࢖ͬͯΔਓ!

  93. Q & A - part 2

  94. ಊʑͱͨ͠ݟग़͠

  95. Thank you! @ken5scal