Amazon GuardDuty 입문부터 실전까지 바로 적용해봅시다

2020.08.10

안녕하세요!ㅎㅎ Classmethod 컨설팅부 소속 김태우입니다.

오늘은 Amazon GuardDuty 에 대해 기초적인 설명부터 실제 AWS 어카운트에 적용하는 방법까지 소개해드리려고 합니다.

그럼, 시작하겠습니다 :)

AWS 에서의 시큐리티 서비스

Amazon GuardDuty 에 대해 이야기하기 전에, 우선 AWS 에서 가이드하는 시큐리티 대응 전체과정에서 Amazon GuardDuty 가 어떤 역할을 담당하고 있는지를 알아둘 필요가 있습니다. 위 그림을 보시면, 시큐리티 대응 과정은 크게 5가지 단계로 분류됨을 알 수 있습니다.

1. Identify (식별)

시큐리티의 대상이 될 리소스를 식별하여 관리하는 단계입니다. 여기서 리소스라함은 EC2 나 RDS 등의 인스턴스를 하나의 예로 들 수 있습니다. AWS 에서는 SSM 과 Config 를 활용하여 리소스를 식별하고 관리할 수 있도록 돕고 있습니다.

2. Protect (방어)

식별되어 관리되는 리소스들 중에 방어해야할 리소스들을 선별하여 모든 레이어에서 보호합니다. 네트워크(VPC) 상에서 전송되는 데이터를 안전하게 보호하거나 접속경로를 차단하는 등의 설정, AWS Shield 를 통한 DDoS 공격 방어, WAF 를 통한 웹방화벽, KMS 를 통한 데이터 암호화 키 보호, IAM 을 통한 권한 관리 등 굉장히 많은 AWS 서비스들이 방어 과정에서 활용될 수 있습니다. 당연한 말이지만, 우선은 뚫리지 않는것이 가장 중요하겠죠ㅎㅎ

3. Detect (검출)

이렇게 열심히 방어를 했다고 하더라도 간혹 시큐리티 설정 누락 혹은 관리 상의 허점 등으로 인해 시큐리티 사고가 발생할 수 있습니다. 이런 경우에는 검출되었다는 사실 자체를 깨닫기가 상당히 어려운데요, 이걸 좀 더 쉽고 효과적으로 검출할 수 있도록 도와주기 위해 도와주는 서비스 들 중에 하나가 바로 Amazon GuardDuty 입니다.

4. Respond (반응)

Amazon GuardDuty 가 어떤 역할을 하는지를 알게되었지만, 이왕 설명하는김에 5가지 단계 전부다 한번씩 살펴보도록 하겠습니다. 시큐리티 사고가 발생했다는 사실을 알게되었다고 하더라도(검출 성공), 그 근본 원인을 조사하는 등의 "Respond(반응)" 과정이 진행되는 것이 일반적입니다. 루트원인을 규명하거나 자동화된 프로세스로 원래 상태로 돌려놓거나 혹은 둘다 동시에 진행하는 등의 과정을 생각할 수 있는데요, 흔히 온프렘 데이터센터 등에서는 시큐리티 사고가 발생하면 우선 랜선을 뽑아버리고 정밀조사를 진행하는 것에 비유될 수 있을 것 같습니다. 하지만, 클라우드에서는 그런 조치를 취할 수가 없으므로 다른 방식으로 접근해야할텐데요, 대표적인 예로 EC2 침해사실을 알게되었다면 즉시 Security Group 을 다 막아버리는 것으로 랜선을 차단하는 것과 동일한 효과를 누릴 수 있습니다. 그리고 스냅샷을 뜨거나 해서 백도어로 해당 인스턴스를 조사하는 등의 방법이 있을 수 있을 것 같습니다. 하지만 루트 원인을 규명하는 것은 역시 상당한 수고로움과 난이도를 요구하는 작업입니다. AWS 에서는 이러한 시큐리티 사고의 루트 원인을 좀 더 쉽게 규명할 수 있도록 2019년 re:Invent 에서 Amazon Detective 라는 서비스를 새롭게 출시하기도 했습니다. Amazon Detective 에 대해서는 다른 글에서 좀 더 자세히 소개해볼까 합니다.

5. Recover (복구)

시큐리티 사고의 조사과정이 끝났다면 원상태로 복구시킴과 동시에 추가적인 시큐리티 설정을 하게됩니다. 이를 위해 평소에 백업을 잘 해두어야하는데요, 백업을 위한 서비스들로는 각종 서비스들의 Snapshot 이나 Glacier 가 있습니다.

참고로, 여기서 시큐리티 사고 란, 흔히들 생각하는 해킹이나 Access Key 누출 등의 사고도 있겠지만, 개발자가 실수로 DB 를 날려먹는다던가 인스턴스를 끄거나 삭제해버리는 등의 행위도 포함됩니다. 즉, 상당히 넓은 범위를 지니고 있는 용어입니다. 기존의 시스템을 실수없이 잘 운영해나가자라는 의미도 지닐 수가 있다는 점을 고려해보면, 어느정도 서비스 규모가 있는 모든 기업들에게 있어서 시큐리티는 선택이 아닌 필수라고 볼 수 있습니다!

이렇게 중요한 시큐리티의 큰 부분을 굉장히 편리하게 만들어주는 Amazon GuardDuty 에 대해 좀 더 알아보고 싶으신 생각이 드셨나요?ㅎㅎ

Amazon GuardDuty 란?

Amazon GuardDuty 란, AWS 계정과 워크로드를 보호하기 위해 악의적 활동 또는 무단 동작을 지속적으로 모니터링하는 위협 탐지 서비스입니다.

네... 이렇게 봐서는 솔직히 무슨 서비스인지 잘 상상이 안되시죠? 공식 페이지에 있는 내용을 그대로 복붙한 내용입니다만, 걱정마세요!ㅎㅎ 스크린샷 첨부 등을 통해 좀 더 자세히 설명해보려고 합니다.

GuardDuty 를 활성화시키고 나서 볼 수 있는 메인 화면입니다. 뭔가 리스트로 잔뜩 표시되어 있는것들은, GuardDuty 가 CloudTrail , VPC Flow Logs, DNS 로그 를 직접 "분석" 해서 위협요소를 탐지한 결과를 나타냅니다. 말이 어렵나요? 그러니까 즉 위의 3가지 로그 데이터를 기반으로 머신러닝 알고리즘을 돌려서 위협이 될만한 요소들을 탐지하고 그것을 리스트로 표현해준다는 것입니다. 즉, 모든 시큐리티 사고에 대한 탐지를 해주기보다는 AWS 상에서 실행되는 모든 동작(API) 로그(CloudTrail)와, VPC 상에서 일어난 모든 트래픽의 메타데이터(VPC Flow Logs)와, DNS 로그를 기반으로 발견할 수 있는 위협요소만을 대상으로 합니다. (여기서 멈추지 마시고 조금만 더 읽어보세요!!! 왜냐면 최근에 업데이트 되어서 지금 적은 말은 거짓말이거든요!ㅎㅎ) 참고로, GuardDuty 에서 사용하는 위의 3가지 데이터소스를 직접 활성화 시키지 않아도 분석이 가능합니다! 즉, GuardDuty 를 사용하기 위해 Flow Logs 를 활성화시킨다거나, CloudTrail 을 활성화시킬 필요는 없다는 뜻입니다. (물론, GuardDuty 가 "분석" 에 사용하는데에는 지장이 없지만, 추후 추가적인 조사를 위해 따로 활성화시켜두는것이 좋습니다)

하지만, 그렇다고 하더라도 CloudTrail 에서 모든 AWS 상에서의 Management Events 를 분석해주고 Flow Logs 를 통해 VPC 의 모든 트래픽을 분석해주니 기본적인 시큐리티 사고는 거의 다 탐지해준다고 보시면 됩니다! 참고로, S3 의 데이터 중에 개인정보 등의 민감한 정보가 포함되어있는지 자동으로 분석해주는 Amazon Macie 라는 서비스를 활용하시면 S3 데이터를 대상으로 시큐리티 사고 탐지도 가능합니다.

....

라고 얼마전까지는 GuardDuty 와 함께 Macie 에 대해서도 함께 소개하기도 했었는데요, 최근에 GuardDuty 의 기능이 대폭 확대되어 S3 Protection 기능을 추가로 설정하실 수도 있습니다!

자, 이제 Amazon GuardDuty 의 기본적인 개요에 대해 설명을 드렸으니 구체적으로 어떤 기능들이 있는지 좌측 메뉴를 하나씩 클릭해보면서 확인해보겠습니다.

Usage 메뉴에서는 단순히 지금까지 GuardDuty 에서 사용한 비용을 보여줍니다. 실제로 활성화시켜보시면 아시겠지만, 대부분의 경우 많아봐야 전체 AWS 비용의 1~2% 를 차지할 정도의 소액입니다. 대신 시큐리티 사고에 대해 즉각적으로 통보를 받고 대응할 수 있도록 도와준다는 점에서 사실상 모든 AWS 어카운트에 무조건 활성화시켜둬야하는 서비스 중에 하나라고 생각합니다.

이번엔 Settings 메뉴로 넘어가보겠습니다. 빨간색으로 표시된 부분은 제가 강조하고 싶은 부분인데요, Findings 의 업데이트 주기는 기본값으로 6시간으로 설정되어있는데, 이 기본값을 가장 짧은 단위인 15분 으로 변경하시는 것이 좋습니다. 시큐리티 문제가 발생하면 다 막대한 비용을 치뤄야하는 경우가 흔하므로 당연히 조금이라도 빨리 Findings 의 통보를 받는것이 좋겠죠! 참고로, 포스팅의 아래에서는 Findings 를 SNS Topics 에 연계하는 방법에 대해서도 소개드리니, Amazon GuardDuty 를 직접 AWS 어카운트에 설정하고 싶으신 분들은 끝까지 읽어주세요ㅎㅎ

그 아래로 스크롤을 좀 내리면 Sample Findings 를 생성해주는 기능이 있습니다. Amazon GuardDuty 를 처음 접하시는 분들은 어떻게 사용해야하나 막막할 수 있는데요 (제가 그랬습니다..ㅠ) Amazon GuardDuty 팀에서 학습목적 등으로 활용할 수 있는 Sample Findings 를 즉시 생성해주는 유용한 기능도 제공하고 있으니, GuardDuty 를 좀 더 공부해보시고 싶으신 분들은 꼭 한번 사용해보세요!ㅎㅎ

이번엔 List 메뉴입니다. GuardDuty 입장에서는 어떤 IP 가 위협을 줄 수 있는 IP 인지 모르기때문에 이러한 Trusted IP lists 와 Threat lists 를 설정해주는 것으로 불필요한 탐지와 통보를 막을 수 있습니다.

다음은 최근에 출시된 S3 Protection 기능입니다! Amazon GuardDuty 를 활성화시켰더라도 이 기능만큼은 별도로 따로 활성화를 시켜줘야하므로 필요한 경우에는 이 기능을 직접 활성화해줍시다!

S3 Protection 에 대한 자세한 내용은 아래 글들을 참고해주세요 :)

이번엔 Accounts 메뉴입니다. AWS 를 사용해서 서비스를 구성하다보면 다양한 이유로 어카운트를 나누는 것을 고려하게 됩니다. Amazon GuardDuty 를 활성화시키고 제대로 활용하기 위해서는 모든 AWS 어카운트 의, 모든 리젼 에 GuardDuty 를 활성화시켜줄 필요가 있는데요, 활성화와 함께 위에서 설명한 Trusted IP lists / Threat lists 관리, 각종 설정 등을 하나하나 설정해줘야하는 번거로움들이 있습니다. 이러한 불편함을 개선하기위해 마스터 및 멤버 계정을 통해 이러한 작업을 손쉽게 할 수 있도록 도와줍니다.

사실, 이 기능을 제대로 이해하기 위해서는 AWS Organizations 에 대해 이해할 필요가 있습니다. 자세한 내용은 아래 공식 도큐먼트를 참조해주세요 :)

Understanding the relationship between GuardDuty master and member accounts

위 도큐먼트에서 제공하는 "표" 만 정확히 이해하신다면 사용하시는데 큰 어려움은 없을것 같습니다!

GuardDuty 의 Finding 을 살펴봅시다

여기까지 GuardDuty 에서 제공하는 메뉴들에 대한 간단한 개요에 대해 설명드렸습니다. 생각보다 별로 어렵지 않다는거 느끼셨다면 대성공입니다!ㅎㅎ 이번에는 Sample Findings 로 생성한 Finding 하나를 골라서 어떤 정보들을 알 수 있는지 간단히 살펴보겠습니다.

Amazon GuardDuty 에서는 Finding 의 등급을 Low, Medium, High 의 3가지로 분류해줍니다. 색깔을 보시면 High 가 빨간색, Low 가 파란색입니다.

빨간색으로 표시된 Finding 중에 Backdoor:EC2/DenialOfService.Udp 라고 하는 종류의 Finding 을 살펴보겠습니다. 참고로, GuardDuty 에서 제공해주는 Finding 의 모든 분류는 아래의 공식 도큐먼트에서 확인하실 수 있습니다.

Amazon GuardDuty - Finding types

위 문서에 따르면 Backdoor:EC2/DenialOfService.Udp 타입의 경우,

This finding informs you that the listed EC2 instance within your AWS environment is generating a large volume of outbound UDP traffic. This may indicate that the listed instance is compromised and being used to perform denial-of-service (DoS) attacks using UDP protocol.

이 조사 결과는 해당 AWS 환경에 대용량의 아웃바운드 UDP 트래픽을 생성 중인 EC2 인스턴스가 있음을 알려 줍니다. 이것은 인스턴스가 손상되어 UDP 프로토콜을 통한 DoS(Denial of Service) 공격 수행에 사용 중임을 나타냅니다. 이 조사 결과는 DoS 공격의 주요 대상인 공개적으로 라우팅이 가능한 IP 주소에 대한 DoS 공격만 감지합니다.

라고 설명이 되어있는 것을 볼 수 있습니다. 상당히 심각한 문제네요.

Resource Affected 항목에 기재된 리소스에 즉각적인 조치가 필요해보입니다. 아래에 좀 더 스크롤을 내려보면

네트워크 정보나 좀 더 구체적인 액션의 정보 등을 확인하실 수 있습니다.

음..? 이게 GuardDuty 의 기능 전부냐구요?

네, 이게 전부입니다. Amazon GuardDuty 가 좋다는 건 많이 들어봤는데, 어떤 서비스인지 도무지 감이 안오시는 분들은, 바로 Amazon GuardDuty 의 역할이 검출까지 라는 전제를 파악하지 못하고 있을 가능성이 높습니다. 그래서, 추가적인 조치나 대응, 복구 등을 위해서는 직접 대응하거나, 아니면 AWS 에서 제공하는 다른 서비스들을 다같이 조합해서 활용하시는 것이 권장됩니다.

하지만 Amazon GuardDuty 가 해주는 그 "Detect(검출)" 이라는 기능 자체는 굉장히 편리하고 유용합니다. 대부분의 경우 시큐리티 사고가 발생했다는 것을 알게되는 순간은, 월별 청구서에 이상하리만큼 높은 비용이 청구되었을 때 액세스키가 누출된 것을 깨닫게되거나 혹은 아예 시큐리티 사고가 일어난줄도 모르고 있다가 우연히 알게되었을때는 이미 대응이 한참 늦게되는 상황이 벌어지게됩니다. 따라서 Amazon GuardDuty 의 역할은 시큐리티 사고를 "Detect" 하는 것까지 라고 이해를 하시면 Amazon GuardDuty 를 더욱 유용하게 사용하실 수 있으실거라 믿습니다.

GuardDuty 의 Finding 은 정말 신뢰할만할까요?

Finding 을 찾아주는건 너무 고맙고 편리한 기능이지만, 머신러닝 알고리즘을 통해 자동으로 위협요소를 분류해낸것이다보니 가끔 오탐으로 판단되는 Finding 을 알려줄 때도 있습니다. 이 부분은 AWS 측에서 열심히 개선하고 있다고 하니 점점 더 나은 결과를 알려줄 수 있기를 기대해봅니다! 하지만, 현재의 정확도도 충분히 신뢰할 정도라고 생각되므로 GuardDuty 의 유효성에 대해서는 유효하다고 생각합니다. 다만, 모든 Finding 이 "정탐" 이 아닐수도 있다는 점은 알고 계시는 것이 좋습니다!

GuardDuty 의 Findings 가 발견되면 즉각 통보받고 싶어요!!

Amazon GuardDuty 를 실전에서 활용하기 위한 가장 필요한 기능!! 바로 Findings 의 업데이트 정보를 즉각적으로 수신할 수 있도록 설정하는 기능인데요, CloudWatch Events 를 통해 설정하실 수 있습니다.

자세한 내용은 아래 공식 도큐먼트를 읽어주세요 :)

Creating custom responses to GuardDuty findings with Amazon CloudWatch Events

실제로 적용해봅시다!!

이번 포스팅에서는 가장 기본이 되는 Amazon GuardDuty 를 모든 리젼에 대해 활성화시키는 코드를 공유합니다. 위에서 언급한 Finding 을 즉시 통보받기 위한 CloudWatch Events 는 별도로 추가 작업을 해주셔야하지만, 단순히 룰을 연결하는것 뿐이니 매우 쉽게 설정하실 수 있을것입니다!

## 특정 AWS 어카운트의 모든 리젼에 Amazon GuardDuty 를 활성화시키고 
## Finding 의 Frequency 를 15분 간격으로 설정해주는 코드입니다 :)

import boto3

# IAM Role 을 사용하는 경우 (사용하지 않는다면 아래 코드에서 boto3_role 을 boto3 로 수정후 사용하시면 됩니다.)
boto3_role = boto3.session.Session(profile_name='xxxxx', region_name='ap-northeast-2')

# 모든 리젼의 이름을 리스트로 담아줍니다
ec2 = boto3_role.client('ec2')
regions = [ region['RegionName'] for region in ec2.describe_regions()['Regions'] ]
print('Enabling GuardDuty on each region...')

for region in regions:
    msg = "# Region : {} : ".format(region)

    try:
        # 실제로 GuardDuty 를 활성화하는 코드입니다. 단 한번의 메소드 호출로 활성화 됩니다!
        guardduty = boto3_role.client('guardduty', region_name=region)
        result = guardduty.create_detector(
            Enable=True,
            FindingPublishingFrequency='FIFTEEN_MINUTES'
        )
        msg += 'success (DetectorId: {})'.format(result['DetectorId'])
    except Exception as e:
        msg += 'failed (exception message : {})'.format(e)
    
    print(msg)

아래 코드는 모든 리젼에 설정된 Amazon GuardDuty 를 비활성화 시키는 코드입니다.

import boto3

boto3_role = boto3.session.Session(profile_name='xxxxx', region_name='ap-northeast-2')

ec2 = boto3_role.client('ec2')
regions = [ region['RegionName'] for region in ec2.describe_regions()['Regions'] ]

for region in regions:
    guardduty = boto3_role.client('guardduty', region_name=region)
    response = guardduty.list_detectors()
    detectorId = response['DetectorIds'][0]

    result = guardduty.delete_detector(
        DetectorId=detectorId
    )

    print(result)

Amazon GuardDuty Deep Dive

좀 더 딥다이브로 공부하시길 원하신다면 위 영상을 보시는 것을 추천합니다. AWS Online Tech Talks 에서 2018 년 2월 28일에 공개한 영상입니다. S3 Protection 등의 기능은 당연히 빠졌지만 GuardDuty 를 활용하는지 전체적으로 어떤식으로 확인하실 수 있습니다.

글을 맺으며

본 포스팅은 Amazon GuardDuty 에 대한 기초적인 입문 내용부터 실전에서 사용할 수 있는 코드를 공유하는 것까지, 사실상 본 포스팅을 읽는 것만으로도 Amazon GuardDuty 에 대해 상당한 이해수준을 갖출수 있도록 하는 것을 목적으로 작성하였습니다. 혹시 이 글을 읽고 난 후에도 Amazon GuardDuty 가 어떤 기능을 하는지 잘 감이 안오신다면 AWSKRUG 슬랙채널의 @twkiiim 으로 멘션걸어주세요. 더 나은 내용을 전달드릴 수 있도록 글을 지속적으로 수정해나가겠습니다.

긴 글 읽어주셔서 감사합니다.

이상, 컨설팅부의 김태우였습니다! :)