BRICKSTORM의 재림: 기술 및 법률 분야를 노리는 은밀한 백도어와 스파이 작전
Mandiant
Google Threat Intelligence Group
해당 블로그의 원문은 2025년 9월 25일 Google Cloud 블로그(영문)에 게재되었습니다.
작성자: Sarah Yoder, John Wolfram, Ashley Pearson, Doug Bienstock, Josh Madeley, Josh Murchie, Brad Slaybaugh, Matt Lin, Geoff Carstairs, Austin Larsen
서론
Google 위협 인텔리전스 그룹(GTIG)은 BRICKSTORM 악성코드 활동을 추적하고 있으며, 이는 미국 내 피해 조직에 대한 지속적인 접근 권한을 유지하는 데 사용되고 있습니다. 2025년 3월부터 Mandiant Consulting은 법률 서비스, SaaS(Software as a Service) 제공업체, BPO(Business Process Outsourcers), 기술 기업 등 다양한 산업 분야에서 발생한 침해 사고에 대응해 왔습니다. 이러한 표적의 가치는 일반적인 스파이 임무를 넘어, 잠재적으로 제로데이 개발에 필요한 데이터를 제공하고, 다운스트림 피해자에게 더 광범위하게 접근할 수 있는 거점을 확보하는 데 기여할 수 있습니다.
이 활동은 네트워크 어플라이언스를 표적으로 삼는 제로데이 취약점 악용을 포함하여 정교한 역량을 사용하는 UNC5221 및 이와 밀접하게 연관된 중국 연계 의심 위협 그룹의 소행으로 보고 있습니다. UNC5221이 외부에 Silk Typhoon으로 알려진 그룹과 동일시되어 사용되기도 했으나, GTIG는 현재 두 그룹을 동일한 그룹으로 간주하지 않습니다.
이러한 침입은 기존의 EDR(Endpoint Detection and Response) 도구를 지원하지 않는 어플라이언스에 백도어를 배포함으로써 장기적이고 은밀한 접근을 유지하는 데 특별히 중점을 둡니다. 이 공격자는 보안 원격 측정(telemetry) 데이터를 거의 또는 전혀 생성하지 않는 측면 이동 및 데이터 탈취 방식을 사용합니다. 이러한 방식은 BRICKSTORM 백도어의 수정 사항과 결합되어, 공격자가 피해자 환경에서 평균 393일 동안 탐지되지 않은 상태로 유지될 수 있도록 했습니다. Mandiant는 조직들이 어플라이언스에 대한 위협 모델을 재평가하고, 이처럼 고도로 회피적인 공격자를 찾기 위한 헌팅(Hunt) 활동을 수행할 것을 강력하게 권고합니다. 당사는 BRICKSTORM 관련 침입에 대한 업데이트된 위협 행위자 라이프사이클과 더불어, 조직이 이러한 활동을 탐지하고 스스로를 보호하기 위해 취해야 할 구체적이고 실행 가능한 조치를 공유하고 있습니다.


그림 1: BRICKSTORM 표적
위협 행위자 라이프사이클 (Threat Actor Lifecycle)
BRICKSTORM 배후의 공격자는 지속적인 접근 권한을 유지하고 기존 보안 도구의 가시성을 최소화하기 위해 정교한 기술을 사용합니다. 다음 내용은 Mandiant의 다수 조사에서 관찰된 기법들을 고객 정보 없이 정리한 것입니다.
초기 접근 (Initial Access)
Mandiant가 BRICKSTORM 침입을 조사하면서 일관되게 겪는 어려움은 최초 침입 경로를 파악하는 것입니다. 평균 393일에 달하는 긴 은신 기간(dwell time)으로 인해, 많은 경우 로그 보존 기간이 초과되어 초기 침입 흔적이 남아있지 않았습니다.
-
가용한 증거의 패턴은 공격자가 경계 및 원격 접근 인프라를 침해하는 데 집중하고 있음을 보여줍니다.
-
적어도 한 건의 사례에서 공격자는 제로데이 취약점 악용을 통해 접근 권한을 획득했습니다.
-
이전에 발표된 블로그 게시물(2025년 4월)에서 언급했듯이, Mandiant는 공격자가 침입 흔적을 감추기 위해 광범위한 안티 포렌식 기능이 포함된 사후 악용(Post-exploitation) 스크립트를 사용한 증거를 확인했습니다.
거점 확보 (Establish Foothold)
이 공격자가 사용하는 주요 백도어는 앞서 논의된 BRICKSTORM입니다.
-
BRICKSTORM은 SOCKS 프록시 기능을 포함하고 있으며, Go 언어로 작성되어 폭넓은 크로스 플랫폼을 지원합니다. 이는 공격자가 기존의 EDR 도구를 지원하지 않는 어플라이언스 플랫폼에 백도어를 배포하는 것을 선호하기 때문에 필수적입니다.
-
Mandiant는 다양한 제조업체의 Linux 및 BSD 기반 어플라이언스에서 BRICKSTORM의 증거를 발견했습니다. (BRICKSTORM의 Windows 변종에 대한 증거가 있지만, Mandiant의 조사에서는 관찰되지 않았습니다.)
-
어플라이언스는 흔히 인벤토리에 제대로 포함되지 않거나, 보안팀의 모니터링 대상에서 제외되거나, 중앙 집중식 보안 로깅 솔루션에서 누락되는 경우가 많습니다.
-
BRICKSTORM은 다양한 어플라이언스 유형에서 발견되었지만, UNC5221은 일관되게 VMware vCenter 및 ESXi 호스트를 표적으로 삼습니다.
-
공격자는 네트워크 어플라이언스에 BRICKSTORM을 배포한 후, 네트워크 어플라이언스에서 탈취했을 가능성이 높은 유효한 자격 증명을 사용하여 환경 내 vCenter 서버로 측면 이동했습니다.
여러 피해 조직에서 복구된 샘플을 분석한 결과, BRICKSTORM이 활발하게 개발되고 있다는 증거가 발견되었습니다. 핵심 기능은 유지되었지만, 일부 샘플은 Garble을 사용해 난독화되었고, 일부는 맞춤형 wssoft 라이브러리의 새 버전을 포함하고 있었습니다. Mandiant가 복구한 BRICKSTORM 샘플 중 하나에는 "지연 타이머(delay timer)"가 내장되어 있어, 설정된 명령 및 제어(C2) 도메인으로 비콘 통신을 시작하기까지 몇 달 후의 특정 날짜까지 기다리도록 되어 있었습니다. 특히, 이 백도어는 피해 조직이 침해 사고 대응(IR) 조사를 시작한 이후에 내부 vCenter 서버에 배포되었습니다. 이는 공격자가 상황을 적극적으로 모니터링하고 있었으며, 지속성을 유지하기 위해 전술을 신속하게 조정할 수 있음을 보여줍니다.
이전에 보고된 바와 같이, BRICKSTORM 배포는 대상 어플라이언스에 잘 섞여 들어가도록 설계되어 파일 이름 규칙과 심지어 샘플의 기능까지도 합법적인 활동으로 위장하도록 만들어졌습니다. Mandiant는 C2(명령 및 제어) 통신에 Cloudflare Workers 및 Heroku 애플리케이션을 사용하거나, C2 IP 주소로 직접 연결되는 sslip.io 또는 nip.io를 사용하는 샘플을 확인했습니다. 당사가 복구한 샘플 세트에서는 피해자 간 C2 도메인의 재사용은 전혀 없었습니다.
권한 상승 (Escalate Privileges)
한 조사에서 Mandiant는 vCenter 서버를 분석한 결과, 공격자가 vCenter 웹 인터페이스를 실행하는 Apache Tomcat 서버에 악성 Java Servlet 필터를 설치했음을 발견했습니다.
-
BRICKSTEAL: 이 악성 필터는 Mandiant에서 BRICKSTEAL로 추적하고 있으며, vCenter 웹 로그인 URI인
/web/saml2/sso/*
로 전송되는 HTTP 요청에서 실행됩니다. 이 필터는 HTTP Basic 인증 헤더를 디코딩하여 사용자 이름과 암호를 캡처할 수 있습니다. -
높은 권한 탈취: 많은 조직이 vCenter에 Active Directory 인증을 사용하므로, BRICKSTEAL은 이러한 자격 증명을 캡처할 수 있습니다. vCenter에 로그인하는 사용자는 엔터프라이즈 전체에서 높은 수준의 권한을 가질 가능성이 높습니다.
-
완화 조치: 이 시나리오에서 BRICKSTEAL이 유효한 자격 증명을 캡처하는 능력을 완화하기 위한 조치로, 이전에 공유된 vSphere 강화 지침에는 다중 요소 인증(MFA) 의무화가 포함되어 있습니다.
-
VMware vCenter는 vSphere 가상화 플랫폼의 관리 계층 역할을 수행하며 VM 생성, 스냅샷, 복제와 같은 작업을 수행할 수 있기 때문에 위협 공격자에게 매력적인 표적입니다. 적어도 두 건의 사례에서 공격자는 vCenter에 대한 접근 권한을 사용하여 도메인 컨트롤러(Domain Controllers), SSO 자격 증명 공급자(SSO Identity Providers), 비밀 저장소(secret vaults)와 같은 주요 시스템의 Windows Server VM을 복제했습니다. 이는 다른 위협 공격자들도 사용해 온 기법입니다. 공격자는 가상 머신 복제본을 통해 파일 시스템을 마운트하고 Active Directory 도메인 서비스 데이터베이스(ntds.dit
)와 같이 관심 있는 파일을 추출할 수 있습니다. 이러한 Windows 서버에는 보안 도구가 설치되어 있을 가능성이 높지만, 공격자는 복제본을 절대 전원을 켜지 않기 때문에 보안 도구가 실행되지 않습니다. 다음 예시는 위협 공격자가 로컬 vSphere 관리자 계정을 사용하여 VM을 복제한 vCenter VPXD 로그를 보여줍니다.
2025-04-01 03:37:40 [vim.event.TaskEvent] [info] [VSPHERE.LOCAL\Administrator] [<vCenter inventory object>] [<unique identifier>] [Task: VirtualMachine.clone]
2025-04-01 03:37:49 [vim.event.VmBeingClonedEvent] [info] [VSPHERE.LOCAL\Administrator] [<vCenter inventory object>] [<same unique identifier>] [Cloning DC01 on esxi01, in <vCenter inventory object> to DC01-clone on esxi02, in <vCenter inventory object>]
2025-04-01 03:42:07 [vim.event.VmClonedEvent] [info] [VSPHERE.LOCAL\Administrator] [<vCenter inventory object>] [<unique identifier>] [DC01 cloned to DC01-clone on esxi02, in <vCenter inventory object>]
2025-04-01 04:05:40 [vim.event.TaskEvent] [info] [VSPHERE.LOCAL\Administrator] [<vCenter inventory object>] [<unique identifier>] [Task: VirtualMachine.destroy]
2025-04-01 04:05:47 [vim.event.VmRemovedEvent] [info] [VSPHERE.LOCAL\Administrator] [<vCenter inventory object>] [<unique identifier>] [Removed DC01-Clone on esxi02 from <vCenter inventory object>]
한 사례에서, 위협 행위자는 합법적인 서버 관리자 자격 증명을 사용하여 Delinea(구 Thycotic) Secret Server가 실행 중인 시스템으로 반복적으로 측면 이동했습니다. 해당 시스템에서 복구된 포렌식 아티팩트는 Secret Server 애플리케이션에 저장된 모든 자격 증명을 자동으로 추출하고 복호화하는 시크릿 스틸러(secret stealer)와 같은 도구의 실행과 일치했습니다.
측면 이동 (Move Laterally)
일반적으로 BRICKSTORM의 인스턴스 중 적어도 하나가 주요 수동 조작 활동(hands-on keyboard activity)의 근원지가 되며, 두 개 이상의 침해된 어플라이언스가 백업 역할을 수행했습니다. BRICKSTORM을 설치하기 위해 공격자는 합법적인 자격 증명을 사용하여 어플라이언스에 연결했는데, 주로 SSH를 이용했습니다. 한 사례에서는 이전에 접근했던 암호 보관소에 저장되어 있는 것으로 알려진 자격 증명을 사용했습니다. 또 다른 사례에서는 위협 행위자가 이전에 열람했던 PowerShell 스크립트에 저장되어 있는 것으로 알려진 자격 증명을 사용했습니다. 여러 사례에서 공격자는 SSH 서비스에 연결하고 BRICKSTORM을 설치할 수 있도록 ESXi 웹 기반 UI 또는 vCenter Appliance Management Interface (VAMI) 중 하나에 로그인하여 SSH 서비스를 활성화했습니다. 다음은 위협 행위자가 VAMI에 연결하여 vCenter의 SSH 설정을 변경하는 것을 보여주는 VAMI 접근 이벤트의 예시입니다.
::ffff:<Source IP> <vCenter IP>:5480 - [<timestamp>] "GET / HTTP/1.1" 200 1153 "-" "<User Agent>"
::ffff:<Source IP> <vCenter IP>:5480 - [<timestamp>] "POST /rest/com/vmware/cis/session HTTP/1.1" 200 60 "https://10.0.0.255:5480/" "<User Agent>"
::ffff:<Source IP> <vCenter IP>:5480 - [<timestamp>] "PUT /rest/appliance/access/ssh HTTP/1.1" 200 0 "https://10.0.0.255:5480/" "<User Agent>"
지속성 확보 (Establish Persistence)
위협 행위자는 피해자 환경에 대한 접근을 유지하기 위해, 어플라이언스 재부팅 시에도 BRICKSTORM이 시작되도록 init.d
, rc.local
또는 systemd
파일을 수정했습니다. 여러 사례에서 공격자는 합법적인 시작 스크립트를 수정하여 BRICKSTORM을 실행하기 위해 sed 명령어 라인 유틸리티를 사용했습니다. 다음은 공격자가 vCenter에서 실행한 몇 가지 sed
명령어의 예시입니다.
sed -i s/export TEXTDOMAIN=vami-lighttp/export TEXTDOMAIN=vami-lighttp\n\/path/to/brickstorm/g /opt/vmware/etc/init.d/vami-lighttp
sed -i $a\SETCOLOR_WARNING="echo -en `/path/to/brickstorm`\\033[0;33m" /etc/sysconfig/init
위협 행위자는 또한 vCenter 서버에 Mandiant가 SLAYSTYLE로 추적하는 웹 셸을 생성했습니다. SLAYSTYLE은 MITRE에서 BEEFLUSH로 추적하는 JSP(JavaServer Pages) 웹 셸로, 백도어 역할을 합니다. 이는 HTTP 요청을 통해 전달된 임의의 운영 체제 명령을 수신하고 실행하도록 설계되었으며, 이 명령의 출력은 HTTP 응답 본문에 반환됩니다.
임무 완수 (Complete Mission)
조사 전반에 걸쳐 공통된 주제는 위협 행위자가 피해 조직 내 핵심 인물의 이메일에 관심을 보였다는 것입니다. 표적 계정의 이메일 사서함에 접근하기 위해, 위협 행위자는 mail.read
또는 full_access_as_app
범위를 가진 Microsoft Entra ID 엔터프라이즈 애플리케이션을 활용했습니다. 두 범위 모두 애플리케이션이 모든 사서함의 메일에 접근할 수 있도록 허용합니다. 어떤 경우에는 개발자와 시스템 관리자의 사서함을 표적으로 삼았으며, 다른 경우에는 PRC(중화인민공화국)의 경제 및 첩보 이익과 관련된 문제에 관여하는 개인의 사서함을 표적으로 삼았습니다.
위협 행위자가 피해 환경에서 파일을 외부로 반출(exfiltrated)할 때, 그들은 BRICKSTORM의 SOCKS 프록시 기능을 사용하여 자신의 워크스테이션을 터널링하고 관심 있는 시스템과 웹 애플리케이션에 직접 접근했습니다. 여러 사례에서 위협 행위자는 합법적인 자격 증명을 사용하여 내부 코드 저장소 및 다운로드 저장소의 웹 인터페이스에 로그인하고 이를 ZIP 아카이브 형태로 다운로드했습니다. 다른 사례에서는 위협 행위자가 Windows UNC(Universal Naming Convention) 경로를 지정하여 원격 머신의 특정 디렉터리 및 파일로 이동했습니다.
일부 사례에서 위협 행위자가 배포한 BRICKSTORM 샘플은 침해된 시스템에서 제거되었습니다. 이러한 경우, 백업 이미지에 대한 포렌식 분석을 수행하여 BRICKSTORM 악성 코드가 제자리에 있었던 것을 식별함으로써 BRICKSTORM의 존재가 관찰되었습니다.
헌팅 가이드 (Hunting Guidance)
Mandiant는 이전에 원자적 IOC(atomic IOC)의 유용성이 감소하고 TTP(전술, 기술 및 절차) 기반 헌팅을 채택할 필요성에 대해 논의한 바 있습니다. BRICKSTORM 관련 조사 전반에 걸쳐 C2 도메인이나 악성코드 샘플의 재사용이 관찰되지 않았으며, 이는 높은 운영 보안과 결합되어 이러한 지표들이 빠르게 만료되거나 아예 관찰되지 않는다는 것을 의미합니다. 따라서 TTP 기반 헌팅 접근 방식은 이상적인 관행일 뿐만 아니라, 전통적인 시그니처 기반 방어 체계로는 탐지될 가능성이 낮은 공격 패턴을 탐지하기 위한 필수적인 요소입니다. 다음은 Mandiant가 조직에게 BRICKSTORM 및 관련 활동을 탐색하기 위해 권장하는 최소한의 헌팅 체크리스트입니다.
자산 목록 생성 또는 업데이트
모든 위협 헌팅의 성공을 위한 기본 요소는 엣지 디바이스 및 기타 어플라이언스와 같이 표준 보안 도구 스택이 적용되지 않는 디바이스를 포함하는 자산 목록입니다. 이러한 어플라이언스들은 기존 보안 도구의 지원을 받지 못하기 때문에, 효과적인 보완 통제 및 탐지 개발을 위해서는 목록이 매우 중요합니다. 특히, 악성코드 및 위협 행위자 명령이 외부로 나가는 기본 게이트웨이 역할을 하는 이들 어플라이언스의 관리 인터페이스 주소를 추적하는 것이 중요합니다.
Mandiant는 조직이 이 목록을 구축하거나 업데이트하기 위해 다음과 같은 다단계 접근 방식을 취할 것을 권장합니다.
-
알려진 것: 모든 조직이 사용하는 어플라이언스 유형부터 시작하십시오. 방화벽, VPN 집중기, 가상화 플랫폼, 컨퍼런싱 시스템, 배지(출입 통제 시스템) 및 파일 저장소 등이 있습니다.
-
알려지지 않은 것: 여러 팀과 협력하여 조직에 더 특화되어 있지만, 보안 부서가 가시성을 확보하지 못했을 가능성이 있는 어플라이언스 유형을 브레인스토밍하십시오.
-
알려지지 않은 미지수: 이들은 폐기되었어야 했지만 그렇지 않은 어플라이언스, 판매 시점 시연(Sales POV) 장치 등입니다. 네트워크 가시성 도구 또는 기존 EDR을 사용하여 EDR 보고서에 표시되지 않는 "활성" IP 주소를 스캔하는 것을 고려해 보십시오. 이는 EDR이 설치되어야 하지만 설치되지 않은 관리되지 않는 디바이스를 식별하는 추가적인 이점도 제공합니다.


그림 2: 자산 목록
BRICKSTORM에 대한 파일 및 백업 검사
YARA 규칙은 어플라이언스에서 BRICKSTORM 바이너리를 탐지하는 데 가장 효과적인 방법으로 입증되었습니다. 이 게시물의 부록 섹션에서 관련 YARA 규칙을 공유하고 있습니다. YARA는 대규모로 실행하기 어려울 수 있지만, 일부 백업 솔루션은 백업 데이터 저장소 전체에서 YARA를 실행할 수 있는 기능을 제공합니다. Mandiant는 이 방법을 통해 BRICKSTORM을 식별한 다수의 고객 사례를 알고 있습니다.
Mandiant는 조직이 환경에서 BRICKSTORM 활동을 헌팅하는 것을 돕기 위해, 어플라이언스 및 기타 Linux 또는 BSD 기반 시스템에서 실행할 수 있는 스캐너 스크립트를 배포했습니다.
엣지 디바이스 및 어플라이언스에서 발생하는 인터넷 트래픽
어플라이언스 관리 IP 주소의 목록을 사용하여 네트워크 로그에서 악성코드 비콘(beaconing) 증거를 헌팅하십시오. 일반적으로 어플라이언스는 업데이트를 다운로드하고 제조사에 크래시 분석 데이터를 전송하는 경우를 제외하고 관리 IP 주소에서 공용 인터넷과 통신해서는 안 됩니다.
어플라이언스 제조사가 통제하지 않는 도메인 또는 IP 주소로 설정된 아웃바운드 트래픽은 매우 의심스러우며 어플라이언스에 대한 포렌식 검토가 필요합니다. BRICKSTORM은 DNS over HTTP(DoH)를 사용할 수 있으며, 이 또한 어플라이언스 관리 IP 주소에서 발생할 경우 드물게 나타나야 합니다.
어플라이언스에서 Windows 시스템으로의 접근
위협 행위자는 주로 유형 3(네트워크) 로그인을 사용하여 Windows 머신(데스크톱 및 서버 모두)에 접근했지만, 일부 사례에서는 RDP 세션도 설정했습니다. 어플라이언스가 Windows 데스크톱이나 서버에 로그인하는 경우는 극히 드물어야 하며, 모든 연결은 의심스럽게 처리되어야 합니다. 오탐(False Positives)의 몇 가지 예로는 LDAP 조회를 수행하기 위해 알려진 서비스 계정을 사용하여 도메인 컨트롤러에 연결하는 VPN 어플라이언스나, 잘 알려진 서비스 계정을 사용하는 인증된 취약점 스캐너가 포함될 수 있습니다.
EDR 텔레메트리, 터미널 서비스 로그 및 보안 이벤트 로그 외에도, 방어자는 Windows User Access Log (UAL)를 확보하고 파싱해야 합니다. UAL은 Windows 서버의 Windows\System32\LogFiles\Sum
디렉토리에 저장되며, SumECmd
와 같은 오픈 소스 도구를 사용하여 파싱할 수 있습니다. 이 로그 소스는 Windows 시스템에 대한 인증 시도 연결을 기록하며, 종종 일반적인 Windows 이벤트 로그보다 훨씬 더 오래된 아티팩트를 보존합니다. 이 로그 소스는 성공 및 실패한 로그인을 모두 포함하지만, 어플라이언스에서 발생한 의심스러운 활동을 식별하는 데 여전히 유용합니다.
자격 증명 및 시크릿(Secrets)에 대한 접근
Use the forensic capabilities of EDR tools to acquire Windows Shellbags artifacts from Windows workstations and servers. Shellbags records folder paths that are browsed by a user with the Windows Explorer application. Use an open-source parser to extract the relevant data and look for patterns of activity that are suspicious:
EDR 도구의 포렌식 기능을 사용하여 Windows 워크스테이션 및 서버에서 Windows Shellbags 아티팩트를 수집하십시오. Shellbags는 사용자가 Windows 탐색기 애플리케이션으로 탐색한 폴더 경로를 기록합니다. 오픈 소스 파서를 사용하여 관련 데이터를 추출하고, 다음과 같은 의심스러운 활동 패턴을 찾으십시오.
-
시작 사용자가 서비스 계정인 폴더 경로에 대한 접근, 특히 익숙하지 않거나 거의 사용되지 않는 서비스 계정
-
워크스테이션을 가리키는 Windows UNC(Universal Naming Convention) 경로를 포함하는 서버에서 발생한 파일 탐색 활동 (예:
\\bobwin7.corp.local\browsing\path
) -
다음과 같은 자격 증명 데이터를 포함하는 폴더 경로로의 파일 탐색 활동
-
브라우저 프로필 경로 (예:
%appdata%\Mozilla\Firefox\Profiles
) -
세션 토큰 저장에 사용되는 Appdata 위치 (예:
Users\<username>\.azure\
) -
Windows 자격 증명 저장소 (
%appdatalocal%\Microsoft\Credentials
) -
Data Protection API (DPAPI) 키 (
%appdata%\Microsoft\Protect\<SID>\
)
-
엔터프라이즈 애플리케이션을 사용한 M365 사서함 접근
Mandiant는 이 공격자가 Microsoft 365 Exchange Online에서 대량의 이메일 접근 및 외부 반출을 수행하기 위해 일반적인 기술을 사용하는 것을 관찰했습니다. 조직은 이러한 기술을 헌팅하기 위해 APT29 백서에 요약된 당사의 지침을 따라야 합니다. 해당 백서가 구체적으로 APT29를 언급하고 있지만, 이 기술들은 이제 많은 그룹에서 널리 사용되고 있습니다. 여러 조사에서 위협 행위자는 피해 조직 내 핵심 인물의 사서함에 접근하기 위해 mail.read
또는 full_access_as_app
범위를 가진 Microsoft Entra ID 엔터프라이즈 애플리케이션을 사용했습니다.
이러한 활동을 헌팅하기 위해, 당사는 단계별 접근 방식을 권장합니다.
-
모든 메일을 읽을 수 있는 그래프 권한을 가진 엔터프라이즈 애플리케이션 및 애플리케이션 등록을 열거합니다.
-
각 애플리케이션에 대해 최소한 하나의 시크릿(secret) 또는 인증서가 구성되어 있는지 확인합니다. 애플리케이션 (클라이언트) ID를 기록합니다.
-
2단계의 클라이언트 ID에 대해 통합 감사 로그(Unified Audit Log) 또는 Sentinel의
OfficeActivity
테이블을 대상으로 자유 텍스트 검색을 수행합니다. 이는 애플리케이션이 메일에 접근한 것을 기록한mailitemsaccessed
이벤트를 반환합니다. -
각 애플리케이션에 대해 소스 IP 주소와 사용자 에이전트 문자열의 불일치를 분석합니다. 애플리케이션의 합법적인 사용은 잘 정의된 IP 주소에서 발생해야 합니다. 또한, 여러 날에 걸친 핵심 인물 사서함에 대한 집중적인 관심을 찾으십시오.
M365 및 기타 인터넷 연결 서비스에 접근할 때, 이 공격자는 여러 상업용 VPN 및 프록시 공급자를 사용했습니다. Mandiant는 위협 행위자가 PIA, NordVPN, Surfshark, VPN Unlimited, PrivadoVPN을 사용한 증거를 발견했지만, 이것이 사용된 유일한 솔루션일 이유는 없습니다. 또한, 이 공격자가 침해된 소규모 사무실/가정 사무실(SOHO) 라우터로 구축된 맞춤형 난독화 네트워크에 접근했다는 것을 뒷받침하는 증거도 있습니다. Mandiant는 이러한 라우터가 어떻게 침해되었는지에 대해서는 알지 못합니다. 상업용 VPN 및 난독화 네트워크의 출구 노드는 빠르게 변경되므로, 헌팅 목적으로 원자적 지표(atomic indicators)를 공유하는 것은 결과를 산출할 가능성이 낮습니다. 대신, 조직의 분야(vertical)와 위협 행위자의 예상 목표를 고려하여 조직 내 핵심 인물을 식별하십시오. 해당 사서함에 대한 mailitemsaccessed
로그를 지난 1년 동안 또는 보존 기간이 허용하는 한 최대한 가져옵니다. 로그 이벤트의 SessionID
값을 분석하고, IP 주소가 사용자의 일반적인 지리적 위치에 있지 않은 다수의 IP 주소에 걸쳐 있는 ID를 찾으십시오.
민감한 가상 머신(VM) 복제
VMware vCenter 서버에서 VPXD 로그는 복제 이벤트, VM 전원 켜기 및 끄기, 스냅샷 생성과 같은 VM 관리 관련 작업에 대한 귀중한 정보를 포함합니다. 위협 행위자는 VM을 복제할 때 종종 VSPHERE.LOCAL\Administrator
계정을 사용했으며, 암호 저장소 및 도메인 컨트롤러와 같은 자격 증명을 포함할 수 있는 VM을 표적으로 삼았습니다. 위협 행위자는 복제 직후 복제된 VM을 삭제했으며, 주로 UTC 기준 01:00부터 10:00 사이에 활동했습니다. 조사관은 vCenter VPXD 로그에서 앞서 언급된 기준과 일치하는 활동을 검색하고 해당 복제 활동이 의도된 것이었는지 여부를 확인해야 합니다.
로컬 vCenter 및 ESXi 계정 생성
Mandiant는 위협 행위자가 BRICKSTORM을 설치하기 위해 새로운 로컬 계정을 생성한 다음, 작업 완료 후 계정을 제거한 증거를 식별했습니다. 다음 로그는 위협 행위자가 로컬 Administrator 계정을 사용하여 새 로컬 계정을 생성하고 이를 BashShellAdministrators
그룹에 추가하는 것을 보여줍니다. 위협 행위자는 새로 생성된 계정을 사용하여 침해된 어플라이언스에서 vCenter로 SSH 연결을 설정하고 vCenter에 BRICKSTORM 백도어를 설치했습니다. 직후, 위협 행위자는 해당 계정을 삭제했습니다. 조사관은 /var/log/audit/sso-events/audit_events.log
에서 로컬 계정의 생성 및 삭제에 대한 감사 로그를 검토하고 그 목적을 검증해야 합니다. 한 사례에서 위협 행위자는 vCenter에서 백업에 사용되는 로컬 서비스 계정과 유사한 이름 명명 규칙으로 계정을 명명했습니다.
2025-04-01T06:45:32 {"user":"Administrator@VSPHERE.LOCAL","client":"","timestamp":"04/01/2025 06:45:32 GMT","description":"Creating local person user '<account_name>' with details ('','','','','<account_name>@vsphere.local')","eventSeverity":"INFO","type":"com.vmware.sso.PrincipalManagement"}
2025-04-01T06:45:55 {"user":"Administrator@VSPHERE.LOCAL","client":"","timestamp":"04/01/2025 06:45:55 GMT","description":"Adding users '[{Name: <account_name>, Domain: vsphere.local}]' to local group 'Administrators'","eventSeverity":"INFO","type":"com.vmware.sso.PrincipalManagement"}
2025-04-01T06:46:23 {"user":"Administrator@VSPHERE.LOCAL","client":"","timestamp":"04/01/2025 06:46:23 GMT","description":"Updating local group 'SystemConfiguration.BashShellAdministrators' details ('Access bash shell and manage local users on nodes').","eventSeverity":"INFO","type":"com.vmware.sso.PrincipalManagement"}
2025-04-01T06:52:03 <vcenter_hostname> sshd[36952]: Postponed keyboard-interactive/pam for <account_name>@vsphere.local from <compromised_system>
2025-04-01T06:52:30 <vcenter_hostname> sudo: pam_unix(sudo:session): session opened for user root
2025-04-01T06:53:39 Creation of BRICKSTORM on vCenter
2025-04-01T06:56:18 <vcenter_hostname> sudo: pam_unix(sudo:session): session closed for user root
2025-04-01T06:56:25 <vcenter_hostname> sshd[36952]: pam_unix(sshd:session): session closed for user <account_name>@vsphere.local
2025-04-01T06:56:57 {"user":"Administrator@VSPHERE.LOCAL","client":"","timestamp":"04/01/2025 06:56:57 GMT","description":"Removing principals '[{Name: <account_name>, Domain: vsphere.local}]' from local group 'Administrators'","eventSeverity":"INFO","type":"com.vmware.sso.PrincipalManagement"}
2025-04-01T06:58:12 {"user":"Administrator@VSPHERE.LOCAL","client":"","timestamp":"04/01/2025 06:58:12 GMT","description":"Deleting principal '<account_name>'","eventSeverity":"INFO","type":"com.vmware.sso.PrincipalManagement"}
ESXi 및 vCenter에서의 SSH 활성화
ESXi 서버의 경우, 로컬 계정을 사용한 SSH 로그인에 대한 모니터링을 설정해야 합니다. 대부분의 조직에서 SSH를 통한 ESXi 호스트에 대한 합법적인 직접 접근은 비교적 드뭅니다. 많은 경우 SSH 서버는 기본적으로 비활성화되어 있습니다. vSphere 플랫폼 어플라이언스에 대해 SSH가 활성화될 때 로그 이벤트에 대한 알림 규칙을 작성하십시오.
악성 VM
조직은 새로운 VM의 생성 및 삭제를 추적하는 VMWare 감사 이벤트를 검토해야 하며, 특히 비표준 ISO 이미지 및 운영 체제를 사용한 경우에 집중해야 합니다. 감사 이벤트는 또한 위협 행위자가 vSphere에서 사용하는 데이터스토어 볼륨으로 보관된 ISO 이미지를 다운로드하는 것을 기록할 수도 있습니다.
보안 강화 지침
표준 보안 도구 스택이 적용되지 않는 네트워크 내의 어플라이언스 및 기타 디바이스에 대한 최신 목록을 유지하는 것이 중요합니다. 이 목록에 있는 모든 디바이스는 내부용이든 인터넷 연결용이든 관계없이 최소 권한의 원칙을 따르도록 구성되어야 합니다.
-
인터넷 접근: 어플라이언스는 인터넷에 대한 무제한 접근을 허용해서는 안 됩니다. 공급업체와 협력하거나 방화벽 로그를 모니터링하여 어플라이언스가 올바르게 기능하는 데 필요한 도메인 또는 IP 주소로만 인터넷 접근을 제한하십시오.
-
내부 네트워크 접근: 인터넷에 노출된 어플라이언스는 내부 IP 주소 공간에 대한 무제한 접근을 허용해서는 안 됩니다. 대부분의 어플라이언스의 관리 인터페이스는 내부 IP 주소로 연결을 설정할 필요가 없습니다. 공급업체와 협력하여 VPN 로그인에 대한 사용자 속성 확인을 위한 LDAP 쿼리와 같은 특정 필요 사항을 파악하십시오
Mandiant는 이전에 위협 행위자로부터 vSphere 플랫폼을 보호하기 위한 지침을 발표했습니다. 당사는 특히 로그를 중앙 SIEM으로 전달하고, vSphere 잠금 모드(lockdown mode)를 활성화하고, 웹 로그인에 대한 MFA를 강제하며, execInstalledOnly
정책을 강제하는 등 해당 지침을 따를 것을 권장합니다.
조직은 모든 자격 증명 보관 시스템(credential vaulting systems)의 격리를 평가하고 개선해야 합니다. 많은 경우 위협 행위자가 기본 운영 체제에 접근할 수 있게 되면, 모든 보호된 시크릿이 노출될 수 있습니다. 자격 증명 보관 애플리케이션을 호스팅하는 서버는 Tier 0 시스템으로 간주되어야 하며, 엄격한 접근 통제가 적용되어야 합니다. Mandiant는 조직이 서버의 TPM(신뢰 플랫폼 모듈)에 암호화 키를 저장하는 것과 같은 보안 소프트웨어 관행을 채택하도록 공급업체와 협력할 것을 권장합니다.
전망 및 시사점
BRICKSTORM과 관련된 최근 침입 작전은 지정학적 첩보 활동, 접근 작전, 제로데이 익스플로잇 개발을 가능하게 하는 지적 재산(IP) 절도에 이르기까지 광범위한 목표를 나타낼 가능성이 높습니다. 최근 조사 증거에 따르면, 미국 법률 분야에 대한 표적화는 주로 미국 국가 안보 및 국제 무역과 관련된 정보를 수집하기 위한 것입니다. 또한, GTIG(Google Threat Intelligence Group)는 BRICKSTORM이 SaaS 공급자를 표적화하는 목적이 다운스트림 고객 환경이나 SaaS 공급자가 고객을 대신하여 호스팅하는 데이터에 접근하기 위한 것이라고 높은 확신으로 평가합니다. 기술 기업을 표적화하는 것은 가치 있는 IP를 훔쳐 제로데이 익스플로잇 개발을 발전시킬 기회를 제공합니다.
감사의 말씀
이 분석은 Google Threat Intelligence Group, Mandiant Consulting 및 FLARE 전반의 지원 없이는 불가능했을 것입니다. 저희는 특히 GTIG 연구 및 발견(RAD)의 Nick Simonian에게 감사를 표하고 싶습니다. 또한 네트워크 탐지 콘텐츠에 기여한 Mandiant 위협 방어(MTD)의 Ryan Tomcik에게도 감사드립니다.
침해 지표 (Indicators of Compromise)
다음 침해 지표는 Google Threat Intelligence (GTI) 컬렉션에서 확인할 수 있습니다. Mandiant는 위협 행위자가 악성코드 샘플을 재사용하는 사례를 관찰하지 않았으며, 정확한 지표를 헌팅하는 것은 결과를 산출할 가능성이 낮음을 유념하십시오.
YARA 탐지
G_APT_Backdoor_BRICKSTORM_3
rule G_APT_Backdoor_BRICKSTORM_3 {
meta:
author = "Google Threat Intelligence Group (GTIG)"
strings:
$str1 = { 48 8B 05 ?? ?? ?? ?? 48 89 04 24 E8 ?? ?? ?? ?? 48 B8 ?? ?? ?? ?? ?? ?? ?? ?? 48 89 04 24 [0-5] E8 ?? ?? ?? ?? EB ?? }
$str2 = "regex" ascii wide nocase
$str3 = "mime" ascii wide nocase
$str4 = "decompress" ascii wide nocase
$str5 = "MIMEHeader" ascii wide nocase
$str6 = "ResolveReference" ascii wide nocase
$str7 = "115792089210356248762697446949407573529996955224135760342422259061068512044369115792089210356248762697446949407573530086143415290314195533631308867097853951" ascii wide nocase
condition:
uint16(0) == 0x457F and all of them
}
G_Backdoor_BRICKSTORM_2
rule G_Backdoor_BRICKSTORM_2 {
meta:
author = "Google Threat Intelligence Group (GTIG)"
strings:
$obf_func = /[a-z]{20}\/[a-z]{20}\/[a-z]{20}\/[a-z]{20}.go/
$decr1 = { 0F B6 4C 04 ?? 0F B6 54 04 ?? 31 D1 88 4C 04 ?? 48 FF C0 [0-4] 48 83 F8 ?? 7C }
$decr2 = { 40 88 7C 34 34 48 FF C3 48 FF C6 48 39 D6 7D 18 0F B6 3B 48 39 CE 73 63 44 0F B6 04 30 44 31 C7 48 83 FE 04 72 DA }
$decr3 = { 0F B6 54 0C ?? 0F B6 5C 0C ?? 31 DA 88 14 08 48 FF C1 48 83 F9 ?? 7C E8 }
$str1 = "main.selfWatcher"
$str2 = "main.copyFile"
$str3 = "main.startNew"
$str4 = "WRITE_LOG=true"
$str5 = "WRITE_LOGWednesday"
$str6 = "vami-httpdvideo/webm"
$str7 = "/opt/vmware/sbin/"
$str8 = "/home/vsphere-ui/"
$str9 = "/opt/vmware/sbin/vami-http"
$str10 = "main.getVFromEnv"
condition:
uint32(0) == 0x464c457f and ((any of ($decr*) and $obf_func) or (any of ($decr*) and any of ($str*)) or 5 of ($str*)) and filesize < 10MB
}
G_APT_Backdoor_BRICKSTORM_1
rule G_APT_Backdoor_BRICKSTORM_1 {
meta:
author = "Google Threat Intelligence Group (GTIG)"
strings:
$ = "WRITE_LOGWednesday"
$ = "/home/vsphere-ui/"
$ = "WRITE_LOG=true"
$ = "dns rcode: %v"
$ = "dns query not specified or too small"
$ = "/dev/pts: bad file descriptor"
$ = "/libs/doh.Query"
$ = "/libs/doh.createDnsMessage"
$ = "/libs/doh.unpackDnsMessage"
$ = "/core/protocol/websocket.(*WebSocketNetConfig).Dial"
$ = "/core/protocol/websocket.(*connection).Read"
$ = "/core/protocol/websocket.(*connection).getReader"
$ = "/core/protocol/websocket.(*connection).Write"
$ = "/core/protocol/websocket.(*connection).Close"
$ = "/core/protocol/websocket.(*connection).LocalAddr"
$ = "/core/protocol/websocket.(*connection).RemoteAddr"
$ = "/core/protocol/websocket.(*connection).SetDeadline"
$ = "/core/protocol/websocket.(*connection).SetReadDeadline"
$ = "/core/protocol/websocket.(*connection).SetWriteDeadline"
$ = "/core/protocol.UnPackHeaderData"
$ = "/core/protocol.NewWebSocketClient"
$ = "/libs/func1.(*Client).BackgroundRun"
$ = "/libs/func1.CreateClient"
$ = "/libs/func1.NewService"
$ = "/libs/func1.(*Service).Get"
$ = "/libs/func1.(*Service).DoTask"
$ = "/libs/func1.(*Service).Put"
$ = "/core/extends/command.Command"
$ = "/core/extends/command.CommandNoContext"
$ = "/core/extends/command.ExecuteCmd"
$ = "/core/extends/command.RunShell"
$ = "/core/extends/socks.UnPackHeaderData"
$ = "/core/extends/socks.handleRelay"
$ = "/libs/fs.(*RemoteDriver).realPath"
$ = "/libs/fs.(*RemoteDriver).ChangeDir"
$ = "/libs/fs.(*RemoteDriver).Stat"
$ = "/libs/fs.(*SimplePerm).GetMode"
$ = "/libs/fs.(*SimplePerm).GetOwner"
$ = "/libs/fs.(*SimplePerm).GetGroup"
$ = "/libs/fs.(*RemoteDriver).ListDir"
$ = "/libs/fs.(*RemoteDriver).DeleteDir"
$ = "/libs/fs.(*RemoteDriver).DeleteFile"
$ = "/libs/fs.(*RemoteDriver).Rename"
$ = "/libs/fs.(*RemoteDriver).MakeDir"
$ = "/libs/fs.(*RemoteDriver).GetFile"
$ = "/libs/fs.(*RemoteDriver).PutFile"
$ = "/libs/fs.(*RemoteDriver).UpFile"
$ = "/libs/fs.(*RemoteDriver).MD5"
$ = "/libs/doh/doh.go"
$ = "/core/protocol/websocket/config.go"
$ = "/core/extends/command/command.go"
$ = "/libs/fs/driver_unix.go"
$ = "/libs/fs/perm_linux.go"
condition:
uint32(0) == 0x464c457f and 8 of them
}
G_APT_Backdoor_BRICKSTORM_2
rule G_APT_Backdoor_BRICKSTORM_2 {
meta:
author = "Google Threat Intelligence Group (GTIG)"
strings:
$str1 = { 0F 57 C0 0F 11 84 ?? ?? ?? ?? ?? C6 44 ?? ?? 00 4? C7 84 ?? ?? ?? ?? ?? 00 00 00 00 0F 57 C0 0F 11 84 ?? ?? ?? ?? ?? 0F 11 84 ?? ?? ?? ?? ?? 4? 8B 84 ?? ?? ?? ?? ?? 4? 89 04 ?? 4? 8B 8C ?? ?? ?? ?? ?? 4? 89 4C ?? ?? E8 ?? ?? ?? ?? 4? 83 7C ?? ?? 00 0F 84 ?? ?? ?? ?? 4? 8D 05 ?? ?? ?? ?? 4? 89 ?? ?? E8 ?? ?? ?? ?? 4? 8B 7C ?? ?? 4? 8B 84 ?? ?? ?? ?? ?? 4? 89 47 08 83 3D ?? ?? ?? ?? 00 75 ?? 4? 8B 84 ?? ?? ?? ?? ?? 4? 89 07 4? 89 BC ?? ?? ?? ?? ?? 4? C7 84 ?? ?? ?? ?? ?? 01 00 00 00 4? C7 84 ?? ?? ?? ?? ?? 01 00 00 00 0F 57 C0 0F 11 84 ?? ?? ?? ?? ?? 4? 8B ?? ?? ?? ?? ?? ?? 4? 81 C4 ?? ?? ?? ?? C3 }
$str2 = { 4? C7 84 ?? ?? ?? ?? ?? 00 00 00 00 4? C7 84 ?? ?? ?? ?? ?? 00 00 00 00 4? C7 84 ?? ?? ?? ?? ?? 00 00 00 00 4? C7 84 ?? ?? ?? ?? ?? 00 00 00 00 4? C7 84 ?? ?? ?? ?? ?? 00 00 00 00 4? 8B 84 ?? ?? ?? ?? ?? 4? 89 04 ?? 4? 8B 8C ?? ?? ?? ?? ?? 4? 89 4C ?? ?? E8 ?? ?? ?? ?? 4? 8B 44 ?? ?? 4? 85 C0 0F 84 ?? ?? ?? ?? 4? 8D 05 ?? ?? ?? ?? 4? 89 ?? ?? E8 ?? ?? ?? ?? 4? 8B 44 ?? ?? 4? 8B 8C ?? ?? ?? ?? ?? 4? 89 48 08 8B 0D ?? ?? ?? ?? 85 C9 75 ?? 4? 8B 8C ?? ?? ?? ?? ?? 4? 89 08 84 00 4? 89 84 ?? ?? ?? ?? ?? 4? C7 84 ?? ?? ?? ?? ?? 01 00 00 00 4? C7 84 ?? ?? ?? ?? ?? 01 00 00 00 4? C7 84 ?? ?? ?? ?? ?? 00 00 00 00 4? C7 84 ?? ?? ?? ?? ?? 00 00 00 00 90 E8 ?? ?? ?? ?? 4? 8B ?? ?4 D8 00 00 00 4? 81 C4 E0 00 00 00 C3 }
condition:
uint32be(0) == 0x7F454C46 and any of them
}
G_APT_BackdoorWebshell_SLAYSTYLE_1
rule G_APT_BackdoorWebshell_SLAYSTYLE_1 {
meta:
author = "Google Threat Intelligence Group (GTIG)"
strings:
$str1 = /String \w{1,10}=request\.getParameter\(\"\w{1,15}\"\);/ ascii wide nocase
$str2 = "=new String(java.util.Base64.getDecoder().decode(" ascii wide nocase
$str21 = /String\[\]\s\w{1,10}=\{\"\/bin\/sh\",\"-c\",\w{1,10}\+\"\s2>&1\"\};/ ascii wide nocase
$str3 = "= Runtime.getRuntime().exec(" ascii wide nocase
$str4 = "java.io.InputStream" ascii wide nocase
$str5 = "java.util.Base64.getEncoder().encodeToString(org.apache.commons.io.IOUtils.toByteArray(" ascii wide nocase
condition:
filesize < 5MB and all of them
}
G_APT_BackdoorWebshell_SLAYSTYLE_2
rule G_APT_BackdoorWebshell_SLAYSTYLE_2 {
meta:
author = "Google Threat Intelligence Group (GTIG)"
strings:
$str1 = "request.getParameter" nocase
$str2 = "/bin/sh"
$str3 = "java.io.InputStream" nocase
$str4 = "Runtime.getRuntime().exec(" nocase
$str5 = "2>&1"
condition:
(uint16(0) != 0x5A4D and uint32(0) != 0x464C457F) and filesize < 7KB and all of them and @str4 > @str2
}
G_Backdoor_BRICKSTEAL_1
rule G_Backdoor_BRICKSTEAL_1 {
meta:
author = "Google Threat Intelligence Group (GTIG)"
strings:
$str1 = "comvmware"
$str2 = "abcdABCD1234!@#$"
$str3 = "ads.png"
$str4 = "User-Agent"
$str5 = "com/vmware/"
condition:
all of them and filesize < 10KB
}
G_Dropper_BRICKSTEAL_1
rule G_Dropper_BRICKSTEAL_1 {
meta:
author = "Google Threat Intelligence Group (GTIG)"
strings:
$str1 = "Base64.getDecoder().decode"
$str2 = "Thread.currentThread().getContextClassLoader()"
$str3 = ".class.getDeclaredMethod"
$str4 = "byte[].class"
$str5 = "method.invoke"
$str6 = "filterClass.newInstance()"
$str7 = "/websso/SAML2/SSO/*"
condition:
all of them
}
G_Dropper_BRICKSTEAL_2
rule G_Dropper_BRICKSTEAL_2 {
meta:
author = "Google Threat Intelligence Group (GTIG)"
strings:
$str1 = /\(Class<\?>\)\smethod\.invoke\(\w{1,20},\s\w{1,20},\s0,\s\w{1,20}\.length\);/i ascii wide
$str2 = "(\"yv66vg" ascii wide
$str3 = "request.getSession().getServletContext" ascii wide
$str4 = ".getClass().getDeclaredField(" ascii wide
$str5 = "new FilterDef();" ascii wide
$str6 = "new FilterMap();" ascii wide
condition:
all of them
}
Network 탐지
Google SecOps 고객은 Mandiant Front-Line Threats 규칙 팩에서 이러한 광범위한 범주의 규칙과 더 많은 규칙에 접근할 수 있습니다. 다음은 Google Security Operations에서 사용할 수 있는 YARA-L 2.0 규칙이지만, 그 로직은 다른 보안 제품에서 사용하기 위해 다른 형식으로 복제될 수 있습니다.
여러 DNS-over-HTTPS 서비스 쿼리
rule hunting_t1071_001_multiple_dns_over_https_services_queried {
meta:
rule_name = "Multiple DNS-over-HTTPS Services Queried"
severity = "Low"
tactic = "TA0011" // Command and Control
technique = "T1071.001" // Application Layer Protocol: Web Protocols
reference = "https://cloud.google.com/blog/topics/threat-intelligence/brickstorm-espionage-campaign"
description = "Detects on requests by a source IP address to DNS-over-HTTPS (DoH) resolver IP addresses associated with multiple services, such as Quad9, Google DNS, and CloudFlare DNS. DoH is a protocol that encrypts DNS queries and responses using the HTTPS protocol. Threat actors may use DoH to obfuscate domain names associated with their externally hosted infrastructure that would otherwise be visible in standard DNS queries."
events:
$e.metadata.event_type = "NETWORK_CONNECTION"
$e.target.ip = /^(8\.8\.8\.8|8\.8\.4\.4|9\.9\.9\.9|9\.9\.9\.11|1\.1\.1\.1|1\.0\.0\.1|45\.90\.28\.160|45\.90\.30\.160|149\.112\.112\.112|149\.112\.112\.11)$/ nocase
(
$e.target.port = 443 or
$e.target.url = /dns-query|:443\/$|\d\.\d\.\d\.\d\/$/ nocase
)
$source_entity = strings.coalesce($e.principal.asset_id,$e.principal.ip)
match:
$source_entity over 2h
outcome:
$risk_score = max(35)
$unique_doh_ips_count = count_distinct($e.target.ip)
condition:
$e and $unique_doh_ips_count >= 5
options:
allow_zero_values = true
}
알 수 없는 엔드포인트에서 발생하는 DNS-over-HTTPS 및 웹 애플리케이션 개발 서비스 통신
rule hunting_t1071_001_unknown_endpoint_generating_doh_and_web_development_services_communication {
meta:
rule_name = "Unknown Endpoint Generating DNS-over-HTTPS and Web Application Development Services Communication"
severity = "Medium"
tactic = "TA0011" // Command and Control
technique = "T1071.001" // Application Layer Protocol: Web Protocols
reference = "https://cloud.google.com/blog/topics/threat-intelligence/brickstorm-espionage-campaign"
description = "Detects on requests by an unknown source IP address to multiple DNS-over-HTTPS (DoH) resolver services and web application development services, such as Cloudflare Workers or Heroku hosted web applications. To investigate this activity further, determine the source of the network activity and verify if the communication is consistent with the device's intended use and standard allow-list domains."
events:
$c1.metadata.event_type = "NETWORK_CONNECTION"
$c1.target.ip = /^(8\.8\.8\.8|8\.8\.4\.4|9\.9\.9\.9|9\.9\.9\.11|1\.1\.1\.1|1\.0\.0\.1|45\.90\.28\.160|45\.90\.30\.160|149\.112\.112\.112|149\.112\.112\.11)$/ nocase
$c1.principal.hostname = ""
$c1.principal.asset_id = ""
(
$c1.target.port = 443 or
$c1.target.url = /dns-query|:443\/$|\d\.\d\.\d\.\d\/$/ nocase
)
$c2.metadata.event_type = "NETWORK_CONNECTION"
$c2.target.hostname = /\.workers\.dev$|\.herokuapp\.com$/ nocase
$c2.principal.hostname = ""
$c2.principal.asset_id = ""
$c2.target.port = 443
$source_entity = $c1.principal.ip
$source_entity = $c2.principal.ip
match:
$source_entity over 24h
outcome:
$risk_score = max(65)
$unique_doh_ips_count = count_distinct($c1.target.ip)
condition:
$c1 and $c2 and $unique_doh_ips_count >= 3
options:
allow_zero_values = true
}
알 수 없는 엔드포인트에서 발생하는 Google DNS-over-HTTPS 및 Cloudflare 호스팅 IP 통신
rule hunting_t1071_001_unknown_endpoint_generating_google_doh_and_cloudflare_communication {
meta:
rule_name = "Unknown Endpoint Generating Google DNS-over-HTTPS and Cloudflare Hosted IP Communication"
severity = "Medium"
tactic = "TA0011" // Command and Control
technique = "T1071.001" // Application Layer Protocol: Web Protocols
reference = "https://cloud.google.com/blog/topics/threat-intelligence/brickstorm-espionage-campaign"
description = "Detects on requests by an unknown source IP address to Google DNS-over-HTTPS (DoH) resolver service and a Cloudflare hosted IP address. To investigate this activity further, determine the source of the network activity and verify if the communication is consistent with the device's intended use and standard allow-list domains."
events:
$c1.metadata.event_type = "NETWORK_CONNECTION"
$c1.target.ip = /^(8\.8\.8\.8|8\.8\.4\.4)$/ nocase
$c1.principal.hostname = ""
$c1.principal.asset_id = ""
(
$c1.target.port = 443 or
$c1.target.url = /dns-query|:443\/$|\d\.\d\.\d\.\d\/$/ nocase
)
$c2.metadata.event_type = "NETWORK_CONNECTION"
$c2.principal.hostname = ""
$c2.principal.asset_id = ""
$c2.target.ip_geo_artifact.network.carrier_name = /cloudflare/ nocase
$c2.target.port = 443
$source_entity = $c1.principal.ip
$source_entity = $c2.principal.ip
match:
$source_entity over 1h
outcome:
$risk_score = max(65)
$time_diff = math.abs(min($c1.metadata.event_timestamp.seconds) - min($c2.metadata.event_timestamp.seconds))
condition:
$c1 and $c2 and $time_diff <= 2
options:
allow_zero_values = true
}
알 수 없는 엔드포인트에서 발생하는 Google DNS-over-HTTPS 및 Amazon 호스팅 IP 통신
rule hunting_t1071_001_unknown_endpoint_generating_google_doh_and_amazon_communication {
meta:
rule_name = "Unknown Endpoint Generating Google DNS-over-HTTPS and Amazon Hosted IP Communication"
severity = "Medium"
tactic = "TA0011" // Command and Control
technique = "T1071.001" // Application Layer Protocol: Web Protocols
reference = "https://cloud.google.com/blog/topics/threat-intelligence/brickstorm-espionage-campaign"
description = "Detects on requests by an unknown source IP address to Google DNS-over-HTTPS (DoH) resolver service and an Amazon hosted IP address. To investigate this activity further, determine the source of the network activity and verify if the communication is consistent with the device's intended use and standard allow-list domains."
events:
$c1.metadata.event_type = "NETWORK_CONNECTION"
$c1.target.ip = /^(8\.8\.8\.8|8\.8\.4\.4)$/ nocase
$c1.principal.hostname = ""
$c1.principal.asset_id = ""
(
$c1.target.port = 443 or
$c1.target.url = /dns-query|:443\/$|\d\.\d\.\d\.\d\/$/ nocase
)
$c2.metadata.event_type = "NETWORK_CONNECTION"
$c2.principal.hostname = ""
$c2.principal.asset_id = ""
$c2.target.ip_geo_artifact.network.carrier_name = /amazon/ nocase
$c2.target.port = 443
$source_entity = $c1.principal.ip
$source_entity = $c2.principal.ip
match:
$source_entity over 24h
outcome:
$risk_score = max(65)
$time_diff = math.abs(min($c1.metadata.event_timestamp.seconds) - min($c2.metadata.event_timestamp.seconds))
condition:
// As observed by Mandiant IR, the two connection events to DoH and Amazon occurred nearly simultaneously
$c1 and $c2 and $time_diff <= 2
options:
allow_zero_values = true
}