AWS에서 네트워크 공격 자동차단 하기

Feb.23.2018 오석윤

Security

Introduction

Summary

최근 Public cloud 시장이 활성화 되면서 많은 기업들이 Cloud 도입을 시작하고 있으며, 한국의 경우 대표적으로 Amazon Web Service(AWS)를 사용하고 있다. 그리고 한국의 Seoul region(ap-northeast2)은 2017년 12월 기준으로 AWS Global 매출 TOP 5에 포함된 만큼 폭팔적으로 사용량이 늘어나고 있다. 그러나 Legacy환경의 IDC과 너무도 다른 환경에서의 보안은 쉽지 않기때문에 본 글에서는 우아한형제들의 AWS에서 기술적인 보안 방법을 공유 하는것을 목적으로 하고, 시리즈로 연재 하고자 한다.

Backbround

AWS에서 네트워크 보안은 몇가지 어려움이 있는데, 그 중에서 SecurityGroup은 White-list 기반 정책만 가능하기때문에 특정 EC2로 네트워크 공격이 들어오는 경우 Black-list로 차단 할 수가 없다. 차단 하려면 윈도우 방화벽이나, iptables를 이용해야 하는데 그렇게 하려면 scale-in, out이 빈번하게 일어나는 환경에서 매번 ec2 한대씩 터미널로 접속을 해야하는 엄청난 수고를 해야한다.그래서 VPC의 subnet에 있는 NACL을 이용을 권장하며, NACL은 subnet 단위로 L4 기반 차단을 할 수가 있다.

그.러.나 GuardDuty에서 탐지되는 수백개의 이벤트를 하나씩 확인해서, 공격 대상이 되고 있는 ec2들이 사용하는 subnet을 확인하고, NACL을 입력해주는것은 수백마리의 벌레들을 한마리씩 잡는것과 같다. 그정도로 많은 이벤트가 발생할까? 라는 생각을 할 수도 있는데, AWS는 AWS에서 사용되는 IP주소 목록을 Public하게 공개 해뒀고, 그 목록 안에서 사용자들에게 할당/회수를 반복적으로 하기때문에 IP주소 목록을 기반으로 많은 공격들이 들어온다.

(그나마 몇개 잡으면 다른 것들이 벌때처럼 밀려들어온다..)

나는 고민끝에 GuardDuty에서 탐지되는 네트워크 공격들의 대상 정보를 자동으로 Pasring 하고, 대상 정보를 바탕으로 NACL에 차단 Rule을 자동으로 추가 및 차단 로그를 남기고, 지정된 시간이 경과하면 자동으로 차단 해제하는 자동화된 초동 대응용 모델을 AWS API들을 이용하여 디자인하였다.

Architecture

구성도

  1. VPC 트래픽을 미러링으로 받은 GuardDuty가 악성 트래픽을 탐지.
  2. 탐지 이벤트가 발생하면, CloudWatch Event 에서 차단용 Lambda에게 이벤트를 전달 및 호출하여 Lambda에서 이벤트 정보 분석 후 NACL으로 차단 Rule 삽입
  3. 차단 후, s3에 차단 Log를 저장.
  4. 차단 후, 일정 시간(기본 5분)이 지나면 차단 해제용 Lambda에서 s3의 차단 Log를 불러옴.
  5. 차단 해제용 Lambda에서 NACL의 차단 Rule 삭제.
  6. 자동화된 초동 대응은 1~5번까지 작동하고, 관리자는 이후 의사결정을 통한 후속 대응.

순서도

  1. GuardDuty에서 탐지 이벤트가 발생하면, CloudWatch Event를 호출하게 되고 Event Rule 조건과 일치 한다면, CloudWatch Event에서 지정된 Lambda에게 이벤트 log를 전달 하면서, 호출하게 된다.
  2. 호출된 차단용 Lambda는 GuardDuty 이벤트 log를 parsing 한다.
  3. parsing된 JSON Object를 이용하여 AWS NACL관련 API를 사용하여 차단 Rule을 추가하고, 차단 log를 JSON Object 포멧으로 s3에 저장하게 된다.
  4. 그리고 CloudWatch Event에서 차단용 Lambda를 호출할때 동시에 SNS를 이용하여 연동된 메신저로 관리자에게 경고 메세지를 발송하게 된다.
  5. 차단과 경고 메세지 발송이 완료된 이후, 지정된 시간(15분)이 지나서 차단 해제용 Lambda를 호출하면, 차단 해제용 Lambda는 s3에서 차단 log를 불러와서 차단된 Rule을 확인하고 삭제한다.
  6. 여기까지가 자동화된 초동 대응 완료!
  7. ElasticSearch로 전송된 log는, orchestration & automation tool에 의하여 자동으로 IP주소나 domain 평판 정보를 분석하고 관리자에게 이메일로 리포팅 한다.
  8. 관리자는 리포트를 확인하고 악성으로 판단되는 경우 GuardDuty의 Black-list에 등록하게 되고, 오탐인 경우에 White-list에 등록하여 예외 처리를 한다. 즉, 관리자는 마지막 부분의 Black-list, White-list부분에서만 개입하게 되고 나머지는 자동으로 진행되게 된다.

GuardDuty 설정하기

GuardDuty의 탐지 데이터가 어떻게 표현 되는지 확인

GuardDuty에서 탐지 이벤트 발생을 CloudWatch Event의 trigger 조건으로 설정해서, 이벤트가 발생하면 탐지 데이터를 특정 Lambda로 넘겨주고 Parsing 과정을 거친 다음 NACL에 차단 Rule을 추가하는 순서로 진행된다. 때문에 탐지된 데이터를 적절히 Parsing 해야, NACL에 차단 Rule을 추가/삭제를 용이 하게 할 수 있기때문에 아래와 같이, 먼저 샘플용 탐지 데이터들을 생성하여 참고하는것이 좋다.

  1. GuardDuty 활성화.
  2. Settings → General(일반) 텝에서 Generate sample findings 버튼을 클릭하여 샘플 데이터를 생성.
  3. Findings → Current 에서 생성된 샘플 데이터를 선택하고 Action → Export 버튼을 클릭하면, JSON format의 탐지 데이터를 볼 수 있다.
  4. 생성된 샘플들을 모두 다운로드 받아서, 필요한 Field를 추출.
GuardDuty의 탐지 데이터에서 필요한 필드
  • detail.region : 공격이 탐지된 region
  • detail.type : 공격 식별자(약어로 표시 됨)
  • detail.service.action.actionType : 공격 유형
  • detail.resource.instanceDetails.instanceId : 공격을 받은 인스턴스의 ID
  • detail.accountId : 공격이 탐지된 AccountID
  • detail.resource.instanceDetails.tags : 인스턴스 Tag들 정보이며, 반복문을 이용해서 Name과 같은 정보 추출에 용이하다.
  • detail.service.action : 공격자의 source IP, Port, Protocol, GeoLocation 등 공격자 정보.
  • 기타 다른 부분들은 샘플 JSON 참고.

Lambda 만들기

탐지 이벤트 발생과 동시에, CloudWatch Event에서 Lambda를 호출하게 되는데 Parsing 및 NACL 차단 Rule 추가시 주의해야할 사항은 아래와 같다.

  • detail.service.action.actionType은 공격 유형을 나타내는데, 이 공격 유형에 따라서 탐지 데이터의 JSON Field 위치들이 변경된다. 예를들면,Port scanning의 공격자 정보는 detail.service.action.portProbeAction.portProbeDetails 필드에 나타나지만, Brute force의 공격자 정보는 detail.service.action.networkConnectionAction 필드에 나타난다.
  • NACL에 차단 Rule을 추가 할때에 Rule Number는 필수로 들어가야 한다.(Rule Number는 중복되면 안됨)
  • NACL에 차단 Rule을 추가 할때에 Protocol 종류는 필수로 들어가야 하며, 문자열이 아닌 Protocol number인 숫자로 표기해야 한다.(TCP:6, UDP:17)
  • NACL당 차단 Rule은 기본 20개 까지만 추가 가능하며, 더 필요한 경우 40개 까지 늘릴 수 있지만, 워크로드 증가로 네트워크 성능에 영향을 줄 수 있다.
  • 내가 테스트 했을때 차단 해제는 5분, 20분 1시간 단위가 가장 적절한것으로 테스트 되었지만, 서비스에 따라서 시간은 조절 할 필요가 있다.(차단 해제는 timestamp 비교로 했음)
  //참고용 NACL에 차단 Rule 추가 코드(javascript)
  //ACl inbound rule params
  var in_params = {
    CidrBlock: ipv4 + "/32",
    Egress: false, //If true, OUTbound rule. fasle is INbound
    NetworkAclId: aclId,
    PortRange: {
      From: port,
      To: port
    },
    Protocol: protocol,
    RuleAction: "deny",
    RuleNumber: acl_cnt
  };

  //Create ACL inbound rule
  ec2.createNetworkAclEntry(in_params, function(err, data) {
    if (err) {
      console.log(err.message, acl_cnt);
    }
    else {
      //Calc timestamp
      var createDate = Date.now()

      //ACL rule data for log saved
      var aclRuleData = {
        aclId: aclId,
        aclRuleNum: acl_cnt,
        sourceIpv4: ipv4,
        localPort: localPort,
        protocol: protocol,
        accountName: accountName,
        instanceId: instanceId,
        instanceName: instanceName,
        instanceTeam: instanceTeam,
        region: region,
        soureCountry: soureCountry,
        threatType: threatType,
        createDate: createDate,
        date: convertMsecToMin(Date.now())
      };

      //ACL rule data to s3 params
      var s3_params = {
        Bucket: accountBucketName,
        Key: 'guardduty.' + aclId + '.' + acl_cnt + '.log',
        Body: JSON.stringify(aclRuleData)
      };

      //Send to ElasticSearch
      post(JSON.stringify(aclRuleData));

      //Put ACL rule data to s3
      s3.putObject(s3_params, function(err, result) {
        if (err) {
          console.log(err, err.stack);
        }
        else 
      });
      console.log("Create AclEntry Successful : n", in_params); // successful response
    }
  });

CloudWatch Event 설정하기

GuardDuty에서 탐지 이벤트가 발생되면, Lambda를 실행 하도록 trigger 설정을 CloudWatch Event에서 해줘야 하며, 모든 공격에 반응하기 보다는 serverity가 5이상의 수준에만 반응 하도록 설정 해주는것이 워크로드 증가를 줄일수 있기 때문에 권장한다.

  1. CloudWatch → Events → Rules → 에서 Create rule 버튼을 클릭하여 추가.
  2. Event Pattern → Servive Name은 GuardDuty로 설정.
  3. Ebent Pattern Preview에서 Edit 버튼을 클릭하여 아래와 같이 serverity가 5 이상의 수준에만 반응 하도록 수정.
    {
    "source": [
    "aws.guardduty"
    ],
    "detail-type": [
    "GuardDuty Finding"
    ],
    "detail": {
    "severity": [
      5,
      6,
      7,
      8,
      9,
      10
    ]
    }
    }

차단 로그 활용하기

차단된 로그들은 s3에 저장하고, 저장된 로그들을 위의 그림처럼 ElasticSearch로 가져와서 차단 추이 분석이나, 다른 AWS Account별로 공유하여 IP Black-list를 생성 할 수 있다.
나는 ElasticSearch를 이용하여 차단 로그들을 관리하고 NACL을 조절함으로써 자동차단 도입전 대비 공격 시도를 약 80% 줄였다.

Conclusion

Public cloud는 flexibility and scalability가 최고의 장점이다. 그런데, 보안하는 입장에서는 신경 써야할것이 엄청나게 많다. 예전에는 IDC환경에서 장비들 박아놓고 관리만 하면 되었지만, 지금은 늘어났다 줄어났다도 부족해서 여기갔다 저기갔다 하는 IT자산들에 맞춰서 움직이고, 구성을 변경하고, 보안 범위를 늘였다 줄였다 해야한다.이런 환경에서 사람이 수동으로 작업 한다는것은 미친짓이다. 때문에 이런 환경에 빠르게 대응 하려면 자동화는 필수이다. Public cloud로 이전을 고려하고 있는 회사의 보안 관리자라면 이러한 Security orchestration and automation를 반드시 고민해야 할것이다.