SolarWinds의 IT 관리 솔루션 업데이트를 이용해 SUNBURST 백어도를 배포한 트로이 목마 공격 분석

FireEye
Jan 06, 2021
10 min read
|   Last updated: Jun 06, 2023

파이어아이는 2020년 봄에 광범위하게 진행 중인 캠페인을 하나 발견했습니다. 그리고 이를 진행하는 행위자를 UNC2452이라고 명명한 다음 지속적으로 추적하고 있습니다. 이번 캠페인의 배후에 있는 UNC2452는 IT 모니터링 및 관리 소프트웨어인 SolarWinds의 Orion 공식 업데이트를 통해 트로이 목마를 배포하였습니다. 이로 인해 전 세계 주요 공공 및 민간 조직이 영향을 받았습니다. 이 악성 코드를 파이어아이는 SUNBURST라고 이름 붙였습니다. 공격자는 여러 기술을 동원해 탐지를 회피하였습니다. 파이어아이는 이 공격을 탐지하기 위해 서명을 공개하였고, 이를 깃허브에 올렸습니다. SUNBURST 백도어 침투와 측면 이동을 어떻게 탐지하였는지 살펴보겠습니다.

2020년 봄에 시작된 백도어 배포

파이어아이의 관찰에 따르면 UNC2452는 2020년 봄부터 캠페인을 시작하였고, 현재도 진행 중입니다. 이 공격은 맬웨어를 이용한 침투를 시작으로 내부 확산 및 데이터 도난 등의 피해로 이어지고 있습니다. 이번 캠페인의 고도로 숙련된 이들의 작업으로 보입니다.

SolarWinds.Orion.Core.BusinessLayer.dll은 SolarWinds 디지털 서명 구성 요소로 HTTP를 통해 타사 서버와 통신하는 Orion 소프트웨어 프레임워크의 한 부분입니다. 파이어아이는 SolarWinds Orion 플러그인의 트로이 목마 버전을 SUNBURST라 이름 붙여 추적하고 있습니다.

SUNBURST는 최대 2주의 초기 휴면 기간이 지나면 파일 전송, 파일 실행, 시스템 프로파일링, 시스템 재부팅 및 시스템 서비스 비활성화 기능을 포함하는 "Jobs" 명령을 검색하고 실행합니다. 이 악성 코드는 네트워크 트래픽을 OIP(Orion Improvement Program) 프로토콜로 가장하고 정찰 결과를 합법적인 플러그인 구성 파일에 저장합니다. 따라서 합법적인 SolarWinds의 활동과 섞여 이상 행위를 탐지하지 못하게 합니다. 백도어는 여러 난독화된 차단 목록을 사용해 프로세스, 서비스, 드라이버로 실행되는 포렌식 및 안티 바이러스 도구를 식별합니다.

 


백도어가 있는 소프트웨어의 SolarWinds 디지털 서명

파이어아이의 관찰에 따르면 여러 트로이 목마 업데이트가 202년 3월부터 5월까지 디지털 서명이 되어 SolarWinds 업데이트 사이트에 게시되었습니다.

  • hxxps://downloads.solarwinds[.]com/solarwinds/CatalogResources/Core/2019.4/2019.4.5220.20574/SolarWinds-Core-v2019.4.5220-Hotfix5.msp

트로이 목마를 포함한 업데이트 파일은 SolarWinds.Orion.Core.BusinessLayer.dll 구성 요소 및 업데이트와 관련된 압축 리소스를 포함하는 표준 윈도우 인스톨러 패치 파일입니다. 업데이트가 설치되면 합법적인 SolarWinds.BusinessLayerHost.exe 또는 SolarWinds.BusinessLayerHostx64.exe (시스템 구성에 따라 다름)에 의해 악성 DLL이 로드됩니다. 최대 2주의 휴면 기간이 지나면 악성 코드는 avsvmcloud [.] com의 하위 도메인 확인을 시도합니다. DNS 응답은 명령 및 제어(C2) 도메인을 가리키는 CNAME 레코드를 반환합니다. 악성 도메인에 대한 C2 트래픽은 정상적인 SolarWinds API 통신을 모방하도록 설계되었습니다. 알려진 악성 인프라 목록은 파이어아이 깃허브 페이지를 참조 바랍니다.

전 세계 여러 조직에 피해 입혀

SolarWinds 업데이트에 숨어 들어온 트로이 목마의 피해자는 북미, 유럽, 아시아, 중동 지역의 정부, 컨설팅, 기술, 통신 회사 등입니다. 이외에도 다른 국가 및 조직에도 피해를 끼쳤을 것으로 보고 있습니다. 참고로 파이어아이는 발견된 피해 조직에 악성 코드 침투 사실을 모두 알렸습니다.

파이어아이는 악성 코드 침투 후 활동도 추적하고 있습니다. UNC2452는 초기 액세스 권한 획득 후 다양한 기술을 사용해 측면 이동을 시도했습니다. 분석에 따르면 UNC2452는 합법적인 자격 증명 및 원격 액세스를 선호합니다.

 

 

공격 기법

 

파이어아이는 여러 개의 SUNBURST 샘플을 복구해 분석했습니다. 공격자들은 Cobalt Strike BEACON 배포를 위해 이전에 본적 없던 메모리 전용 드로퍼를 배포했습니다. 파이어아이는 이를 TEARDROP이라고 이름 붙였습니다.

TEARDROP은 서비스로 실행되고, 스레드를 생성하고, 가짜 JPG 헤더가 있을 가능성이 있는 "gracious_truth.jpg" 파일을 읽는 메모리 전용 드로퍼입니다. 이후 공격자는 KU \ SOFTWARE \ Microsoft \ CTF가 있는지 확인하고, 사용자 지정 롤링 XOR 알고리즘을 사용해 페이로드를 디코딩 합니다. 그리고 사용자 지정 PE와 유사한 파일 형식을 사용해 수동으로 메모리에 포함된 페이로드를 로드합니다. TEARDROP은 이전에 파이어아이가 본 맬웨어와 코드가 중복되지 않습니다. 파이어아이는 이를 Cobalt Strike BEACON을 맞춤형으로 실행하기 위해 만들었다고 보고 있습니다. 참고로 파이어아이는 TEARDROP 감지를 위한 Yara 규칙 두 개를 깃허브에 올려놓았습니다. FireEye HX를 사용 중이라면 MalwareGuard 및 WindowsDefender의 다음 얼럿을 찾아야 합니다.

Process Information

file_operation_closed
file-path*: “c:\\windows\\syswow64\\netsetupsvc.dll
actor-process:
pid: 17900

Window’s defender Exploit Guard log entries: (Microsoft-Windows-Security-Mitigations/KernelMode event ID 12)           

Process”\Device\HarddiskVolume2\Windows\System32\svchost.exe” (PID XXXXX) would have been blocked from loading the non-Microsoft-signed binary
‘\Windows\SysWOW64\NetSetupSvc.dll’

공격자는 피해자 환경에서 찾은 합법적인 호스트 이름과 일치하도록 C2 인프라에 호스트 이름을 설정합니다. 이를 통해 의심에서 벗어나고 탐지를 회피합니다.

탐지 기회

공격자는 RDP SSL 인증서에서 구성된 호스트 이름을 유출하는데, 이는 인터넷 전체 스캔 데이터에서 식별할 수 있습니다. 역으로 생각하면 이는 방어자에게 탐지 기회를 제공한다고 볼 수 있습니다. 인터넷 전체 스캔 데이터 소스에서 조직 호스트 이름을 쿼리 하면 조직으로 가장할 수 있는 악성 IP 주소를 발견할 수 있습니다. 따라서 원격 액세스 로그와 인터넷 스캔 데이터에서 식별된 IP 목록을 상호 참조하면 공격의 증거를 찾을 수 있습니다.

파이어아이의 관찰에 따르면 공격자가 선택한 IP 주소는 탐지 회피에 최적화되어 있었습니다. 공격자는 주로 가상 사설 서버(VPS)를 활용해 피해자와 같은 국가의 IP 주소만 사용했습니다. 공격자가 주로 VPS를 사용하는 것도 탐지 기회를 제공합니다. 공격자는 VPS 공급자당 여러 IP 주소를 사용했습니다. 따라서 비정상적인 ASN의 악의적인 로그인이 식별되면 해당 ASN의 모든 로그인을 살펴보면 악의적인 활동 탐지에 도움이 될 수 있습니다.

공격자는 초기 침투 후 여러 다른 자격 증명을 사용해 내부 이동을 했습니다. 측면 이동에 사용된 자격 증명은 원격 액세스에 사용되는 자격 증명과 항상 달랐습니다. 참고로 FireEye HX 이용 조직은 LogonTracker 모듈로 모든 로그온 활동을 그래프로 표시해 소스 시스템과 계정 간의 일대다 관계를 분석할 수 있습니다. 이렇게 하면 비교적 드물게 발생하는 여러 계정을 사용해 여러 시스템에 인증을 시도하는 단일 시스템을 찾을 수 있습니다.

다음으로 공격자는 임시 파일 교체 기술을 사용해 원격으로 유틸리티를 실행했습니다. 합법적인 유틸리티를 공격자의 것으로 교체해 페이로드를 실행한 다음 합법적인 원본 파일을 복원했습니다. 공격자는 기존의 합법적인 작업을 업데이트하여 도구를 실행한 다음 예약된 작업을 원래 구성으로 되돌리는 방식으로 조작했습니다. 합법적인 원격 액세스가 이루어지면 백도어 제거를 포함해 정기적으로 도구를 제거하였습니다. 이런 공격 패턴에도 탐지 기회가 있습니다. 방어자는 합법적인 디렉토리에 대한 액세스를 보여주는 SMB 세션 로그를 검사하고 짧은 시간 내에 delete-create-execute-delete-create 패턴을 보이는 행위를 식별할 수 있습니다. 또한, 방어자는 비정상적인 수정을 식별하기 위해 기존 예약 작업을 모니터링할 수 있습니다. 이를 통해 새 바이너리나 알려지지 않은 바이너리를 실행하는 합법적인 윈도우 작업을 감시할 수 있습니다.

악성 코드 분석

이 플러그인에는 Orion 프레임워크 내에서 기능을 구현하는 합법적인 네임 스페이스, 클래스, 루틴 등으로 구성됩니다. 이중 SolarWinds.Orion.Core.BusinessLayer.OrionImprovementBusinessLayer 클래스는 HTTP 기반 백도어를 구현합니다. SolarWinds.Orion.Core.BusinessLayer.dll은 일련번호가 0f : e9 : 73 : 75 : 20 : 22 : a6 : 06 : ad : f2 : a3 : 6e : 34 : 5d : c0 : 인 인증서를 사용하여 SolarWinds에 의해 서명됩니다. 예제 파일은 2020년 3월 24일에 서명된 것입니다.

샘플 파일의 경우 SolarWinds.Orion.Core.BusinessLayer.OrionImprovementBusinessLayer.Initialize 메소드를 실행할 때 소문자 프로세스 이름이 17291806236368054941 값으로 해시 되는지 확인합니다. 이 해시 값은 표준 FNV-1A 64 비트 해시로 계산됩니다. 이 해시는 "solarwinds.businesslayerhost"라는 프로세스와 일치합니다.

샘플 파일의 경우 어셈블리 파일시스템 쓰기 시간이 현재보다 최소 12~14일 이전인 경우만 실행됩니다. 정확한 임계 값은 무작위로 선택됩니다. 샘플을 보면 합법적인 백그라운드 작업을 통해 계속해서 임계 값을 확인함을 알 수 있습니다. 샘플의 경우 임계 값이 충족되자 583da945-62af-10e8-4902-a8f205c72b2e를 생성하여 디스크에서 SolarWinds.Orion.Core.BusinessLayer.dll.config를 읽습니다. 참고로 디스크에서 appSettings. appSettings 필드의 키는 악성 로직이 영구 구성으로 다시 사용하는 합법적인 값입니다.

샘플의 경우 컴퓨터가 도메인에 가입되어 있는지 확인하고 실행을 계속하기 전에 도메인 이름을 검색합니다. 사용자 ID는 루프백 장치가 아닌 네트워크 인터페이스 MAC 주소의 MD5, 도메인 이름 및 레지스트리 HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Cryptography \ MachineGuid를 계산하여 생성합니다. 사용자 ID는 MD5 계산 후 사용자 지정 XOR 체계로 인코딩됩니다. 그런 다음 AppSettings의 ReportWatcherPostpone 키를 SolarWinds.Orion.Core.BusinessLayer.dll.config에서 읽어 합법적인 초기 값을 검색합니다. 비트 플래그를 읽으려면 초기 값을 알아야 합니다. 초기 값을 찾은 다음 핵심 이벤트 루프인 Update 메소드를 호출합니다.

벡도어는 C2 서버를 결정하기 위해 DAG(Domain Generation Algorithm)를 사용합니다. Update 메소드는 임의의 C3 하위 도메인을 생성하기 위해 암호화 헬퍼를 초기화합니다. 하위 도메인의 피해자 사용자 ID를 피해자 로컬 시스템 도메인 이름의 가역적 인코딩과 연결해 생성합니다. 공격자는 DGA 하위 도메인을 활용해 맬웨어가 방어자의 표적이 되지 않도록 DNS 응답을 변경합니다. 하위 도메인은 다음 중 하나와 연결되어 호스트 이름을 만듭니다.

  • .appsync-api.eu-west-1[.]avsvmcloud[.]com
  • .appsync-api.us-west-2[.]avsvmcloud[.]com
  • .appsync-api.us-east-1[.]avsvmcloud[.]com
  • .appsync-api.us-east-2[.]avsvmcloud[.]com

프로세스 이름, 서비스 이름 및 드라이버 경로 목록을 얻고 각 값은 이전에 설명한 바와 같이 FNV-1a + XOR 알고리즘으로 해시 되고 하드 코딩된 차단 목록과 비교 확인을 합니다. 해시 중 일부는 분석 도구 및 바이러스 백신 엔진 구성 요소를 검색합니다. 차단 목록에 있는 프로세스가 발견되면 업데이트 루틴이 종료되고 차단 목록을 통과할 때까지 루틴 실행을 계속 시도합니다. 차단 목록에 있는 서비스는 해당 HKLM \ SYSTEM \ CurrentControlSet \ services \ <service_name> \ Start 레지스트리 항목을 사용하지 않도록 값 4로 설정하여 중지됩니다. 시스템에 있는 경우 서비스 목록의 일부 항목은 생성된 값과 관련하여 DGA 알고리즘 동작에 영향을 미칠 수 있습니다. 중지된 서비스 목록은 appSettings 항목의 ReportWatcherPostpone 키에 비트로 압축됩니다. 서비스가 비활성화된 상태로 전환된 경우 Update 메소드가 종료되고 나중에 다시 시도합니다.

샘플의 경우 WIM 쿼리 WMI 쿼리 Select * From Win32_SystemDriver를 통해 드라이버 목록을 검색합니다. 차단 목록에 있는 드라이버가 표시되면 Update 메소드가 종료되고 다시 시도됩니다. 모든 차단 목록 테스트를 통과하면 샘플은 api.solarwinds.com을 확인하여 네트워크 연결을 테스트합니다.

네트워크 명령 제어 (C2)

모든 차단 목록 및 연결 확인을 통과하면 DGA를 통해 While 루프에서 도메인 생성을 시작합니다. 이 간격은 1~3분, 30~102분, 최대 420~540분(9시간)의 오류 조건에서의 임의의 값이 될 수 있습니다. 생성된 도메인의 DNS A 레코드는 악성 코드의 동작을 제어하는 하드 코딩된 IP 주소 블록 목록과 비교하여 확인됩니다. 다음 범위 내의 레코드는 맬웨어를 종료하고 구성 키 ReportWatcherRetry의 추가 실행을 방지하는 값으로 업데이트합니다.

  • 10.0.0.0/8
  • 172.16.0.0/12
  • 192.168.0.0/16
  • 224.0.0.0/3
  • fc00:: - fe00::
  • fec0:: - ffc0::
  • ff00:: - ff00::
  • 20.140.0.0/15
  • 96.31.172.0/24
  • 131.228.12.0/22
  • 144.86.226.0/24

CNAME DNS 응답에서 도메인이 성공적으로 검색되면 모든 C2 통신 및 디스패치를 담당하는 HttpHelper.Initialize 메소드를 호출하는 새 실행 스레드를 생성합니다. HTTP 스레드는 SetTime 명령으로 제어되는 구성 가능한 시간 동안 지연되며 최소 1분 동안 지연됩니다. 악성 코드는 HTTP GET 또는 HTTP POST 요청을 사용합니다. 아웃 바운드 데이터를 보내려고 하는 경우 컨텐츠 유형 HTTP 헤더는 HttpHelper.Initialize"application / octet-stream"으로 설정되고 그렇지 않으면 "application / json"으로 설정됩니다.

JSON 페이로드는 모든 HTTP POST 및 PUT 요청에 존재하며 "userId", "sessionId"및 "steps"키를 포함합니다. “steps” 필드에는“Timestamp”,“Index”,“EventType”,“EventName”,“DurationMs”,“Succeeded”및“Message” 키가 있는 개체 목록이 포함됩니다. JSON 키 “EventType”은 “Orion ”값으로 하드 코딩되고“EventName”은 “EventManager”로 하드 코딩됩니다. 서버로 보낼 맬웨어 응답 메시지는 DEFLATE 압축 및 1 바이트 XOR 인코딩 된 다음 "steps" 배열의 "Message" 필드로 분할됩니다. 각 "Message" 값은 별도로 Base64로 인코딩됩니다. "steps" 배열의 모든 개체가 맬웨어 메시지에 기여하는 것은 아닙니다. "Timestamp" 필드의 정수는 "Message" 필드의 내용이 맬웨어 메시지에 사용됨을 나타 내기 위해 0x2 비트를 설정해야 합니다.

HTTP 응답 본문은 .NET 어셈블리와 관련된 무해한 XML처럼 보이지만 실제로는 명령 데이터가 많은 GUID 및 HEX 문자열에 분산되어 있습니다. 다음 정규식을 사용하여 HEX 문자열을 검색하여 HTTP 응답 본문에서 명령을 추출합니다. "\ {[0-9a-f-] {36} \}"| "[0-9a-f] {32}"| " [0-9a-f] {16} " 명령 데이터는 GUID 및 HEX 문자열로 가장한 여러 문자열에 분산됩니다. 응답에서 일치하는 모든 하위 문자열은 HEX가 아닌 문자에 대해 필터링 되고 함께 결합되고 HEX로 디코딩 됩니다. 첫 번째 DWORD 값은 메시지의 실제 크기를 표시하고 그 뒤에는 선택적인 추가 정크 바이트가 뒤따르는 메시지가 바로 뒤에 표시됩니다. 추출된 메시는 메시지의 첫 번째 바이트를 사용하여 1 바이트 XOR 디코딩 됩니다. 그러면 DEFLATE가 압축 해제됩니다. 첫 번째 문자는 공백 문자로 구분된 선택적 추가 명령 인수와 함께 JobEngine 열거 형에 매핑되는 ASCII 정수입니다. 그런 다음 명령은 다음에 설명된 대로 명령 값을 기반으로 JobExecutionEngine으로 디스패치됩니다.

Supported Commands

명령

동작

Idle

0

작동하지 않음

Exit

1

현재 스레드를 종료합니다.

SetTime

2

메인 이벤트 루프 실행 사이의 시간을 설정합니다.

CollectSystemDescription

3

호스트 이름, 사용자 이름, 운영체제 버전, MAC 주소, IP 주소, DHCP 구성 및 도메인 정보를 포함하여 로컬 시스템을 프로파일링 합니다.

UploadSystemDescription

4

지정된 URL에 대한 HTTP 요청을 수행하고 구문을 분석하고 알 수 없는 해시 값과 구성 요소를 비교한 다음 보고서를 C2 서버로 보냅니다.

RunTask

5

주어진 파일 경로와 인수로 새 프로세스를 시작합니다.

GetProcessByDescription

6

프로세스 목록을 반환합니다. 인수가 제공되지 않으면 PID와 프로세스 이름만 반환됩니다. 인수가 제공되면 프로세스 소유자의 부모 PID와 사용자 이름 및 도메인도 반환됩니다.

 

KillTask

7

PID로 주어진 프로세스를 종료합니다.

GetFileSystemEntries

8

경로와 선택적 일치 패턴이 주어지면 파일과 디렉토리를 반복해 나열합니다.

WriteFile

9

파일 경로와 Base64 인코딩 문자열이 주어지면 Base64 인코딩 문자열의 내용을 주어진 파일 경로에 씁니다. 추가 모드를 사용하며 쓰며 완료 후 [1s, 2s] 동안 지연됩니다.

FileExists

10

주어진 파일 경로가 존재하는지 테스트합니다.

DeleteFile

11

지정된 파일 경로를 삭제합니다.

GetFileHash

12

주어진 경로에서 파일의 MD5를 계산하고 결과를 HEX 문자열로 반환합니다. 인수가 제공되면 파일의 예산 MD5 해시이며, 계산된 MD5가 다른 경우 오류를 반환합니다.

 

ReadRegistryValue

13

지원되는 하이브 중 하나에서 임의 레지스트리 쓰기

SetRegistryValue

14

원되는 하이브 중 하나에서 임의 레지스트리 쓰기

DeleteRegistryValue

15

작되는 하이브 중 하나에서 임의 레지스트리 삭제

GetRegistrySubKeyAndValueNames

 

16

지정된 레지스트리 경로 아래의 하위 키 값 및 값 이름 목록을 반환합니다.

Reboot

17

시스템 재부팅을 즉시 트리거 하려고 시도합니다.

파이어아이는 이 백도어 및 위협 행위자 식별에 도움을 주기 위해 탐지 및 서명 목록을 파이어아이 깃허브 페이지를 통해 제공합니다. 서명은 Yara, IOC, Snort 형식의 혼합형입니다. 다음은 관찰된 MITER ATT&CK 기법입니다.

ID

설명

T1012

쿼리 레지스트리

T1027

난독화된 파일 또는 정보

T1057

프로세스 발견

T1070.004

파일 삭제

T1071.001

웹 프로토콜

T1071.004

애플리케이션 계층 프로토콜: DNS

T1083

파일 및 디렉토리 검색

T1105

Ingress 도구 전송

T1132.001

표준 인코딩

T1195.002

소프트웨어 공급망 손상

T1518

소프트웨어 발견

T1518.001

보안 소프트웨어 검색

T1543.003

윈도우 서비스

T1553.002

고드 서명

T1568.002

도메인 생성 알고리즘

T1569.002

서비스 실행

T1584

인프라 손상

권장 사항

현재 SolarWinds는 고객 포탈을 통해 Orion 플랫폼 릴리즈 2020.2.1 HF1을 사용하라고 안내하고 있으며 완화 조치 및 보안 강화 지침을 제공하고 있습니다. 이 릴리즈를 쓰기 전에 주의할 것이 있습니다. 최신 버전으로 업그레이드하기 전에 기존에 영향받은 장치를 보존하는 것 입니다. 이를 하지 않고 업그레이드를 하면 포렌식 증거가 사라질 수 있습니다. 더불어 시스템 내에 추가 백도어가 남을 우려도 있습니다. 만약 SolarWinds의 권장 사항을 따를 수 없을 경우 다음고 같은 완화 조치를 우선해야 합니다.

  1. 추가 조사가 수행될 때 가지 SolarWinds 서버를 격리합니다.
  2. 만약 SolarWinds 인프라가 격리되지 않을 경우 엔드포인트 연결 범위 제한, 로컬 관리자 권한이 있는 계정 제한, 서버 및 엔드포인트 인터넷 인그레스 차단 조치를 합니다.
  3. SolarWinds 서버, 인프라에 접근할 수 있는 계정의 비밀번호 변경을 고려합니다.
  4. SolarWinds 인프라 관련 승인되지 않은 수정이 있는지 네트워크 장치 구성을 검토합니다.

이상으로 SolarWinds의 Orion 정식 업데이트를 통해 숨어 들어온 트로이목마 사태를 알아보았습니다. 현재 소프트웨어로 인프라를 모니터링 및 관리하고 있다면 반드시 숙지해 보안 조치를 취하기 바랍니다.