SOC Prime Bias: 치명적

08 Jun 2026 19:43 UTC

사전 설치에서 지속성까지: Red Hat npm 미아즈마 자격 증명 탈취 캠페인 내부 분석

Author Photo
SOC Prime Team linkedin icon 팔로우
사전 설치에서 지속성까지: Red Hat npm 미아즈마 자격 증명 탈취 캠페인 내부 분석
shield icon

Detection stack

  • AIDR
  • Alert
  • ETL
  • Query

요약

Microsoft Defender는 이름하에 게시된 32개의 npm 패키지에 영향을 미치는 공급망 침해를 식별했습니다 @redhat-cloud-services 네임스페이스. 공격자는 심하게 난독화된 JavaScript 로더를 배포하는 사전 설치 후크를 삽입하여 Bun 런타임과 2단계 자격 증명 탈취기를 검색합니다. 이 악성코드는 GitHub, npm, 주요 클라우드 제공업체, HashiCorp Vault, Kubernetes에서 토큰을 수집한 후 오염된 패키지를 재게시하여 확산을 계속합니다. 이 캠페인은 또한 디코이 토큰이 감지되면 피해자의 홈 디렉토리를 삭제하는 파괴적인 안전 장치를 포함합니다.

조사

조사는 초기 침해가 RedHatInsights/javascript-clients의 CI/CD 파이프라인이 손상되어 발생했음을 추적했습니다. 여기서 공격자는 합법적인 GitHub Actions OIDC 워크플로우를 악용하여 유효한 출처 서명이 있는 트로이 목마화된 패키지를 게시했습니다. 드로퍼 분석은 Bun을 실행하여 2단계 페이로드를 시작하기 전에 여러 난독화 계층을 드러냈습니다. 여기에는 ROT 기반 인코딩, AES-128-GCM 암호화 및 사용자 지정 암호가 포함됩니다. 위협 행위자는 실행 중인 프로세스에서 직접 비밀을 추출할 수 있도록 GitHub Actions 러너의 메모리를 긁어모았습니다.

완화

Microsoft는 영향을 받은 @redhat-cloud-services 패키지에 대한 종속 트리를 검토하고 신뢰할 수 있는 버전을 고정하며 가능한 경우 --ignore-scripts 플래그로 npm 스크립트 실행을 비활성화할 것을 권장합니다. 모든 손상된 npm 토큰은 해지 및 재발급해야 하며, 무단 저장소 생성 또는 의심스러운 활동이 있는 GitHub 계정을 검토해야 합니다. 무단 게시를 방지하기 위해 네임스페이스 내에 추가 안전 장치가 구현되었습니다. @redhat-cloud-services namespace to prevent unauthorized publishing.

대응

수비수는 의심스러운 npm 사전 설치 실행 및 임시 디렉터리에서의 예기치 않은 Bun 런타임 실행을 탐지해야 합니다. 모니터링은 알 수 없는 공개 GitHub 리포지토리 생성 및 비정상적인 토큰 사용 패턴도 다뤄야 합니다. 네트워크 방어는 알려진 Bun 다운로드 URL 및 api.anthropic.com 도메인에 대한 연결을 차단하거나 경고해야 합니다. 노출 가능성이 있는 자격 증명은 즉시 회전되어야 하며, CI/CD 러너 메모리에서 유출된 비밀의 징후를 조사해야 합니다.

"graph TB %% Class Definitions classDef action fill:#99ccff classDef tool fill:#cccccc classDef malware fill:#ffcc99 classDef process fill:#ff9966 %% Nodes node_sc_001["<b>Action</b> – <b>T1195.001 Supply Chain Compromise</b>: Compromise Software Dependencies and Development Tools<br/>Attacker hijacked the RedHatInsights/javascript-clients CI/CD pipeline and used GitHub Actions OIDC to publish trojanized @redhat-cloud-services npm packages."] class node_sc_001 action tool_github_oidc["<b>Tool</b> – <b>Name</b>: GitHub Actions OIDC<br/><b>Description</b>: OpenID Connect integration that provides shortu2011lived tokens to CI workflows."] class tool_github_oidc tool malicious_preinstall["<b>Malware</b> – <b>T1127.003 Trusted Developer Utilities Proxy Execution</b>: Malicious preu2011install hook in package.json executed automatically during <code>npm install</code>, spawning <code>node index.js</code>."] class malicious_preinstall malware installer_trigger["<b>Action</b> – <b>T1546.016 Event Triggered Execution</b>: Installeru2011package trigger that runs the dropper when the preu2011install script is invoked."] class installer_trigger action obfuscated_payload["<b>Malware</b> – <b>T1027.009 Obfuscated Files or Information</b>: Embedded payload (4.29u202fMB index.js) using multiu2011layer ROT, AESu2011128u2011GCM, stringu2011array and custom PBKDF2 cipher to hide its code."] class obfuscated_payload malware dynamic_resolution["<b>Malware</b> – <b>T1027.007 Obfuscated Files or Information</b>: Dynamic API resolution u2013 runtime deobfuscation resolves URLs for the Bun runtime and C2 endpoints."] class dynamic_resolution malware ingress_transfer["<b>Action</b> – <b>T1105 Ingress Tool Transfer</b>: Dropper downloads the Bun JavaScript runtime from official release URLs before executing the secondu2011stage payload."] class ingress_transfer action tool_bun_runtime["<b>Tool</b> – <b>Name</b>: Bun JavaScript Runtime<br/><b>Description</b>: Highu2011performance JavaScript engine used as the execution environment for the second stage."] class tool_bun_runtime tool metadata_query["<b>Action</b> – <b>T1552.005 Unsecured Credentials</b>: Cloud Instance Metadata API<br/>Queries AWS/ECS, Azure IMDS and GCP metadata services to obtain cloud access tokens."] class metadata_query action file_credential["<b>Action</b> – <b>T1552.001 Unsecured Credentials</b>: Credentials In Files<br/>Scrapes local files for SSH keys, CLI configs, cryptocurrency wallet files and other secret material."] class file_credential action token_harvest["<b>Action</b> – <b>T1528 Steal Application Access Token</b>: Harvests GitHub Actions runner tokens, npm OIDC tokens and other provider tokens."] class token_harvest action browser_discovery["<b>Action</b> – <b>T1217 Browser Information Discovery</b>: Collects browser stores and cryptocurrency wallet files from developer workstations."] class browser_discovery action elevation_control["<b>Action</b> – <b>T1548 Abuse Elevation Control Mechanism</b>: Installs a passwordu2011less sudo rule via a bindu2011mounted <code>/etc/sudoers.d</code> to gain root privileges."] class elevation_control action exfiltration_git["<b>Action</b> – <b>T1048 Exfiltration Over Alternative Protocol</b>: Exfiltrates stolen credentials by creating GitHub repositories under the victimu2019s account, committing JSON files, and also uses an alternate HTTPS endpoint."] class exfiltration_git action destructive_cleanup["<b>Action</b> – <b>T1070.010 Indicator Removal</b>: Relocates malware and, if a decoy token was used, executes <code>rm -rf ~/</code> to wipe the useru2019s home directory."] class destructive_cleanup action node_sc_002["<b>Action</b> – <b>T1195.002 Supply Chain Compromise</b>: Compromise Software Supply Chain u2013 republished poisoned packages with forged SLSA provenance, enabling wormu2011like propagation to downstream projects."] class node_sc_002 action %% Connections node_sc_001 –>|uses| tool_github_oidc tool_github_oidc –>|executes| malicious_preinstall malicious_preinstall –>|triggers| installer_trigger installer_trigger –>|executes| obfuscated_payload obfuscated_payload –>|performs| dynamic_resolution dynamic_resolution –>|downloads| ingress_transfer ingress_transfer –>|installs| tool_bun_runtime tool_bun_runtime –>|queries| metadata_query metadata_query –>|scrapes| file_credential file_credential –>|harvests| token_harvest token_harvest –>|collects| browser_discovery browser_discovery –>|enables| elevation_control elevation_control –>|exfiltrates via| exfiltration_git exfiltration_git –>|may trigger| destructive_cleanup destructive_cleanup –>|facilitates| node_sc_002 node_sc_002 –>|propagates to| node_sc_001 "

공격 흐름

시뮬레이션 실행

필수사항: Telemetry & Baseline Pre‑flight 검사에 통과해야 합니다.

사유: 이 섹션은 탐지 규칙을 일으키기 위해 설계된 적대자의 기술적 전술 (TTP)의 정확한 실행을 상세히 설명합니다. 명령어와 서술은 확인된 TTP를 직접 반영해야 하며 탐지 논리가 기대하는 정확한 원격 측정을 생성하는 것을 목표로 해야 합니다.

  • 공격 서술 & 명령어:
    이미 GCE VM을 손상시킨 적이 있는 공격자는 VM의 기본 서비스 계정 토큰을 수확하기 위해 자족형 (living‑off‑the‑land) 접근법을 사용합니다. 단계는 다음과 같습니다:

    1. 메타데이터 서버를 프로브하여 접근이 가능한지 확인합니다.
    2. 토큰 요청을 발행합니다 to http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token 필요한 Metadata-Flavor: Google 헤더와 함께.
    3. 반환된 JSON을 저장합니다 (다음 내용을 포함합니다 access_token, expires_in, token_type).
    4. 토큰을 사용하여 행동할 수 있는 자격 증명을 증명하기 위해 특권 GCP API 예를 들어, 모든 버킷 나열을 호출합니다.

    이 정확한 순서는 Sigma 규칙의 GCPServiceAccountTokenAccess와 일치하는 선택.

  • 회귀 테스트 스크립트:

    #!/usr/bin/env bash
    set -euo pipefail
    
    # 1. Verify metadata server reachability
    echo "[*] Probing metadata server..."
    curl -s -H "Metadata-Flavor: Google" 
      "http://metadata.google.internal/computeMetadata/v1/instance/id" >/dev/null
    
    # 2. Harvest the default service‑account token
    echo "[*] Requesting service‑account token..."
    TOKEN_RESPONSE=$(curl -s -H "Metadata-Flavor: Google" 
      "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token")
    
    echo "[+] Token response received:"
    echo "${TOKEN_RESPONSE}" | jq .
    
    # 3. Extract the access token
    ACCESS_TOKEN=$(echo "${TOKEN_RESPONSE}" | jq -r '.access_token')
    
    # 4. Use the token to list GCS buckets (demonstrates token utility)
    echo "[*] Using token to list GCS buckets..."
    curl -s -H "Authorization: Bearer ${ACCESS_TOKEN}" 
      "https://storage.googleapis.com/storage/v1/b" | jq .
    
    echo "[+] Simulation complete. The above actions should have produced a GCPServiceAccountTokenAccess audit event."
  • 정리 명령어:

    # No persistent changes were made; only removing temporary variables.
    unset TOKEN_RESPONSE ACCESS_TOKEN
    echo "[*] Cleanup complete."