포티넷 제로데이와 맞춤형 맬웨어를 사용하는 중국의 위협 행위자
Mandiant
*본 아티클의 원문은 2023년 3월 16일 Google Cloud 블로그(영문)에 게재되었습니다.
사이버 스파이 활동을 하는 위협 행위자들은 방화벽, IoT 장치, 하이퍼바이저 및 VPN 기술(예: Fortinet, SonicWall, Pulse Secure 등)처럼 EDR로 방어하기 어려운 대상으로 지속해서 표적으로 삼고 있습니다. 맨디언트(Mandiant)는 지난 수년 간 방위 산업 기반(Defense Industrial Base), 정부, 기술 및 통신 조직을 목표로 제로데이 취약점을 악용하고 맞춤형 맬웨어를 배포하여 사용자 자격 증명을 도용하고 피해 조직의 네트워크에 오랜 기간 접근한 것으로 보이는 수십 건의 침입을 조사했습니다.
맨디언트는 사이버 스파이 활동을 하는 위협 행위자들이 제로데이 취약점을 악용하여 인터넷에 노출된 시스템에 맞춤형 맬웨어를 초기 공격 벡터로 배포하는 것을 자주 목격합니다. 이번 포스팅에서는 중국-넥서스(China-nexus) 위협 행위자로 의심되는 공격자가 피해자 환경에 접근한 다음 해당 네트워크에 대한 지속적인 액세스를 유지하기 위해 포티넷 및 VM웨어 솔루션에 백도어를 배포한 시나리오를 알아봅니다. 참고로 맨디언트는 2022년 9월에 VM웨어 맬웨어 생태계에 대한 세부 정보를 발표한 바 있습니다.
2022년 중순에 맨디언트와 포티넷은 양사 협력 하에 포티넷 솔루션을 대상으로 한 맬웨어 배포를 조사하였습니다. 당시 조사 대상 솔루션은 방화벽인 FortiGate, 관리 솔루션인 FortiManager, 로그 관리와 분석 및 리포팅 플랫폼인 FortiAnalyzer이었습니다. 위협 행위자가 취한 조치는 다음과 같이 단계를 구분할 수 있습니다.
- 로컬 디렉토리 트래버스 제로데이(CVE-2022-41328) 익스플로잇을 활용해 쉘 액세스 허용 범위를 벗어나 FortiGate 방화벽 디스크에 파일을 씁니다.
- ICMP 포트 노킹(Knocking)을 통해 FortiGate 방화벽 내에서 슈퍼 관리자 권한으로 지속적인 접근을 유지합니다.
- FortiManager 장치에서 활성화된 방화벽 규칙을 우회하여 슈퍼 관리자 권한으로 백도어에 계속 연결할 수 있도록 합니다.
- 장치 내에서 생성된 사용자 지정 API 엔드포인트를 통해 FortiManager 및 FortiAnalyzer 장치에 지속성을 확립합니다.
- 부팅 파일 손상을 통해 시스템 파일에 대한 OpenSSL 1.1.0 디지털 서명 확인을 비활성합니다.
맨디언트는 관찰한 활동의 배후에 중국의 UNC3886 그룹이 있다고 보고 있습니다. 이 공격 그룹은 2022년 9월에 공개된 새로운 VM웨어 ESXi 하이퍼바이저 맬웨어 프레임워크와 연관된 것으로 추정됩니다. 맨디언트는 ESXi 하이퍼바이저 침해가 발생했을 때 UNC3886이 여러 차례에 걸쳐 FortiGate와 FortiManager 장치에서 VIRTUALPITA 백도어로 직접 연결하는 것을 관찰하였습니다.
맨디언트는 포티넷 관리 IP 주소에서 VIRTUALPITA로 연결되는 것을 보고 FortiGate와 FortiManager 장치가 손상된 것으로 의심하였습니다. 또한, FIPS 준수 모드가 활성화된 FortiGate 장치는 나중에 재부팅한 다음에 다시 부팅을 하는 데 실패하였습니다. 그 이유를 살펴보자면 FIPS 모드가 활성화되면 운영체제의 체크섬이 클린 이미지의 체크섬과 비교됩니다. 위협 행위자가 운영체제를 변조한 결과 체크섬 비교에 실패했고, 이에 따라 FortiGate는 장치를 보호하기 위해 시스템을 다시 시작하지 못하게 조치 하였습니다. 맨디언트는 포티넷의 도움으로 부팅이 실패한 장치의 포렌식 이미지를 확보하였고, 이 장치를 분석해 ICMP 포트 노킹 백도어인 CASTLETAP을 발견하였습니다.
포티넷 생태계
UNC3886이 VM웨어 인프라를 가로질러 이동하기 전에 포티넷 생태계의 여러 구성 요소들이 침해 대상이 되었습니다. 침해 당시 이들 구성 요소와 관련된 버전은 다음과 같습니다.
- FortiGate 6.2.7
- FortiManager 6.4.7
- FortiAnalyzer 6.4.7
시나리오 #1 요약: 인터넷에 노출된 FortiManager
맨디언트는 위협 행위자가 포티넷 기술을 악용해 네트워크 접근을 설정하는 두 가지 공격 라이프 사이클을 관찰했습니다. 첫 번째는 FortiManager 장치가 인터넷에 노출되었을 때의 접근입니다. 그림 1과 같이 위협 행위자는 정당한 API 호출로 가장한 백도어(THINCRUST)를 FortiManager와 FortiAnalyzer에 배포하였습니다. 두 장치에 지속성이 확보되면 FortiManager 스크립트를 사용해 FortiGate 장치에 백도어(CASTLETAP)를 배포하였습니다.
맨디언트는 포티넷 장치에서 ESXi 서버로 SSH 연결하는 것을 관찰하였습니다. 그리고 이어서 VIRTUALPITA와 VIRTUALPIE 백도어가 포함된 악성 vSphere 설치 번들(Installation Bundle)이 깔렸습니다. 이를 통해 위협 행위자는 하이퍼바이저에 대한 지속적인 접근 권한을 확보하여 가상 머신에 명령을 실행할 수 있게 됩니다.
본 포스팅을 작성하는 시점에서 맨디언트는 초기 접근을 얻거나 악성 VIB 배포에 사용된 제로데이 취약점에 대한 증거가 없었습니다. 참고로 VIRTUALPITA와 VIRTUALPIE는 2022년 9월에 올린 맨디언트 블로그 게시물에서 자세한 설명을 볼 수 있습니다.


그림 1. 인터넷에 노출된 FortiManager를 대상으로 한 공격 라이프사이클
시나리오 #2 요약: 인터넷에 노출되지 않은 FortiManager
두 번째로 알아볼 공격 시나리오는 FortiManager 장치에 ACL이 설정되어 외부 접근을 TCP 포트 541(FortiGate에서 FortiManager로의 연결)로만 제한한 경우에 발생한 침해입니다. 그림 2와 같이 위협 행위자는 새로운 ACL을 우회하기 위해 FortiManager 장치에 네트워크 트래픽 리다이렉션 유틸리티(TABLEFLIP)과 리버스 쉘 백도어(REPTILE)를 배포했습니다. 위협 행위자는 TABLEFLIP 유틸리티로 설정한 리다이렉션 규칙을 통해 인터넷에서 직접 REPTILE 백도어에 접근해 피해자 환경에 지속해서 액세스할 수 있었습니다.


그림 2: FortiManager에 인터넷 액세스 제한이 적용된 후의 활동
시나리오 #1 상세 분석: 인터넷에 노출된 FortiManager
이제 인터넷에 노출된 FortiManager를 대상으로 한 위협 행위자의 공격 경로를 상세히 알아보겠습니다.
파이썬 기반 백도어 THINCRUST
맨디언트 분석 결과 위협 행위자는 FortiManager에 처음 연결할 때 합법적인 웹 프레임워크 파일에 파이썬 백도어 코드를 추가하였습니다. 맨디언트는 이 새로운 맬웨어 제품군을 THINCRUST로 분류했습니다. 위협 행위자는 그림 3과 같이 악성 API 호출인 'show_device_info'를 넣기 위해 합법적인 파일인 '/usr/local/lib/python3.8/proj/util/urls.py'를 수정했습니다. 이를 통해 위협 행위자는 '/p/util/show_device_info'에 대한 POST 요청으로 THINCRUST 백도어와 상호작용할 수 있었습니다.


그림 3: urls.py 비교
POST 요청이 'show_device_info' URL로 전송되면 이 요청은 '/usr/local/lib/python3.8/proj/util/views.py' 함수에 전달됩니다. 'get_device_info' 함수는 THINCRUST 백도어를 포함하고 있어 그림 4와 같이 POST 요청에 제공된 쿠키에 따라 위협 행위자가 명령을 실행하고, 디스크에 파일을 쓰고, 디스크에서 파일을 읽을 수 있게 됩니다.


그림 4: THINCRUST 백도어 파이썬 코드
'get_device_info' 함수는 POST 요청 내에 두 개의 쿠키(FGMGTOKEN, DEVICEID)의 존재에 의존했습니다. FGMGTOKEN 쿠키는 'views.py'에 하드코딩된 RSA 키로 암호화되었고, DEVICEID 쿠키를 통해 받은 명령을 복호화하는 데 사용되는 RC4 키를 포함하고 있습니다. DEVICEID의 복호화 결과는 'id'와 'key'라는 키를 가진 JSON 인코딩 딕셔너리였습니다. 표 1과 같이 'id' 값은 백도어 내에서 실행할 작업을 결정하며 'key' 값은 수행되는 작업에 대한 인수로 작용하는 문자열을 포함했습니다.
'view.py' 파일에는 '@login_required' 데코레이터가 적용되어 있었습니다. 이 데코레이터는 다른 함수의 동작을 명시적으로 수정하지 않고 확장하는 함수입니다(데코레이터 호출 구문: '@). 그러나 악의적인 함수인 'get_device_info'는 시스템에 기본적으로 탑재된 Django 파이썬 모듈을 사용해 그림 5와 같이 함수에 '@csrf_exempt' 데코레이터를 추가했습니다. 이는 악의적인 API 호출에 대한 POST 요청이 로그인이나 CSRF 토큰 없이도 성공적으로 실행될 수 있다는 것을 의미합니다.


그림 5: @login_required와 @csrf_exempt 비교
맨디언트는 악의적인 API 호출 변형을 FortiAnalyzer 장치에서도 발견했습니다. 'view.py'의 백도어 함수인 'get_device_info'는 FortiManager와 동일했지만 백도어에 접근하는 데 사용되는 API 호출은 그림 6과 같이 FortiAnalyzer 장치에서 '/p/utils/fortigate_syslog_send'로 변경되었습니다.


그림 6: FortiAnalyzer의 urls.py 변형: fortigate_syslog_send
FortiGate 장치에서 CVE-2022-41328 악용
위협 행위자는 THINCRUST 백도어를 사용해 FortiManager와 FortiAnalyzer 장치 간 지속성을 확립한 후 여러 FortiGate 방화벽에 FortiManager 스크립트를 배포했습니다. 이 활동은 그림 7과 같이 FortiGate 로그에 기록되었습니다.
위협 행위자는 보안 전문가의 분석을 방해하기 위해 FortiManager 장치에서 스크립트를 삭제했습니다. 그러나 여러 이벤트 로그의 상관관계를 볼 때 스크립트가 경로 순회 취약점(CVE-2022-41328)을 이용했다는 것을 알 수 있습니다. 위협 행위자는 'execute wireless-controller hs20-icon upload-icon' 명령으로 취약점을 악용했습니다. 이 명령으로 위협 행위자는 평소 제한된 시스템 디렉토리에서 합법적인 파일을 덮어쓸 수 있었습니다. 일반적으로 'execute wireless-controller hs20-icon upload-icon' 명령은 FTP나 TFTP를 사용해 서버에서 FortiGate 방화벽에 .ico 파일(아이콘 파일)을 업로드하는 데 사용되며, 이 파일들은 HotSpot 2.0 온라인 가입(OSU) 포털에서 사용할 수 있습니다. HotSpot 2.0은 모바일 기기가 셀룰러 데이터와 공용 와이파이 간에 원활하게 전환할 수 있도록 하는 기술입니다.
'execute wireless-controller hs20-icon upload-icon' 명령은 두 가지 문제가 있습니다. 이 명령은 업로드되는 파일 유형을 검증하지 않았고, 디렉토리 순위 취약점에 취약하여 슈퍼 관리자 권한을 가진 위협 행위자가 파일시스템의 임의 위치에 65,535바이트보다 작은 파일을 업로드할 수 있게 했습니다. 이는 위협 행위자가 FortiGate 방화벽의 합법적인 시스템 파일을 대체할 수 있다는 것을 의미합니다.
취약점(CVE-2022-41328)을 성공적으로 악용하는 것은 FortiGate 로그에 기록되지 않습니다. FortiManager 스크립트 실행 시간에 취약점을 사용해 시스템 파일 '/bin/lspci'를 덮어쓰려는 위협 행위자의 실패는 그림 8과 같이 로그에 기록되었습니다.
포티넷은 앞서 소개한 명령을 악용한 사례가 이전에는 없었다는 것을 확인했습니다. 그리고 이 취약점을 CVE-2022-41328로 지정하였습니다. 포티넷은 그림 8과 같은 실패한 명령 이벤트에서 확인한 구문을 사용해 취약점 악용 사례를 성공적으로 재현하였습니다.
'file_transfer: TFTP.Server.Buffer.Overflow repeated X times'가 msg 필드에 있는 FortiGuard 로그 이벤트에서 추가로 시도된 악용 증거가 발견되었습니다. 이러한 이벤트는 FortiGate 방화벽에서 FortiAnalyzer 장치로 연결을 보여줍니다. 패킷 내용에는 그림 9에서 볼 수 있는 lscpi 디렉토리 순회 문자열이 포함되어 있습니다. 파일 이름 'node'가 포함된 디렉토리 순회 문자열도 유사한 이벤트에서 참조되었습니다. 이는 FortiGate 6.2.7 장치의 '/bin/' 디렉토리에 있는 다른 이진 파일입니다. 그러나 맨디언트는 위협 행위자가 lscpi 이진 파일만 성공적으로 교체하는 것을 관찰하였습니다.
심볼릭 링크를 사용한 의심스러운 백도어 (/bin/lspci -> /bin/sysctl)
맨디언트는 FortiGate 로그에서 본 실패한 명령을 기반으로 수정된 '/bin/lspci' 버전을 찾기 위해 여러 FortiGate 방화벽의 파일 목록을 검토했는데 총 두 가지 변형의 '/bin/lspci' 가 확인되었습니다. 이 중 하나는 독립 실행형 이진 파일이고 다른 하나는 '/bin/sysctl'로 심볼릭 링크된 버전입니다. 포티넷은 '/bin/lspci'가 항상 독립 실행형 이진 파일이어야 한다고 확인했습니다.
취약해진 FortiGate 방화벽에서 '/bin/lspci'와 '/bin/sysctl'에 대한 파일 목록 항목은 FortiGate 기기의 다른 합법적인 이진 파일과 일치하지 않는 유사한 타임스탬프를 포함하고 있었습니다. 또한, 손상된 FortiGate 방화벽의 '/bin/sysctl' 파일 크기는 손상되지 않은 기기에서 보고된 것보다 훨씬 컸습니다.
정상적인 상황에서 'diagnose hardware lscpi' 명령은 FortiGate 방화벽에 연결된 PCIe 기기 목록을 작성하는 데 사용되지만 위협 행위자가 합법적인 lspci 이진 파일을 심볼릭 링크로 교체하면 진단 명령어가 위협 행위자가 수정한 sysctl 파일을 실행할 수 있습니다. 그림 10과 11의 파일 목록 스니펫은 FortiGate 방화벽에 존재하는 원본과 수정된 '/bin/lspci' 및 '/bin/sysctl' 버전 간의 차이를 보여줍니다.
수정 시간과 크기 차이 외에도 파일 목록 명령 'fnsysctl ls -l /bin'의 출력은 여러 필드를 다른 형식과 순서로 표시했습니다. 이는 위협 행위자가 ' /bin/sysctl'을 교체하여 FortiGate 방화벽의 쉘 기능이 변경되었기 때문일 가능성이 큽니다. FortiOS 파일시스템에 대한 변경은 영구적이지 않아 침해 분석을 위해 파일을 복구할 수 없었습니다.
기본적으로 FortiOS를 실행하는 포티넷 장치는 '/data/' 파티션 내에 rootfs.gz라는 디스크 아카이브를 가지고 있습니다. 부팅 시 이 파일은 루트 파일시스템으로 마운트됩니다. 이는 마운트된 이미지에 수정 사항이 있으면 rootfs.gz 아카이브에 쓰이지 않는 한 변경 사항이 영구적이지 않다는 것을 의미합니다. FortiGate 방화벽은 런타임 동안 마운트된 파일시스템에서 파일을 내보낼 수 없습니다. '/bin/lspci'와 '/bin/sysctl'에 대한 수정 사항이 rootfs.gz 아카이브에 기록되지 않았기 때문에 영구적으로 설치되지 않았으며 추가 분석을 할 수 없었습니다.
맨디언트는 포티넷과 협력해 손상된 FortiGate 방화벽의 포렌식 이미지를 획득하여 위협 행위자의 행동을 더 잘 파악할 수 있었습니다. 포티넷은 손상된 FortiGate 방화벽의 포렌식 이미지를 침해를 입지 않은 버전과 비교하여 영구적인 백도어가 포함된 트로이 목마 펌웨어를 식별했습니다. 맨디언트는 백도어를 새로운 맬웨어 패밀리인 CASTLETAP으로 이름 붙였습니다.
FortiGate 방화벽 백도어 CASTLETAP
FortiGate 방화벽 분석을 통해 추가 맬웨어인 '/bin/fgfm'을 발견했습니다. 분석 결과 이는 특수한 ICMP 패킷을 활성화로 감지하는 백도어인 CASTLETAP으로 판명되었습니다. 위협 행위자는 파일을 'fgfm'이라고 이름 붙여 합법적인 서비스인 'fgfmd'로 위장하려 하였습니다. 참고로 'fgfmd'는 FortiManager와 FortiGate 방화벽 간의 통신을 돕습니다.
CASTLETAP이 실행되면 네트워크 트래픽을 스니핑하기 위해 원시 프로미스큐어스(promiscuous) 소켓을 생성합니다. 그런 다음 ICMP 에코 요청 패킷의 페이로드에 있는 9바이트 활성화 매직 문자열을 필터링하고 XOR 디코딩합니다. 표 2는 CASTLETAP이 해석하는 매직 문자열과 그에 따른 작업 결과입니다.
ICMP 패킷 내의 C2 서버 정보를 디코드하기 위해 Epoch 날짜 표시를 사용해 페이로드 데이터를 복호화하는 단일 바이트 XOR 키가 생성되었습니다. 이는 인코딩 표준이 매일 변경되었다는 것을 의미합니다. 그림 12는 XOR 키 계산에 사용한 공식입니다.
표 3은 ICMP 패킷의 페이로드 구조를 정의합니다.
활성화 패킷에서 C2 서버 IP 주소와 포트가 파싱되면 CASTLETAP은 SSL 소켓을 통해 C2 서버와 연결을 시작합니다. 연결이 설정되면 CASTLETAP은 C2 서버가 그림 13처럼 16바이트 시퀀스로 핸드쉐이크를 시작하며, 동일한 시퀀스를 응답으로 반복합니다.
C2 서버에 연결되면 표 4와 같이 CASTLETAP은 SSL을 통해 여러 유형의 명령을 받을 수 있습니다.
명령이 성공적으로 수신되면 백도어는 인증 토큰으로 ';7(Zu9YTsA7qQ#vw' 시퀀스를 반환합니다. 이 문자열은 세션 정료 신호로도 전송됩니다.
CASTLETAP이 FortiGate 방화벽에 배포되면 위협 행위자는 ESXi와 vCenter에 접근을 합니다. 위협 행위자는 VIRTUALPITA와 VIRTUALPIE를 배포해 지속성을 확립하고, 하이퍼바이저와 게스트 머신에 대한 지속적인 액세스를 가능하게 합니다. 이에 대한 상세 정보는 관련 포스팅을 참조 바랍니다.
시나리오 #2 상세 분석: 인터넷에 노출되지 않은 FortiManager
위협 행위자가 ACL이 설정된 FortiManager를 대상으로 수행한 공격 경로를 알아보겠습니다.
인터넷 연결이 제한된 FortiManager에 다시 액세스하기
FortiManager 장치에 ACL이 설정되면 위협 행위자는 장치에 대한 인터넷을 통한 액세스 권한을 잃게 됩니다. 이 경우 위협 행위자는 FortiManager에 다시 접근하기 위해 CASTLETAP으로 손상된 FortiGate 방화벽을 활용하는 다시 접근할 수 있는 발판을 마련하였습니다. 위협 행위자는 FortiManager에 성공적으로 다시 연결한 다음 세 개의 맬웨어를 배포하였습니다. 이는 표 5를 참조 바랍니다.
' /bin/support (MD5: 9ce2459168cf4b5af494776a70e0feda)' 파일은 ' /bin/klogd REPTILE 변형)'과 '/bin/auth(TABLEFLIP)'를 실행하는 런치 스크립트 역할을 했습니다. 위협 행위자는 시작 파일 ' /etc/init.d/localnet'을 수정하여 ‘nohup /bin/support &’ 라인을 실행하도록 했습니다. 이에 시스템이 재부팅될 때마다 스크립트가 실행되었습니다. 실행 중인 FortiOS 파일시스템은 아카이브 rootfs.gz의 일시적인 복사본이므로 파일은 메모리에 로드된 후 복사본에서 삭제되고 rootfs.gz 아카이브에 지속되었습니다. 이 파일은 포렌식 이미지를 가저 오지 않는 한 사용자가 액세스할 수 없었습니다. '/bin/support'의 내용은 그림 14와 같습니다.
위협 행위자는 인터넷을 통해 계속 장치에 직접 액세스할 수 있도록 모든 활성 인터페이스에서 특수한 명령 패킷을 수신하는 트래픽 리다이렉션 유틸리티인 TABLEFLIP(MD5: b6e92149efaf78e9ce7552297505b9d5)을 구현하였습니다. 이 유틸리티가 있으면 ACL 존재 여부와 관계없이 위협 행위자가 그림 15와 같이 FortiManager에 직접 연결할 수 있습니다.


그림 15. TABLEFLIP을 이용한 연결
TABLEFLIP은 모든 활성 인터페이스에서 TCP 패킷을 수신하도록 설정되었으며 TCP 541 포트로 전송되는 패킷의 TCP 페이로드 시작 부분에서 그림 16과 같은 매직 패킷을 찾았습니다.
매직 넘버가 발견되면 맬웨어는 TCP 페이로드의 오프셋 OxB에서 XOR 키를 추출합니다. 이 키는 XOR 기반 순차적 복호화를 위한 시드로 사용됩니다. TCP 페이로드 오프셋 0xC 이후는 이 스키마를 사용해 복호화됩니다. 그림 17은 페이로드 구조를 보여줍니다.
이 맬웨어는 페이로드에서 명령, IP, 포트를 추출하려고 시도했습니다. 표 6은 명령으로 인해 수행되는 작업에 대한 설명입니다.
-Mandiant, 작성자: Alexander Marvi, Brad Slaybaugh, Dan Ebreo, Tufail Ahmed, Muhammad Umair, Tina Johnson