Skip to content

Instantly share code, notes, and snippets.

@Qwizi
Created April 1, 2026 09:13
Show Gist options
  • Select an option

  • Save Qwizi/f6a83dee93f2b2698d9725c113b407de to your computer and use it in GitHub Desktop.

Select an option

Save Qwizi/f6a83dee93f2b2698d9725c113b407de to your computer and use it in GitHub Desktop.
check_axios.ps1
# ============================================================================
# Axios Supply-Chain Compromise Scanner — Windows (PowerShell)
# Date: 2026-03-31
# Based on: https://gist.github.com/joe-desimone/36061dabd2bc2913705e0d083a9673e7
#
# Sprawdza:
# 1. Skompromitowane wersje axios (1.14.1, 0.30.4) w lockfiles i node_modules
# 2. Złośliwy pakiet "plain-crypto-js"
# 3. Stage-2 payload IOCs (wt.exe, .vbs, .ps1)
# 4. Aktywne połączenia C2 do sfrclak.com
# 5. Globalne pakiety npm/yarn/pnpm
# 6. Zanieczyszczenie cache npm
#
# Użycie:
# .\Scan-AxiosCompromise.ps1 # skanuje $HOME
# .\Scan-AxiosCompromise.ps1 -ScanRoot C:\Projects # wybrany katalog
#
# Wymagania: PowerShell 5.1+ (lub PowerShell 7+)
# ============================================================================
param(
[string]$ScanRoot = $env:USERPROFILE
)
$ErrorActionPreference = "SilentlyContinue"
$script:FoundIssues = 0
# ── Kolory ──────────────────────────────────────────────────────────────────
function Write-Banner {
Write-Host ""
Write-Host "========================================" -ForegroundColor White
Write-Host " Axios Compromise Scanner (2026-03-31)" -ForegroundColor White
Write-Host "========================================" -ForegroundColor White
Write-Host ""
}
function Write-Section($text) {
Write-Host ""
Write-Host "[*] $text" -ForegroundColor Cyan
Write-Host ("-" * 50) -ForegroundColor Cyan
}
function Write-Found($text) {
Write-Host "[!!!] FOUND: $text" -ForegroundColor Red
$script:FoundIssues++
}
function Write-Warn($text) {
Write-Host "[!] WARNING: $text" -ForegroundColor Yellow
}
function Write-Safe($text) {
Write-Host "[OK] $text" -ForegroundColor Green
}
function Write-Info($text) {
Write-Host " $text"
}
# ============================================================================
# 1. FILESYSTEM IOCs — Stage-2 Payloads (Windows)
# ============================================================================
Write-Banner
Write-Host "Platform: Windows"
Write-Host "Scan root: $ScanRoot"
Write-Host "Date: $(Get-Date -Format 'yyyy-MM-ddTHH:mm:ssZ' -AsUTC)"
Write-Section "Sprawdzanie stage-2 payload IOCs na dysku"
$ProgramData = $env:ProgramData
$TempDir = $env:TEMP
$iocFiles = @(
"$ProgramData\wt.exe",
"$TempDir\6202033.vbs",
"$TempDir\6202033.ps1"
)
$iocFound = $false
foreach ($f in $iocFiles) {
if (Test-Path $f) {
Write-Found "Windows IOC: $f"
Get-Item $f | Select-Object FullName, Length, LastWriteTime | Format-List
$iocFound = $true
}
}
if (-not $iocFound) {
Write-Safe "Brak stage-2 IOCs (wt.exe, 6202033.vbs, 6202033.ps1)"
}
# ============================================================================
# 2. SIEĆ — Aktywne połączenia C2
# ============================================================================
Write-Section "Sprawdzanie aktywnych połączeń do C2 (sfrclak.com)"
# Rozwiąż IP domeny C2
$c2Domain = "sfrclak.com"
$c2IPs = @()
try {
$c2IPs = [System.Net.Dns]::GetHostAddresses($c2Domain) | ForEach-Object { $_.IPAddressToString }
if ($c2IPs) {
Write-Info "Domena C2 $c2Domain rozwiązuje się do: $($c2IPs -join ', ')"
Write-Info "Sprawdź logi DNS/firewall pod kątem połączeń do tych IP"
}
} catch {
Write-Info "Nie udało się rozwiązać $c2Domain (może być już zablokowany — dobrze)"
}
# Sprawdź aktywne połączenia TCP
$c2Active = $false
$netConns = Get-NetTCPConnection -State Established, TimeWait, CloseWait 2>$null
foreach ($conn in $netConns) {
$remoteIP = $conn.RemoteAddress
if ($c2IPs -contains $remoteIP) {
Write-Found "Aktywne połączenie do C2 ($c2Domain / $remoteIP)!"
Write-Info " LocalPort=$($conn.LocalPort) RemotePort=$($conn.RemotePort) State=$($conn.State)"
# Spróbuj zidentyfikować proces
$proc = Get-Process -Id $conn.OwningProcess 2>$null
if ($proc) { Write-Info " Proces: $($proc.Name) (PID $($proc.Id))" }
$c2Active = $true
}
}
# Sprawdź też po nazwie hosta w DNS cache
$dnsCache = Get-DnsClientCache 2>$null | Where-Object { $_.Entry -match "sfrclak" }
if ($dnsCache) {
Write-Warn "sfrclak.com znaleziony w lokalnym cache DNS — połączenie mogło mieć miejsce!"
$dnsCache | Format-Table Entry, RecordName, Data -AutoSize
}
if (-not $c2Active) {
Write-Safe "Brak aktywnych połączeń do C2"
}
# ============================================================================
# 3. GLOBALNE PAKIETY npm / yarn / pnpm
# ============================================================================
Write-Section "Sprawdzanie globalnie zainstalowanych pakietów npm"
function Test-GlobalPackage($listOutput, $pkgPattern, $manager) {
$matches = $listOutput | Select-String $pkgPattern
if ($matches) {
Write-Found "$pkgPattern znaleziony w globalnych pakietach $manager!"
$matches | ForEach-Object { Write-Info " $_" }
}
}
# npm
if (Get-Command npm -ErrorAction SilentlyContinue) {
Write-Info "Skanowanie globalnych pakietów npm..."
$npmGlobal = npm list -g --depth=0 2>$null
Test-GlobalPackage $npmGlobal "axios@1\.14\.1" "npm"
Test-GlobalPackage $npmGlobal "axios@0\.30\.4" "npm"
Test-GlobalPackage $npmGlobal "plain-crypto-js" "npm"
$npmGlobalDeep = npm list -g --all 2>$null
if ($npmGlobalDeep | Select-String "plain-crypto-js") {
Write-Found "plain-crypto-js jako tranzytywna zależność globalnych pakietów npm!"
}
$npmRoot = (npm root -g 2>$null)
if ($npmRoot -and (Test-Path "$npmRoot\plain-crypto-js")) {
Write-Found "Katalog plain-crypto-js istnieje: $npmRoot\plain-crypto-js"
}
if ($npmRoot -and (Test-Path "$npmRoot\axios\package.json")) {
$axiosVer = node -p "require('$($npmRoot.Replace('\','/'))/axios/package.json').version" 2>$null
if ($axiosVer -in "1.14.1","0.30.4") {
Write-Found "Skompromitowana globalna wersja axios: $axiosVer"
} else {
Write-Safe "Globalna wersja axios: $axiosVer (bezpieczna)"
}
}
} else {
Write-Warn "npm nie znaleziony, pomijam skan globalnych pakietów npm"
}
# yarn
if (Get-Command yarn -ErrorAction SilentlyContinue) {
Write-Info "Skanowanie globalnych pakietów yarn..."
$yarnGlobal = yarn global list 2>$null
Test-GlobalPackage $yarnGlobal "axios@1\.14\.1" "yarn"
Test-GlobalPackage $yarnGlobal "axios@0\.30\.4" "yarn"
Test-GlobalPackage $yarnGlobal "plain-crypto-js" "yarn"
}
# pnpm
if (Get-Command pnpm -ErrorAction SilentlyContinue) {
Write-Info "Skanowanie globalnych pakietów pnpm..."
$pnpmGlobal = pnpm list -g 2>$null
Test-GlobalPackage $pnpmGlobal "axios@1\.14\.1" "pnpm"
Test-GlobalPackage $pnpmGlobal "axios@0\.30\.4" "pnpm"
Test-GlobalPackage $pnpmGlobal "plain-crypto-js" "pnpm"
}
# ============================================================================
# 4. CACHE npm
# ============================================================================
Write-Section "Sprawdzanie cache npm pod kątem skompromitowanych pakietów"
if (Get-Command npm -ErrorAction SilentlyContinue) {
$npmCacheDir = (npm config get cache 2>$null)
if ($npmCacheDir -and (Test-Path "$npmCacheDir\_cacache")) {
Write-Info "Skanowanie $npmCacheDir\_cacache ..."
$cacheHits = Get-ChildItem "$npmCacheDir\_cacache" -Recurse -Filter "*.json" -ErrorAction SilentlyContinue |
Select-String "plain-crypto-js" -ErrorAction SilentlyContinue |
Select-Object -First 20 -ExpandProperty Path
if ($cacheHits) {
Write-Warn "plain-crypto-js znaleziony w cache npm (mogło mieć miejsce wcześniej):"
$cacheHits | ForEach-Object { Write-Info " $_" }
Write-Info "Zalecenie: npm cache clean --force"
} else {
Write-Safe "Cache npm czysty (brak plain-crypto-js)"
}
}
}
# ============================================================================
# 5. LOCKFILES — Skanowanie projektów
# ============================================================================
Write-Section "Skanowanie lockfiles w $ScanRoot ..."
$lockfileCount = 0
$lockfileNames = @("package-lock.json","yarn.lock","pnpm-lock.yaml")
$lockfiles = Get-ChildItem -Path $ScanRoot -Recurse -Include $lockfileNames `
-ErrorAction SilentlyContinue -Depth 8 |
Where-Object { $_.FullName -notmatch "\\node_modules\\" -and $_.FullName -notmatch "\\.git\\" }
foreach ($lf in $lockfiles) {
$hit = $false
$content = Get-Content $lf.FullName -Raw -ErrorAction SilentlyContinue
if ($content -match "axios@1\.14\.1" -or ($content -match '"1\.14\.1"' -and $content -match '"axios"')) {
Write-Found "axios@1.14.1 w $($lf.FullName)"
$hit = $true
}
if ($content -match "axios@0\.30\.4" -or ($content -match '"0\.30\.4"' -and $content -match '"axios"')) {
Write-Found "axios@0.30.4 w $($lf.FullName)"
$hit = $true
}
if ($content -match "plain-crypto-js") {
Write-Found "plain-crypto-js w $($lf.FullName) — TEN PAKIET JEST ZŁOŚLIWY"
$hit = $true
}
if (-not $hit) { $lockfileCount++ }
}
Write-Safe "$lockfileCount lockfiles przeskanowanych bez znalezisk"
# ============================================================================
# 6. NODE_MODULES — Bezpośrednia inspekcja
# ============================================================================
Write-Section "Skanowanie katalogów node_modules"
$nmDirs = Get-ChildItem -Path $ScanRoot -Recurse -Filter "node_modules" `
-Directory -ErrorAction SilentlyContinue -Depth 7 |
Where-Object { $_.FullName -notmatch "\\node_modules\\node_modules" }
$nmScanned = 0
foreach ($nm in $nmDirs) {
$nmScanned++
$nmPath = $nm.FullName
# plain-crypto-js
if (Test-Path "$nmPath\plain-crypto-js") {
Write-Found "plain-crypto-js zainstalowany w $nmPath\plain-crypto-js"
if (Test-Path "$nmPath\plain-crypto-js\setup.js") {
Write-Found "setup.js NADAL OBECNY — payload nie został wyczyszczony!"
}
$pcjPkg = "$nmPath\plain-crypto-js\package.json"
if (Test-Path $pcjPkg) {
$pcjContent = Get-Content $pcjPkg -Raw
if ($pcjContent -match "postinstall") {
Write-Found "package.json zawiera hak postinstall (payload nie wykonał się jeszcze?)"
} else {
Write-Warn "package.json BEZ postinstall — prawdopodobnie podmieniony (payload już wykonał się na tym systemie!)"
}
}
}
# axios
$axiosPkg = "$nmPath\axios\package.json"
if (Test-Path $axiosPkg) {
$axiosVer = node -p "try{require('$(($axiosPkg).Replace('\','/'))').version}catch(e){'err'}" 2>$null
if ($axiosVer -in "1.14.1","0.30.4") {
Write-Found "Skompromitowany axios@$axiosVer w $nmPath\axios\"
$axiosContent = Get-Content $axiosPkg -Raw
if ($axiosContent -match "plain-crypto-js") {
Write-Found "Ten axios ma plain-crypto-js jako zależność — POTWIERDZONY KOMPROMIS"
}
}
}
}
Write-Safe "$nmScanned katalogów node_modules przeskanowanych"
# ============================================================================
# 7. URUCHOMIONE PROCESY
# ============================================================================
Write-Section "Sprawdzanie uruchomionych procesów"
$suspiciousPatterns = @("com.apple.act.mond","ld.py","6202033","sfrclak","wt")
$procHit = $false
$processes = Get-Process -ErrorAction SilentlyContinue
foreach ($pattern in $suspiciousPatterns) {
$matches = $processes | Where-Object { $_.Name -match $pattern -or $_.Path -match $pattern }
if ($matches) {
foreach ($m in $matches) {
Write-Found "Podejrzany proces pasujący do '$pattern': $($m.Name) (PID $($m.Id)) — $($m.Path)"
$procHit = $true
}
}
}
# Sprawdź też procesy node.js uruchamiające podejrzane skrypty
$nodeProcs = $processes | Where-Object { $_.Name -eq "node" }
foreach ($np in $nodeProcs) {
try {
$cmdLine = (Get-CimInstance Win32_Process -Filter "ProcessId = $($np.Id)").CommandLine
if ($cmdLine -match "sfrclak|plain-crypto|6202033") {
Write-Found "Podejrzana linia poleceń node.js: $cmdLine"
$procHit = $true
}
} catch {}
}
if (-not $procHit) {
Write-Safe "Brak podejrzanych procesów"
}
# ============================================================================
# 8. HISTORIA POWERSHELL (informacyjnie)
# ============================================================================
Write-Section "Sprawdzanie historii PowerShell (informacyjnie)"
$histFile = (Get-PSReadlineOption 2>$null).HistorySavePath
if (-not $histFile) {
$histFile = "$env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt"
}
if (Test-Path $histFile) {
$recentInstalls = Get-Content $histFile |
Where-Object { $_ -match "npm install|npm i |yarn add|pnpm add|bun add|bun install" } |
Select-Object -Last 10
if ($recentInstalls) {
Write-Info "Ostatnie komendy instalacji pakietów:"
$recentInstalls | ForEach-Object { Write-Info " $_" }
}
}
# ============================================================================
# PODSUMOWANIE
# ============================================================================
Write-Host ""
Write-Host "========================================" -ForegroundColor White
Write-Host " SKAN ZAKOŃCZONY" -ForegroundColor White
Write-Host "========================================" -ForegroundColor White
Write-Host ""
if ($script:FoundIssues -gt 0) {
Write-Host "⚠️ $($script:FoundIssues) PROBLEM(Y) ZNALEZIONY — SYSTEM MOŻE BYĆ SKOMPROMITOWANY" -ForegroundColor Red
Write-Host ""
Write-Host "Natychmiastowe działania:" -ForegroundColor Yellow
Write-Host " 1. Odłącz się od sieci jeśli znaleziono stage-2 IOCs"
Write-Host " 2. Usuń skompromitowany axios: npm uninstall axios && npm install axios@1.14.0"
Write-Host " 3. Usuń plain-crypto-js ze wszystkich node_modules"
Write-Host " 4. Usuń payloady stage-2:"
Write-Host " del `"$env:ProgramData\wt.exe`""
Write-Host " del `"$env:TEMP\6202033.vbs`""
Write-Host " del `"$env:TEMP\6202033.ps1`""
Write-Host " 5. Wyczyść cache npm: npm cache clean --force"
Write-Host " 6. ZMIEŃ WSZYSTKIE DANE DOSTĘPOWE — tokeny, klucze API, hasła, klucze SSH"
Write-Host " 7. Zablokuj sfrclak.com na DNS/firewall"
Write-Host " 8. Sprawdź pipeline CI/CD pod kątem tego samego kompromisu"
} else {
Write-Host "✅ Brak wskaźników kompromisu." -ForegroundColor Green
Write-Host ""
Write-Host "Zalecenia prewencyjne:"
Write-Host " • Przypnij axios do wersji 1.14.0 w lockfiles"
Write-Host " • Uruchom: npm audit"
Write-Host " • Rozważ --ignore-scripts dla niezaufanych instalacji"
Write-Host " • Zablokuj sfrclak.com na DNS/firewall prewencyjnie"
}
Write-Host ""
Write-Host "Skan zakończony: $(Get-Date -Format 'yyyy-MM-ddTHH:mm:ssZ' -AsUTC)"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment