$30 off During Our Annual Pro Sale. View Details »

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

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

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

Kengo Suzuki

July 29, 2018
Tweet

More Decks by Kengo Suzuki

Other Decks in Technology

Transcript

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

    View Slide

  2. AWS࢖ͬͯΔਓ!

    View Slide

  3. GuardDuty࢖ͬͯΔਓ!

    View Slide

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

    View Slide

  5. ׬

    View Slide

  6. ׬

    View Slide

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

    View Slide

  8. GuardDuty in NutShell

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  12. ڴҖͷݕ஌

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  19. View Slide

  20. View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  24. ֹۚྫ:
    IUUQTBXTBNB[PODPNKQHVBSEEVUZQSJDJOH

    View Slide

  25. Why GuardDuty?

    View Slide

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

    View Slide

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

    View Slide

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

    'JSFXBMM 'JSFXBMM
    *%4
    1SPYZ
    'JMF
    *OUFHSJUZ
    'JMF
    *OUFHSJUZ
    'JMF
    *OUFHSJUZ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  36. ଟ૚๷ޚ(ݕ஌)
    IUUQTXXXMPDLIFFENBSUJODPNFOVTDBQBCJMJUJFTDZCFSDZCFSLJMMDIBJOIUNM

    View Slide

  37. ଟ૚๷ޚ(ݕ஌)
    IUUQTXXXMPDLIFFENBSUJODPNFOVTDBQBCJMJUJFTDZCFSDZCFSLJMMDIBJOIUNM

    View Slide

  38. ଟ૚๷ޚ(ݕ஌)
    IUUQTXXXMPDLIFFENBSUJODPNFOVTDBQBCJMJUJFTDZCFSDZCFSLJMMDIBJOIUNM

    View Slide

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

    View Slide

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

    View Slide

  41. ڴҖݕ஌
    in
    GuardDuty

    View Slide

  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

    View Slide

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

    View Slide

  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
    ݕ஌Ͱ͖ΔڴҖ

    View Slide

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

    View Slide

  46. Q & A
    - part 1

    View Slide

  47. GuardDuty࢖ͬͯΔਓ!

    View Slide

  48. GuardDuty in Folio

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  52. Ձ֨
    EBZ

    View Slide

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

    View Slide

  54. ࠓͷॴ
    ʢগʣ
    ͳ͍

    View Slide

  55. ࠓͷॴ
    ʢগʣ
    ͳ͍

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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",

    View Slide

  65. Slack௨஌

    View Slide

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

    View Slide

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

    View Slide

  68. JIRAνέοτ࡞੒

    View Slide

  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
    }

    View Slide

  70. PagerDuty࿈ܞ

    View Slide

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

    View Slide

  72. ࣗಈִ཭(Forensic४උʣ
    TOBQTIPU



    ᶅ ᶆ
    - "Digital Forensic Analysis of
    Amazon Linux EC2 Instances”
    by SANSͷҰ෦ΛίʔυԽ
    AWS FIntech ϦϑΝϨϯεΨΠ
    υ
    IUUQTXXXTBOTPSHSFBEJOHSPPNXIJUFQBQFST
    DMPVEEJHJUBMGPSFOTJDBOBMZTJTBNB[POMJOVYFD
    JOTUBODFT

    View Slide

  73. Snapshotੜ੒
    TOBQTIPU

    View Slide

  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
    }

    View Slide

  75. EBSੜ੒
    TOBQTIPU


    View Slide

  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
    }

    View Slide

  77. Forensic༻EC2ੜ੒
    TOBQTIPU


    View Slide

  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
    }

    View Slide

  79. EBSΞλον
    TOBQTIPU


    View Slide

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

    View Slide

  81. ͓·͚

    View Slide

  82. ݁࿦: GuadDuty͸͍͍ͧ!

    View Slide

  83. Future GuardDuty in Folio

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  89. Confidence

    View Slide

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

    View Slide

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

    View Slide

  92. GuardDuty࢖ͬͯΔਓ!

    View Slide

  93. Q & A
    - part 2

    View Slide

  94. ಊʑͱͨ͠ݟग़͠

    View Slide

  95. Thank you!
    @ken5scal

    View Slide