위협 요약
2026년 8월 초, Sonatype과 OpenSourceMalware가 npm 레지스트리에서 약 800개의 악성 패키지가 대규모로 유입된 'Flooding Dropper'(WEL1DROPPER) 캠페인을 발견했다. 이 캠페인은 preinstall/postinstall 라이프사이클 훅을 사용하지 않고 README에서 require()로 패키지를 로드하도록 지시하는 새로운 실행 트리거 방식을 채택했다. 개발자가 SDK를 초기화하거나 의심스러운 메서드를 호출할 필요가 없으며, 단순히 import만으로 감염이 시작된다. Cloudflare Workers 호스트를 경유한 후 HTTPS GET 방식으로 크로스플랫폼 바이너리를 다운로드하며, 실패 시 DNS TXT 레코드 기반 폴백 배달을 통해 HTTPS 차단을 우회한다. 2차 페이로드는 플랫폼별로 분화되어 Windows에서는 ETW 패치와 AMSI 우회를, macOS에서는 LaunchAgent 지속성을, Linux에서는 Sliver C2 프레임워크를 적용하는 것으로 알려졌으나 1차 분석에서는 아직 확인되지 않은 상태이다. macOS 페이로드 내 러시아 금융기관 도메인 노출로 표적 공격 가능성이 지목된다.
악성 패키지 유포 기법 — AI Slop Squatting
패키지 네이밍 전략
공격자는 'AI slop squatting'이라 불리는 전략을 활용해 패키지를 네이밍했다. bigops, bnpl 키워드를 포함하거나 버전 35.x.y 패턴을 적용해 합법적인 SDK처럼 위장한다. typo squatting(오타 사칭) 기법도 병용해 개발자가 실제로 악성 패키지를 설치할 확률을 높인다.
새로운 실행 트리거 — preinstall 없이 require()
기존 npm 공격캠페인과 구분되는 핵심 특징은 preinstall/postinstall 라이프사이클 훅을 사용하지 않는 것이다. 대신 README에서 require()로 패키지를 로드하도록 지시한다.
// index.js 일부
module.exports = {
CheckoutMobileBnpl,
create: (opts) => new CheckoutMobileBnpl(opts),
VERSION
};
try { require("./_helpers"); } catch (_) {}
_helpers.js는 로드 즉시 run()을 실행한다. 개발자가 SDK를 초기화하거나 의심할 필요 없이 단순히 import만으로 감염이 시작된다.
핵심 인사이트: npm 악성패키지는 preinstall 스크립트가 없어도 실행된다. 설치 스크립트 차단은 도움이 되지만, 개발/테스트/프로덕션 시작 시 악성 의존성을 import하는 애플리케이션을 보호하지는 않는다.
WEL1DROPPER — 크로스플랫폼 다운로드 아키텍처
WEL1DROPPER는 호스트 OS와 CPU 아키텍처를 식별해 플랫폼별 페이로드를 다운로드한다.
| 플랫폼 | 페이로드 경로 |
|---|---|
| Linux x64 | /pkg/package |
| Linux ARM64 | /pkg/package-arm64 |
| macOS x64/ARM64 | /pkg/loader_mac |
| Windows x64/x86 | /pkg/package.exe |
메인 배달 경로 (HTTPS)
3개 Cloudflare Workers 호스트를 셔플링한 후 HTTPS GET 요청을 보낸다.
- oob-worker.cf103-070.workers.dev
- oob-worker.cf102-baf.workers.dev
- oob-worker.cf99-9b3.workers.dev
요청 특징은 IPv4 강제, 15초 타임아웃, User-Agent node-fetch/2.6, HTTP 200 응답 시 1,000바이트 이상 파일만 수락, 서버에서 반환된 것이 곧 실행파일이다.
폴백 배달 경로 (DNS TXT)
HTTPS가 실패하면 플랫폼별 도메인으로 전환된다.
| 플랫폼 | 도메인 |
|---|---|
| Linux x64 | sdk.dl.wel1.ru |
| Linux ARM64 | ext.dl.wel1.ru |
| macOS | pkg.dl.wel1.ru |
| Windows | net.dl.wel1.ru |
동작 방식은 c.<domain>의 TXT 레코드 조회로 페이로드 청크 수를 확인한 후 0.<domain>, 1.<domain>... 순차적으로 TXT 레코드를 조회하고, 반환된 문자열을 결합해 Base64 디코딩한 후 바이너리 버퍼로 만든다. DNS 모니터링이 known tunneling tool만 감지할 경우 이 우회 경로는 탐지되지 않는다.
페이로드 실행 및 위장
페이로드(1,001바이트 이상)를 획득 후 8자리 16진수 식별자로 임의의 이름 파일에 저장한다.
- Linux/macOS:
/var/tmp/.cache_<8자리>→/bin/sh -c "/var/tmp/.cache_<id> &" - Windows:
%TEMP%\dotnet_diag_<8자리>.exe→cmd.exe /c start /b %TEMP%\dotnet_diag_<id>.exe
공통 특징은 디터치(분리) 프로세스 실행으로 npm/Node.js 프로세스 종료해도 백그라운드에서 계속 실행되며, 표준 입력/출력 무시가 적용된다. 파일명은 위장 전략을 적용한다(.cache_는 Unix 합법 임시파일처럼, dotnet_diag_는 Windows 합법 디버깅 도구처럼 위장). 마커 파일 /tmp/.analytics_state 또는 %TEMP%\analytics_state 생성으로 약 6시간 간격으로 재실행을 방지한다.
2차 페이로드 — 플랫폼별 동작
Windows 2차 페이로드
- ETW(Event Tracing for Windows) 패치로 모니터링 방해
- AMSI(Antimalware Scan Interface) 우회로 악성코드 스캔 회피
- Sandbox/VM 탐지로 분석 환경 감지
- Registry Run 키 + 예약작업으로 지속성 확보
/pkg/update_win.exe암호화 페이로드 다운로드 후 메모리에서 리플렉티브 로딩
macOS 2차 페이로드
- 디버거 탐지, pcap/VM웨어 탐지
- 메모리 크기 체크로 Sandbox 휴리스틱 우회
/pkg/beacon_mac.bin다운로드 (Cloudflare Workers 프록시, 실패 시 DNS TXT 폴백)~/.local/share/runtime하위에 페이로드 설치- LaunchAgent(
com.apple.windowserver.helper.plist)로 지속성 확보 - XOR(0x9c 키)으로 암호화된 추가 C2 5개: package-proxy.cf{5,6,7,8,11}oobworker.workers.dev
- 피스체크 도메인: nexus.tcsbank.ru, repo-linux.tcsbank.ru, alertmanager.cloudpayments.ru (러시아 금융기관 타겟팅 의문)
Linux 2차 페이로드
- UPX-packed ELF 바이너리
- oob-worker.cf99-9b3.workers.dev에서 추가 단계 바이너리 다운로드
- 추가 단계가 Sliver C2 프레임워크인 것으로 알려졌으나, 1차 분석에서는 아직 확인되지 않음
탐지 지표 (IOC)
Cloudflare Workers C2
- oob-worker.cf103-070.workers.dev
- oob-worker.cf102-baf.workers.dev
- oob-worker.cf99-9b3.workers.dev
- package-proxy.cf{5,6,7,8,11}oobworker.workers.dev (macOS 3차)
DNS TXT 폴백 도메인
- sdk.dl.wel1.ru, ext.dl.wel1.ru, pkg.dl.wel1.ru, net.dl.wel1.ru
- dl.wel1.ru (macOS 2차)
macOS 추가 도메인
- nexus.tcsbank.ru, repo-linux.tcsbank.ru, alertmanager.cloudpayments.ru
페이로드 해시
| 샘플 | 포맷 | SHA-256 |
|---|---|---|
| Linux x86-64 | 정적 링크 ELF, UPX-packed | 7e486657f30594afda379b97030252a09a19fe8055e25c9e371544f59bd8e9e3 |
| macOS Universal | Mach-O x86-64 + ARM64 | c214746c74cae8ece8bdaf69aa05da4db6ce013f9e77452d1eed1a002fd9ba00 |
대응 방안
즉시 (24시간 내)
- sonatype-2026-005660에 등장한 패키지가 설치됐는지 개발 워크스테이션, CI/CD 러너, 빌드 이벤트, 내부 레지스트리/캐시, 테스트/프로덕션 시스템에서 확인한다.
- 감염 호스트 격리 후 지속성 메커니즘(Registry Run 키, 예약작업, LaunchAgent) 제거한다.
- 프로세스/DNS/프록시/엔드포인트 텔레메트리 검토한다.
- Node.js/npm/임시 디렉토리에서 시작된 디터치 프로세스 식별한다.
단기 (48시간 내)
- npm lockfile, 컨테이너 레이아웃, 내부 미러에서 악성 패키지를 제거한다.
- npm/GitHub/클라우드/CI/CD 자격증명을 재발급한다.
- bigops, bnpl 키워드 포함 패키지 버전 35.x.y 패턴의 의심성 여부를 추가 검증한다.
- 패키지명 철자 확인을 통한 typo squatting 방지 점검을 진행한다.
장기
- npm audit, Dependabot, Snyk 등 자동 스캔을 도입한다.
- 내부 npm 프록시(Verdaccio 등)를 도입해 외부 패키지를 필터링한다.
- CI/CD 파이프라인에 package.json 검증 단계를 추가한다.
- npm 패키지의 preinstall/postinstall 스크립트 실행 차단 정책을 검토한다.
- 행위 기반 분석 + 시뮬레이션 기반 탐지를 도입한다(명단 차단만으로 부족하다).
결론
npm 레지스트리를 통한 악성 패키지 유포는 단순한 위장성 문제가 아니다. 이번 Flooding Dropper 캠페인은 preinstall 스크립트 없이 require()만으로 실행이 가능한 새로운 트리거 방식을 채택했으며, Cloudflare Workers와 DNS TXT 폴백을 결합한 고도화된 배달 체계를 구축했다. 2차 페이로드는 ETW/AMSI 우회, Sliver C2(미확인), 러시아 금융기관 타겟팅 등 조직 맞춤형 공격 패턴을 보여준다. 개발 조직은 패키지 설치 전 검증, 내부 레지스트리 도입, CI/CD 파이프라인 보안 강화 등 다층 방어 전략이 필요하다.
참고문헌
-
The Hacker News — Nearly 800 Malicious NPM Packages Discovered
https://thehackernews.com/2026/08/nearly-800-malicious-npm-packages.html -
OpenSourceMalware — Russian AI Slop Squatting NPM Campaign
https://opensourcemalware.com/blog/russian-ai-slopsquatting-npm-campaign -
Sonatype — Flooding Dropper Hits NPM with 850 Malicious Packages
https://www.sonatype.com/blog/flooding-dropper-hits-npm-with-850-malicious-packages -
Sonatype Guide — sonatype-2026-005660
https://guide.sonatype.com/vulnerability/sonatype-2026-005660/sonatype-research
본 콘텐츠는 AI 기술로 작성된 분석 리포트를 포함하고 있습니다. 내용 중 사실과 다르거나 보완이 필요한 정보를 발견하셨으면 댓글을 통해 의견을 부탁드립니다. 여러분의 피드백은 더 정확한 보안 정보 공유에 큰 도움이 됩니다.
댓글 (0)
댓글을 작성하려면 로그인이 필요합니다.
로그인아직 댓글이 없습니다.
첫 번째 댓글을 작성해보세요!