콘텐츠로 이동

1. 개요

1.1 사고 배경

Ubiquiti는 미국 뉴욕에 본사를 둔 기술 기업으로, 전 세계 200개국 이상에서 사용되는 네트워크 인프라 장비와 관련 소프트웨어 플랫폼을 개발·판매합니다. 회사는 서비스 제공자, 기업, 소비자 시장을 대상으로 무선 LAN, 라우팅, 보안 게이트웨이, 영상감시, 출입통제 등 다양한 네트워크 제품군을 운영하고 있습니다. 즉, AWS와 GitHub 같은 클라우드 및 개발 인프라는 단순 내부 IT 시스템이 아니라, 회사의 제품 개발과 운영 전반을 뒷받침하는 핵심 자산이라고 볼 수 있습니다.

이 사건의 가해자인 Nickolas Sharp는 2018년 8월경부터 2021년 4월 1일경까지 Ubiquiti에서 근무한 시니어 개발자였습니다. 미국 법무부에 따르면 그는 회사의 AWS와 GitHub 서버 자격증명에 접근할 수 있는 위치에 있었고, 실제로 자신의 역할상 AWS 클라우드 관리자 권한에 접근할 수 있었습니다.

1.2 사고 요약

사건은 2020년 12월 10일부터 26일 사이에 발생했으며, 2021년 1월 11일 대외에 공개되었습니다. 공격자 Nickolas Sharp는 시니어 클라우드 엔지니어로서 GitHub 레포지터리 1,100개 이상, Secrets Manager 파일 수십 개, Task Definition 파일 1,400개 이상을 탈취했습니다.

법무부 자료에 따르면 Sharp는 2020년 12월 회사의 기밀 데이터를 수 기가바이트 단위로 내려받은 뒤, 2021년 1월 익명 공격자로 가장하여 회사에 50 BTC를 요구했습니다. 이후 데이터 유출 과정 중 한 시점에 SHARP의 자택에서 일시적인 인터넷 장애가 발생하여 그의 IP 주소가 노출되어 FBI가 자택을 수색했습니다. 그럼에도 불구하고 Sharp는 자신은 가해자가 아니라는 등의 거짓 진술을 하였습니다. 또한 이후에 몸값이 받아들여지지 않자, 자신을 익명의 내부고발자로 꾸며 언론에 허위 정보를 전달했고, 검찰은 이로 인해 회사 시가총액이 40억 달러 이상 떨어졌다고 설명했습니다. Sharp는 결국 6년의 징역형과 1,590,487달러의 배상금을 지불하게 되었습니다.

2. 공격 분석

2.1 공격 흐름 (Attack Flow)

이 사건에서의 공격 흐름은 다음과 같이 정리할 수 있습니다.

  1. 자택 네트워크에서 자신의 직원 자격증명을 사전 검증
  2. SurfShark VPN으로 신원을 은폐한 채 GitHub Repo를 대량으로 클론하고 AWS에 침투해 데이터 탈취
  3. 탈취 이후에는 Cloudtrail 로그가 담긴 S3 버킷의 수명 주기 정책을 1일로 변경해 증거 인멸 시도
  4. 익명으로 회사의 데이터를 빌미로 몸값을 요구하면서 동시에 사고 조사 팀에 합류해 수사 상황을 모니터링
  5. 자신의 자택 수사 이후에도 허위 제보를 통해 주가 폭락을 유도

2.2 단계별 공격 프로세스

1. 자격증명 사전 검증

  • Sharp(이하 공격자)는 본격적인 데이터 탈취에 앞서 자택 네트워크에서 자신의 직원 자격증명이 유효한지 먼저 확인했습니다.
  • 공격자는 현재 사용 중인 자격증명이 어느 AWS 계정의 어느 사용자에 연결되어 있는지를 반환 하는 "GetCallerIdentity" 명령을 실행하여 AWS 계정의 사용자 이름과 계정 정보를 가져왔습니다. (자신이 보유한 자격증명이 여전히 유효한지 확인)

2. VPN 우회 후 GitHub 대규모 클론

  • 공격자는 신원 은폐를 위해 Surfshark VPN을 켠 뒤 Ubiquiti의 GitHub 조직 계정에 접속하여 레포지터리를 로컬로 대량 클론하기 시작했습니다.
  • 최종적으로 1,100개 이상의 레포지터리가 탈취된 것으로 확인되었습니다.
  • 클론 도중 Sharp의 자택 인터넷 연결이 약 30분간 끊겼는데, 연결이 복구된 후에도 VPN이 재연결되지 않은 상태에서 클론 명령이 계속 실행되었고, 이 30분간의 로그에 그의 자택 IP 주소가 남게 되었습니다.

3. AWS 세션 이름 위조

  • CloudTrail 로그를 분석하는 사람이 봤을 때 다른 직원의 행위처럼 보이도록 AWS에 접속할 때 공격자는 세션 이름을 수동 지정하는 방식으로 DevOps 팀원 5명의 이름 중 하나처럼 보이도록 18회에 걸쳐 위조했습니다.

4. CloudTrail 로그 수명 주기 정책 변경

  • AWS Secrets Manager에서 수십 개의 시크릿 파일과 1,400개 이상의 Task Definition을 탈취한 뒤, CloudTrail 이벤트가 저장된 S3 버킷의 수명 주기 정책을 1일로 변경했습니다.(다음 날에 자신의 활동 흔적이 담긴 로그가 자동으로 삭제되도록 설계)

5. 몸값(랜섬) 요구 및 사고 대응 팀 합류

  • 탈취한 데이터를 빌미로 50 BTC를 요구하는 이메일을 익명으로 발송했습니다.
  • 회사가 이에 응하지 않자 일부 데이터를 Keybase 퍼블릭 링크로 공개했습니다.
  • 동시에 회사 내부에서 진행되는 사고 대응 팀에 직접 합류하여 수사가 어떻게 진행되는지 실시간으로 파악하며 수사가 어떤 방향으로 흘러가는지 모니터링했습니다.
  • 마지막으로 보안 전문 저널리스트 Brian Krebs에게 익명의 내부 제보자인 척 허위 정보를 흘려 회사가 사건 규모를 축소하고 있다는 내용의 제보를 했습니다.
  • Krebs의 기사가 나간 직후 주가가 20% 이상 폭락하며 시가총액 약 40억 달러가 감소했습니다.

2.3 사용된 기법 및 도구 (TTPs)

마이터 어택을 기준으로 한 TTPs를 정리하면 다음과 같이 정리할 수 있습니다.

전술 (Tactic) 기법 (Technique) 설명
Defense Evasion Masquerading Sharp는 AWS에 접속할 때 세션 이름을 다른 DevOps 팀원의 이름처럼 보이도록 위조했습니다.
Defense Evasion Proxy Sharp는 Surfshark VPN을 사용해 자신의 실제 자택 IP 주소를 숨기고 GitHub 조직 계정 등에 접근했습니다.
Initial Access Valid Accounts Sharp는 외부에서 탈취한 계정을 사용한 것이 아니라, 본인이 업무상 정당하게 보유하고 있던 AWS 및 GitHub 접근 권한을 악용했습니다.
Collection Data from Cloud Storage Sharp는 AWS Secrets Manager의 시크릿 파일, Task Definition 등 클라우드 환경에 저장된 데이터를 대량으로 수집했습니다.

3. 대응 방안

3.1 즉각 대응 절차

해당 사건에서는, 사건 도중에서야 공격자의 실수로 인해 내부자 위협임을 알게되었는데, 이렇게 내부자인지 외부자인지 모르는 상황에서 할 수 있는 즉각 대응은 범인을 특정하는 게 아니라, 피해 범위를 정확하게 파악하고 추가 유출을 막는 것입니다.

이를 위해서는 어떤 자격증명이 비정상적으로 사용되었는지, 어떤 버킷에 접근이 있었는지, 로그가 얼마나 남아있는지를 먼저 파악해야 합니다. 또한접근 패턴이 정상 자격증명을 사용했고 인증 단계에서 이상 징후가 없었다면, 조사 범위를 외부자뿐만아니라 내부자로도 넓혀 외부에 알려지지 않은 채로 비밀리에 조사를 해야합니다.

이 사건처럼 CloudTrail 로그가 저장된 S3 버킷의 수명 주기 정책이 이미 변조된 상황이라면, 아직 삭제되지 않은 로그를 즉시 별도 위치로 복사해 보존해야합니다.

이렇게 로그 보존을 해두고, 의심 직원을 식별한 뒤에는 해당 직원의 AWS IAM 자격증명, GitHub 토큰, SSO 세션을 즉시 비활성화해야 합니다. 이후 GitHub Audit Log에서 클론 이력을 확인하고, Secrets Manager 접근 이력을 전수 조회하여 노출된 시크릿을 전체 교체하는 등의 조치를 취해야합니다.

3.2 사후 조치 및 재발 방지

이 사건에서 알 수 있는 중요한 보안 사항은 신뢰할 수 있는 내부 직원도 감시 대상이어야 한다는 점입니다. 권한이 있다고 해서 모든 행위가 무조건 정당한 것은 아니며, 특히 로그와 감사 데이터를 건드릴 수 있는 권한은 별도로 관리되어야 합니다.

  1. 이 사건에서 가장 큰 문제는 공격자가 자신의 흔적이 담긴 CloudTrail 로그를 지울 수 있었다는 점입니다. 이 것이 가능했던 이유는 로그 버킷과 운영 환경이 같은 AWS 계정 안에 있었고, 공격자는 그 계정의 관리자였기 때문이라고 할 수 있습니다. 따라서 CloudTrail 로그 보호 아키텍처를 서비스 운영 계정과 분리해 운영하는 것이 재발 방지를 위한 대안이 될 수 있습니다. 따라서 운영 계정에서는 로그를 생성하기만 하고, 실제 저장은 별도 보안 전용 계정의 S3 버킷에 교차 계정 방식으로 하도록 구성하도록 한다면, 운영 계정 관리자는 로그가 어디에 쌓이는지는 알아도 거기에 손을 댈 수가 없을 것입니다. 해당 버킷에는 S3 Object Lock을 통해 Amazon S3에 저장된 객체의 삭제나 덮어쓰기를 일정 기간 또는 무기한으로 방지하는 기능인 WORM(Write Once Read Many) 설정을 적용하고, SCP로 수명 주기 정책 변경 자체를 금지하면 운영 계정 관리자라도 로그를 삭제할 수 없게 될 것입니다.

  2. 또한 관리자급 계정의 고위험 API 호출에 대한 실시간 모니터링 체계가 필요합니다. PutBucketLifecycleConfiguration, DeleteTrail, StopLogging, GetSecretValue 등의 대량 호출, 동일 IAM 세션 명의의 중복 접속, 평소와 다른 IP 대역에서의 접속 등은 즉시 알림을 할 필요가 있습니다. CloudWatch Metric Filter와 SNS를 조합하거나 GuardDuty 및 EventBridge로 수신하도록 구성한다면 이러한 행위를 실시간으로 포착할 수 있을 것입니다.


참고자료

  • https://www.justice.gov/usao-sdny/pr/former-employee-technology-company-charged-stealing-confidential-data-and-extorting
  • https://www.justice.gov/usao-sdny/pr/former-employee-technology-company-sentenced-six-years-prison-stealing-confidential
  • https://www.breaches.cloud/incidents/ubiquiti