Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
npm-incident-response — keyv/cacheable 공급망 공격용 스캐너: 손상된 npm 패키지를 탐지하고, 페이로드 해시를 검증하며, repo 및 host 모드에서 지속성 임플란트를 찾아냅니다. | Kitploit
도구/GitHubGitHub/securest8/npm-incident-response
Vulnerability ScannersPersistence MechanismsMalware AnalysisDigital ForensicsSupply Chain SecurityIncident Response
GitHubsecurest8/npm-incident-response

npm-incident-response

keyv/cacheable 공급망 공격용 스캐너: 손상된 npm 패키지를 탐지하고, 페이로드 해시를 검증하며, repo 및 host 모드에서 지속성 임플란트를 찾아냅니다.

저장소 보기
21181개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

npm-incident-response

English | Português

**keyv/cacheable 공급망 사고("Shai-Hulud: Here We Go Again", 2026년 8월 4일)**를 위한 독립형 스캐너 — 클라우드/CI 자격 증명을 탈취하고 데드맨 스위치와 함께 지속성을 심는 자가 증식 웜에 의해 손상된 440개 이상의 npm 패키지.

몇 분 안에, 아무것도 설치하지 않고 탐지합니다:

  • package-lock.json, npm-shrinkwrap.json, yarn.lock(v1 및 Berry), pnpm-lock.yaml, bun.lock의 손상된 패키지 — 전이적 의존성을 포함하며 전체 체인(예: eslint → file-entry-cache → flat-cache → [email protected])을 표시합니다;
  • node_modules에 설치된 페이로드(알려진 아티팩트의 이름 + SHA-256 해시);
  • IOC 목록에 아직 없는 변종(휴리스틱: 의심스러운 수명주기 스크립트, 웜 이름을 가진 파일) — 항상 SUSPECT로 표시되며, 해시 없이는 확정하지 않습니다;
  • 호스트 지속성 임플란트: LaunchAgent(macOS), systemd 사용자 서비스 + linger(Linux), .claude/settings.json 및 .vscode/tasks.json의 훅, 임시 아티팩트(bun-dl-*);
  • 데드맨 스위치: 임플란트가 GitHub 토큰을 모니터링하고, 폐기 시 4xx 응답이 반환되면 원격 명령을 실행합니다. 호스트를 정리하기 전에 자격 증명을 교체하면 함정이 발동됩니다 — 보고서가 경고하며, 아래의 대응 순서가 이 실수를 방지합니다.

공격 이해하기

  1. keyv/cacheable 계열의 관리자 계정이 손상되었습니다. 공격자는 "preinstall": "node setup.mjs" 훅이 포함된 새 버전을 게시했습니다 — 패키지가 설치되기 전에, npm install을 실행한 사람의 권한으로 실행되는 코드입니다.
  2. setup.mjs는 GitHub에서 Bun 런타임을 다운로드하여 그 안에서 페이로드를 실행합니다 — node 프로세스만 모니터링하는 도구에 대한 회피 수법입니다.
  3. Math_Symbol.js(약 728KB, 난독화됨)는 자격 증명을 탈취합니다: AWS 인스턴스 메타데이터, AWS/GCP/Azure 키, Vault 토큰, Kubernetes 서비스 계정, GitHub Actions 시크릿, npm 토큰, 그리고 디스크의 개인 키와 Bearer 토큰을 찾는 일반적인 정규식 스캔까지 포함합니다.
  4. 웜입니다: 탈취한 npm 토큰으로 동일한 훅을 그 자격으로 게시할 수 있는 다른 패키지에 주입하고, 무결성 해시를 다시 계산하여 재게시합니다. 그렇게 약 10개에서 수백 개의 패키지로 확산되었습니다.
  5. 고정된 C2 없이 데이터를 유출하며(그때그때 생성되는 GitHub 저장소, DNS) 뒤에 함정을 남깁니다 — 아래 참조.

두 가지 벡터(두 번째가 더 교묘합니다)

  • 벡터 A — 설치: 2026-08-04 09:35 UTC 이후 수명주기 스크립트가 활성화된 상태로 npm install/npm ci를 실행한 모든 사람. --ignore-scripts를 사용했다면 훅이 실행되지 않았습니다.
  • 벡터 B — 클론: 소스 저장소의 .claude/settings.json(SessionStart)과 .vscode/tasks.json(folderOpen)에 자동 시작 훅이 추가되었으며, 이 훅은 클론한 폴더가 열릴 때 로더를 실행합니다 — npm install도, 설치되는 것도 없습니다. 여기에는 사고를 조사하기 위해 저장소를 클론한 사람과 디렉터리를 연 AI 코딩 에이전트가 포함됩니다 — AI 에이전트 훅(.claude/)이 공급망 벡터로 사용된 최초의 공개 사례 중 하나입니다.

함정(데드맨 스위치)

임플란트는 LaunchAgent(macOS) 또는 systemd 사용자 서비스 + loginctl enable-linger(Linux)로 유지되는 "워처"(gh-token-monitor)를 설치합니다. 60초마다 API를 통해 탈취한 GitHub 토큰의 유효성을 검증합니다. 토큰이 유효한 동안에는 아무 일도 일어나지 않습니다. 응답이 4xx로 바뀌면 — 즉 토큰을 폐기하는 순간 — eval을 통해 ~/.config/gh-token-monitor/handler의 내용, 즉 공격자가 원격으로 정의한 임의의 명령을 실행합니다. 공개 분석에서는 그 내용이 무엇인지 알 수 없습니다 — 데이터 파괴, 재감염, 랜섬웨어일 수도 있고 아무것도 아닐 수도 있습니다. 위험을 평가할 수 없기 때문에 대응 순서가 절대적입니다.

대응을 바꾸는 세 가지 속성:

  • 네트워크 격리는 안전합니다: 연결이 없으면 HTTP 응답이 없으므로 4xx도 없습니다 — 함정이 발동하지 않고 유출도 중단됩니다. 먼저 격리하되, 전원을 끄지 마십시오(휘발성 메모리는 증거입니다).
  • 일회용이며 발동 후 스스로 흔적을 지웁니다 — 동작이 설명되지 않은 채로 남고, 조사할 아티팩트도 남지 않습니다.
  • 약 24시간 TTL: 워처는 하루가 지나면 자동 파괴됩니다. 아티팩트가 없다고 해서 시스템이 깨끗했다는 증거는 되지 않습니다 — 스캐너는 host 모드에서 이에 대해 경고합니다.

일반적인 방어 수단이 대개 이를 놓치는 이유

  • "서명은 유효했다" — [email protected]은 통과된 SLSA 증명과 함께 배포되었습니다. 출처 증명(provenance)은 소스가 아니라 빌드 무결성을 증명합니다. 합법적인 워크플로가 이미 트로이 목마가 심어진 코드를 컴파일한 것입니다.
  • "코드 diff에 변화가 없었다" — 맞습니다. 라이브러리 자체는 수정되지 않았습니다. 악의적인 부분은 package.json(preinstall 훅)과 패키지에 추가된 두 개의 새 파일(setup.mjs, Math_Symbol.js)에 있습니다.
  • "우리는 keyv를 쓰지 않는다" — 간접적으로 사용하고 있습니다. 가장 흔한 체인은 eslint → file-entry-cache → flat-cache → keyv입니다. 그래서 스캐너는 모든 탐지 결과에서 체인을 표시합니다.
  • "아무도 npm install을 실행하지 않았다" — 불충분합니다: 벡터 B를 참조하세요.

이 저장소의 스크립트는 무엇인가

scan.mjs는 다음과 같은 속성을 가집니다 — 공급망 사고에 대응하는 모든 사람에게 중요합니다:

  • 단일 파일, 약 880줄의 읽기 쉬운 코드, 의존성 제로. npm install이 필요 없습니다. 실행 전 15분 안에 scan.mjs 전체를 감사할 수 있습니다.
  • 외부 전송 제로. 데이터가 컴퓨터 밖으로 나가지 않습니다. 텔레메트리도, "분석을 위해 결과를 보내는" 기능도 없습니다. 유일한 네트워크 작업은 명시적이고 선택적인 --update(최신 IOC 매니페스트 다운로드)뿐입니다.
  • 읽기 전용. 스캐너는 발견한 것을 수정, 삭제 또는 실행하지 않습니다.
  • 오프라인으로 동작. docker run --network=none 또는 격리된 머신: scan.mjs + iocs.json만 복사하면 됩니다.

회사에서 사용하는 방법

요구 사항: Node.js ≥ 18(npm이 있는 모든 머신에는 이미 있습니다). scan.mjs + iocs.json 두 파일을 다운로드하면 끝입니다 — 설치가 필요 없습니다.

알림: 이 전체 저장소를 클론했다면, fixtures/ 폴더에는 테스트에 사용된 비활성(inert) IOC가 들어 있습니다(실제 이름과 버전, 더미 콘텐츠 — 악성 코드 없음). 스캐너는 이를 자동으로 건너뛰고 출력에서 경고합니다. 이 폴더의 탐지 결과는 의도적으로 스캔할 때만 나타납니다.

서로 다른 질문에 답하는 두 가지 실행 모드가 있으며, 그것이 어디서 실행할지 결정합니다:

  • repo 모드는 잠금 파일과 node_modules를 읽습니다 — 잠금 파일은 git에 있으므로 중앙 집중화할 수 있습니다: 한 사람이 회사의 모든 저장소를 스캔할 수 있습니다.
  • host 모드는 코드가 실행된 머신에 존재하는 임플란트(워처, LaunchAgent/systemd, IDE 훅)를 찾습니다 — 이는 git에 없으므로 중앙 집중화할 수 없습니다.

1단계 — AppSec이 모든 저장소를 스캔합니다(한 사람, 한 대의 머신)

node scan.mjs repo /folder/with/all/the/repos --json=result.json --html=report.html

"어떤 프로젝트가 노출되었는지"에 몇 분 안에, 아무도 관여시키지 않고 답합니다. 여러 경로를 허용하며 하위 디렉터리를 탐색합니다(모노레포와 워크스페이스 포함).

2단계 — 영향받은 프로젝트에서 작업한 사람이 자신의 머신을 스캔합니다

탐지 결과가 있는 각 프로젝트에 대해 2026-08-04 09:35 UTC 이후로 해당 프로젝트를 만진 사람을 식별합니다(git log, CI 로그). 그 사람들이 자신의 머신에서 실행합니다:

node scan.mjs        # current directory + host, in ~30 seconds

범위: (a) 해당 기간에 npm install/npm ci를 실행한 사람; 또는 (b) 단지 클론하고 VS Code나 AI 에이전트에서 폴더를 열기만 한 사람 — 벡터 B는 설치가 필요 없습니다.

비용이 약 30초이고 대상 선별 과정에 누수가 있을 수 있으므로(우연한 클론, 개인 프로젝트), 가장 안전한 사내 지침은 다음과 같습니다: 모든 개발자가 node scan.mjs를 한 번 실행하고 --json/--html 결과를 AppSec에 보냅니다. 전송은 설계상 수동입니다 — 스캐너에는 텔레메트리가 없습니다(외부 전송 제로).

3단계 — CI 러너와 빌드 서버

최우선 순위: 가장 가치 있는 자격 증명이 있는 곳입니다. 여기서 스캐너는 두 가지 다른 역할을 합니다 — 하나는 과거용, 하나는 미래용입니다:

과거 분류 — 판단을 위해 러너를 스캔하지 마십시오. "이 러너가 감염되었는가?"라는 질문은 스캔으로 답할 수 없습니다. 어떤 작업이 08-04 이후 --ignore-scripts 없이 영향받은 버전을 설치했다면, 그 순간 이미 자격 증명이 탈취된 것이며 러너 호스트는 증거를 거의 남기지 않습니다(임시 러너는 작업이 끝나면 컨테이너를 파기합니다; 워처는 약 24시간 안에 스스로 지워집니다). 이 질문에 답하는 것은 1단계의 잠금 파일과 CI 로그입니다. 답이 "예, 설치했습니다"라면: 러너를 재구축하고 시크릿을 교체하십시오 — 러너는 임시적이므로 정리할 이유가 없습니다.

향후 예방 — 그렇습니다, 파이프라인에서 실행하십시오. 스캐너를 빌드 단계로 추가하되, repo 모드에서 체크아웃 후, npm install 전에 실행합니다. 러너 호스트를 검사하는 것이 아니라 설치될 코드를 검사하며, 악성 preinstall이 실행될 기회를 얻기 전에 종료 코드로 빌드를 실패시킵니다:

# example (GitHub Actions / GitLab CI — adapt):
- run: node scan.mjs repo . --json    # exit 0 clean · 1 findings · 2 COMPROMISED
- run: npm ci --ignore-scripts         # only runs if the previous step passed

빠른 참조

node scan.mjs                     # scan the current directory + the host
node scan.mjs repo /path/a /path/b
node scan.mjs host                # persistence/implants on the machine only
node scan.mjs repo . --json=result.json --html=report.html
node scan.mjs --update            # update iocs.json (the only network operation)

분류

수준의미조치
COMPROMISEDnode_modules에 악성 버전이 설치됨, 해시로 확인된 페이로드, 또는 지속성 임플란트 발견호스트를 손상된 것으로 간주하고 대응 순서를 따르세요 — 자격 증명을 교체하기 전에 임플란트를 제거하세요
EXPOSED잠금 파일에 고정된 악성 버전, 실행 증거 없음안전한 버전을 고정하고, node_modules를 삭제한 후 --ignore-scripts로 재설치하세요
AT_RISK악성 버전을 허용하는 package.json의 범위(^/~)정확한 버전을 고정하거나 레지스트리 프록시에서 차단하세요
SUSPECT휴리스틱(해시 불일치가 있는 웜 파일명, 의심스러운 수명주기 스크립트)수동으로 검사하세요 — 새 변종이거나 오탐일 수 있습니다
INFO벡터는 존재하지만 IOC가 없음(예: 일반적인 folderOpen 작업)검토하세요

증거로서의 보고서

--html은 타임스탬프, 호스트 이름, IOC 매니페스트 버전 및 스캐너 자체의 SHA-256이 포함된 단일 파일 보고서를 생성합니다 — 사고 통지에 첨부하고 감사 추적으로 사용할 수 있습니다.

스캐너가 COMPROMISED를 보고한 경우: 대응 순서

아직 어떤 자격 증명도 폐기하거나 교체하지 마십시오 — 그것이 함정의 방아쇠입니다. 순서:

1. 격리(ISOLATE) — 머신을 네트워크에서 차단하세요. 안전합니다: HTTP 응답이 없으면 4xx도 없고, 함정이 발동하지 않으며, 유출도 중단됩니다. 전원을 끄지 마십시오(휘발성 메모리는 증거입니다).

2. 보존(PRESERVE) — 무엇이든 삭제하기 전에(워처는 약 24시간 후 자동 파괴됩니다):

mkdir -p /tmp/evidence && cp -r ~/.config/gh-token-monitor /tmp/evidence/ 2>/dev/null
cp /tmp/gh-token-monitor.*.log /tmp/evidence/ 2>/dev/null
shasum -a 256 /tmp/evidence/* 2>/dev/null

handler 파일은 실행될 공격자의 명령입니다 — 실행하지 말고, 셸에 붙여넣지 마십시오; 비활성 텍스트로 취급하세요. started_at 파일은 노출 기간의 경계를 정의합니다(감사자와 규제 기관이 이를 요청할 것입니다).

3. 제거(ERADICATE) — 먼저 워처 프로세스를 종료한 다음:

# macOS
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.user.gh-token-monitor.plist
rm -f ~/Library/LaunchAgents/com.user.gh-token-monitor.plist
도구 다운로드