Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

AWS࢖ͬͯΔਓ!

Slide 3

Slide 3 text

GuardDuty࢖ͬͯΔਓ!

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

׬

Slide 6

Slide 6 text

׬

Slide 7

Slide 7 text

1. GuardDuty in nutshell 2. Why GuardDuty? 3. GuardDuty in Folio 4. GuardDuty in Future ໨࣍

Slide 8

Slide 8 text

GuardDuty in NutShell

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

GuardDuty in nutshell - 2017/11ʹϦϦʔε - ڴҖͷݕ஌ - ػցֶशΛ࢖ͬͨݕ஌ - IAM΍EC2पΓʹಛԽ - ΫΠοΫσϓϩΠ

Slide 12

Slide 12 text

ڴҖͷݕ஌

Slide 13

Slide 13 text

GuardDuty in nutshell - 2017/11ʹϦϦʔε - ڴҖͷݕ஌ - ػցֶशΛ࢖ͬͨݕ஌ - IAM΍EC2पΓʹಛԽ - ΫΠοΫσϓϩΠ

Slide 14

Slide 14 text

ػցֶश - σʔλ in AWS - AWS಺ͷϦιʔε - VPC Flow Logs - DNS Logs - CloudTrail Events Logs

Slide 15

Slide 15 text

ػցֶश - σʔλ from ΠϯςϦδΣϯε - ΦʔϓϯͳΠϯςϦδΣϯεσʔλ - Taxii, STIX, OTX - ΠϯςϦδΣϯεσʔλ from αʔϏε - Alien Vault, Fire Eye, Proof Point

Slide 16

Slide 16 text

GuardDuty in nutshell - 2017/11ʹϦϦʔε - ڴҖͷݕ஌ - ػցֶशΛ࢖ͬͨݕ஌ - IAM΍EC2पΓʹಛԽ - ΫΠοΫσϓϩΠ

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

ΫΠοΫσϓϩΠ - ϦʔυλΠϜؚΊͯ30ඵʢ3εςοϓʣ - ःஅͳͲ͸ͳ͍ͷͰγεςϜతͳӨڹͳ͠ - ۚમతӨڹ͸ݕূՄ - 30೔ؒແྉ - ͦͷޙ: - CloudTrail: 1,000,000events/month - VPC Flow Log, DNC Log: 1GB/month

Slide 24

Slide 24 text

ֹۚྫ: IUUQTBXTBNB[PODPNKQHVBSEEVUZQSJDJOH

Slide 25

Slide 25 text

Why GuardDuty?

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

Firewall - Πϯλʔωοτͱͷڥք๷ޚ - L3~4ϨΠϠʔͷstatefulͳηογϣϯपΓͷݕ஌ - ྫ: ωοτϫʔΫ੍ޚ - ྫ: ϙʔτ੍ޚ - ྫ: syn flood߈੍ܸޚ - Untrust΍TrustͳκʔϯΛఆٛ - Juniper Network, Cisco, Yamaha… - ࠓͷ࣌୅ʮͰʁʯͱͳΓ͕ͪ

Slide 30

Slide 30 text

IDS/IPS - ௨৴಺༰ͷݕ஌ɾγάωνϟϕʔε - ϛυϧ΢ΣΞܥγάωνϟଟΊ - ྫ: σΟϨΫτϦτϥόʔαϧ - ྫ: CVEεϖγϑΟοΫ - SnortͳͲ - νϡʔχϯά is େม

Slide 31

Slide 31 text

WAF - Πϯλʔωοτͱͷڥք๷ޚͦͷ2 - L7ͷHTTP(S)ʹಛԽͨ͠ݕ஌ɾγάωνϟϕʔε - LBʢ࠷ۙ͸CDNʣͱ૊Έ߹ΘͤͰ࢖ΘΕ͕ͪ - 2013೥Ҡߦʹ૿͑࢝Ίͨҹ৅ in Japan - BigIP ASM, Imperva, AWS WAF, Fastly, Akamai Kona - νϡʔχϯά is େม

Slide 32

Slide 32 text

Proxy - Πϯλʔωοτʹग़ΔHTTP(S), SSHͷFQDNݕ஌ - ϗϫΠτϦετ΍ϒϥοΫϦετͷ؅ཧ - SquidͳͲ - ϗϫΠτϦετͳͲͷ؅ཧ is େม͔΋

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

SIEM - Security Information and Event Managementͷུ - ઌड़ͷ੡඼܈ͷϩάΛू໿͠ɺΠϕϯτΛ؅ཧ͢Δ - ྫ: ୹࣌ؒͰFirewallʹର͠ɺಉҰૹ৴ݩ͔ΒN݅ͷDeny௨৴͕͋ͬͨ ΒΞϥʔτΛ্͛Δ - ྫ: WAFͰSQL߈ܸγάωνϟʹͻ͔͔ͬΔϦΫΤετʹ200Λฦͨ͠ ΒΞϥʔτΛ্͛Δ - ArchSight, Splunk, Sumo-logic, ELK, Graylog - Eventͷઃఆ is େม

Slide 35

Slide 35 text

ڴҖͷݕ஌ ͦΕͧΕͷιϦϡʔγϣϯ͕ͲͷΑ͏ͳηΩϡϦςΟϦεΫ

Slide 36

Slide 36 text

ଟ૚๷ޚ(ݕ஌) IUUQTXXXMPDLIFFENBSUJODPNFOVTDBQBCJMJUJFTDZCFSDZCFSLJMMDIBJOIUNM

Slide 37

Slide 37 text

ଟ૚๷ޚ(ݕ஌) IUUQTXXXMPDLIFFENBSUJODPNFOVTDBQBCJMJUJFTDZCFSDZCFSLJMMDIBJOIUNM

Slide 38

Slide 38 text

ଟ૚๷ޚ(ݕ஌) IUUQTXXXMPDLIFFENBSUJODPNFOVTDBQBCJMJUJFTDZCFSDZCFSLJMMDIBJOIUNM

Slide 39

Slide 39 text

Applicable to AWSʁ        _,,;' '" '' ゛''" ゛' ';;,,       (rヽ,;''"""''゛゛゛'';, ノr)       ,;'゛ i _  、_ iヽ゛';,    お前AWSでも同じことできんの?       ,;'" ''| ヽ・〉 〈・ノ |゙゛ `';,       ,;'' "|   ▼   |゙゛ `';,       ,;''  ヽ_人_ /  ,;'_      /シ、  ヽ⌒⌒ /   リ \     |   "r,, `"'''゙´  ,,ミ゛   |     |      リ、    ,リ    |     |   i   ゛r、ノ,,r" i   _|     |   `ー――----┴ ⌒´ )     (ヽ  ______ ,, _´)      (_⌒ ______ ,, ィ       丁           |        |           |

Slide 40

Slide 40 text

ҟͳΔύϥμΠϜ(AWSʹݶΒͣʣ - ಛੑ্ɺैདྷͷߏ੒Ͱ͸ͳ͔ͬͨ੬ऑੑ͕͋Δ - Ϋϥ΢υαʔϏεͱͯ͠ͷΞΧ΢ϯτ - Ϧιʔεͱݖݶ - ෺ཧతͳ੍໿͕؇͍Ϧιʔε - ಈతʹεέʔϧΞ΢τ͢ΔϦιʔε - Pay as you GoͳϦιʔε

Slide 41

Slide 41 text

ڴҖݕ஌ in GuardDuty

Slide 42

Slide 42 text

ݕ஌Ͱ͖ΔڴҖ &$ *". #BDLEPPS $SZQUP $VSSFODIZ 1FOUFTU 1FSTJTUFODF 3FDPO #FIBWJPSJBM 5SB⒏D 7PMVNF 4UFBMUI 5SPKBO 6OBVUIPSJ[FE "DDFTT $POTPMF-PHJO *OTUBODF $SFEFOUJBM &YpMUSBUJPO - Ϧιʔε - ໨త - ڴҖͷछྨ - ୔ࢁ IUUQTEPDTBXTBNB[PODPNHVBSEEVUZMBUFTUVHHVBSEEVUZ@pOEJOHUZQFTIUNMVOBVUIPSJ[FE

Slide 43

Slide 43 text

ݟग़͠ https://goo.gl/efpZeL

Slide 44

Slide 44 text

&$ *". #BDLEPPS $SZQUP $VSSFODIZ 1FOUFTU 1FSTJTUFODF 3FDPO #FIBWJPSJBM 5SB⒏D 7PMVNF 4UFBMUI 5SPKBO 6OBVUIPSJ[FE "DDFTT $POTPMF-PHJO *OTUBODF $SFEFOUJBM &YpMUSBUJPO - Ϧιʔε - ໨త IUUQTEPDTBXTBNB[PODPNHVBSEEVUZMBUFTUVHHVBSEEVUZ@pOEJOHUZQFTIUNMVOBVUIPSJ[FE ݕ஌Ͱ͖ΔڴҖ

Slide 45

Slide 45 text

શ͕ͯFʹͳΔGʹͳΒͳ͍ - ࠓ·ͰͷڴҖͱݕ஌ is not ϨΨγʔ - ͳͷͰɺͱΓ͋͑ͣΦϯʹ͓ͯ͜͠͏ʂ

Slide 46

Slide 46 text

Q & A - part 1

Slide 47

Slide 47 text

GuardDuty࢖ͬͯΔਓ!

Slide 48

Slide 48 text

GuardDuty in Folio

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

Ձ֨ EBZ

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

ࠓͷॴ ʢগʣ ͳ͍

Slide 55

Slide 55 text

ࠓͷॴ ʢগʣ ͳ͍

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

جຊతʹ͸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",

Slide 65

Slide 65 text

Slack௨஌

Slide 66

Slide 66 text

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") }

Slide 67

Slide 67 text

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 = " " + 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 }

Slide 68

Slide 68 text

JIRAνέοτ࡞੒

Slide 69

Slide 69 text

ݟग़͠ 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 }

Slide 70

Slide 70 text

PagerDuty࿈ܞ

Slide 71

Slide 71 text

ݟग़͠ 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 } }

Slide 72

Slide 72 text

ࣗಈִ཭(Forensic४උʣ TOBQTIPU ᶃ ᶄ ᶅ ᶆ - "Digital Forensic Analysis of Amazon Linux EC2 Instances” by SANSͷҰ෦ΛίʔυԽ AWS FIntech ϦϑΝϨϯεΨΠ υ IUUQTXXXTBOTPSHSFBEJOHSPPNXIJUFQBQFST DMPVEEJHJUBMGPSFOTJDBOBMZTJTBNB[POMJOVYFD JOTUBODFT

Slide 73

Slide 73 text

Snapshotੜ੒ TOBQTIPU ᶃ

Slide 74

Slide 74 text

ݟग़͠ // 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 }

Slide 75

Slide 75 text

EBSੜ੒ TOBQTIPU ᶄ

Slide 76

Slide 76 text

ݟग़͠ 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 }

Slide 77

Slide 77 text

Forensic༻EC2ੜ੒ TOBQTIPU ᶅ

Slide 78

Slide 78 text

ݟग़͠ 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 }

Slide 79

Slide 79 text

EBSΞλον TOBQTIPU ᶆ

Slide 80

Slide 80 text

ݟग़͠ 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") }

Slide 81

Slide 81 text

͓·͚

Slide 82

Slide 82 text

݁࿦: GuadDuty͸͍͍ͧ!

Slide 83

Slide 83 text

Future GuardDuty in Folio

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

ର৅Ϧιʔεͷ֦ॆ - ʮσʔλ࿙͍͑ʯϦεΫʹඥͮ͘ڴҖ - ීஈͳ͍IP/EC2͔ΒͷRDB΁ͷΞΫηεɺΫΤϦ࣮ߦ - ීஈͳ͍IP/EC2͔ΒͷS3΁ͷҎԼಉจ - ීஈͷNഒͳOutbound VPC Flow logͷൃੜ - Macieʹظ଴ʁ

Slide 86

Slide 86 text

ΞϥʔτʹΑΔεΩʔϚͷ౷Ұ - ݕ஌಺༰ʹΑͬͯJSONεΩʔϚ͕ҟͳΔ - ͦͷࠩ෼ٵऩ - ֤ݕ஌͝ͱͷJSONྫ΄͍͠…

Slide 87

Slide 87 text

{ "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*".

Slide 88

Slide 88 text

"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*".

Slide 89

Slide 89 text

Confidence

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

GuardDuty࢖ͬͯΔਓ!

Slide 93

Slide 93 text

Q & A - part 2

Slide 94

Slide 94 text

ಊʑͱͨ͠ݟग़͠

Slide 95

Slide 95 text

Thank you! @ken5scal