Packj (paquete pronunciado) es una herramienta para ayudar a mitigar los ataques de la cadena de suministro de software. Puede detectar paquetes maliciosos, vulnerables, abandonados, tipográficos y otros paquetes "riesgosos" de registros populares de paquetes de código abierto, como NPM, Rubygems y Pypi. Se puede personalizar fácilmente para minimizar el ruido. Packj comenzó como un proyecto de investigación de doctorado y actualmente se está desarrollando bajo varias subvenciones del gobierno.
¿Tenga en cuenta que el servidor web de Packj autohospedado y varias integraciones que llegarán a finales de este mes? Mire este repositorio para mantenerse actualizado.
Admitimos múltiples modelos de implementación:
Use PackJ para auditoría de dependencias en solicitudes de extracción.
- name : Packj Security Audit
uses : ossillate-inc/[email protected]
with :
# TODO: replace with your dependency files in the repo
DEPENDENCY_FILES : pypi:requirements.txt,npm:package.json,rubygems:Gemfile
REPO_TOKEN : ${{ secrets.GITHUB_TOKEN }}Vista sobre el mercado de Github. Ejemplo de ejecución PR.
La forma más rápida de probar/probar Packj es usar Docker. Podman también es compatible con las ejecuciones contenedores (aisladas).
docker run -v /tmp:/tmp/packj -it ossillate/packj:latest --help
Clon este repositorio,
git clone https://github.com/ossillate-inc/packj.git && cd packj
Instalar dependencias
bundle install && pip3 install -r requirements.txt
Comience con ayuda:
python3 main.py --help
Packj puede examinar los paquetes pubsed de NPM, PYPI, Rust, PHP y Rubygems Package Regsies. El soporte de óxido y PHP es WIP. Estamos agregando activamente apoyo para los registros. También es compatible con los paquetes de NPM y PYPI locales (inéditos).
| Registro | Ecosistema | Compatible |
|---|---|---|
| Npm | Javascript | ✅ |
| Pypi | Pitón | ✅ |
| Carga | Óxido | ✅ |
| Rubygems | Rubí | ✅ |
| Paquete | Php | ✅ |
| Estibador | Estibador | |
| Nuget | .NETO | ✅ |
| Aturdir | Java | ✅ |
| Cocoapods | Rápido |
Packj ofrece las siguientes herramientas:
Packj audita paquetes de software de código abierto para atributos "riesgosos" que los hacen vulnerables a los ataques de la cadena de suministro. Por ejemplo, los paquetes con dominios de correo electrónico vencidos (carentes de 2FA), una gran brecha de tiempo de liberación, API confidenciales o permisos de acceso, etc., se marcan como riesgosos.
Auditar lo siguiente es compatible:
python3 main.py audit -p pypi:requests rubygems:overcommitpython3 main.py audit -f npm:package.json pypi:requirements.txt Por defecto, audit solo realiza un análisis de código estático para detectar código de riesgo. También puede realizar un análisis PAAS -t o --trace para realizar un análisis de código dinámico, que instalará todos los paquetes solicitados en Strace y monitorear el comportamiento de los paquetes de tiempo de instalación. Consulte la salida de ejemplo a continuación.
$ docker run -v /tmp:/tmp/packj -it ossillate/packj:latest audit --trace -p npm:browserify
[+] Fetching 'browserify' from npm..........PASS [ver 17.0.0]
[+] Checking package description.........PASS [browser-side require() the node way]
[+] Checking release history.............PASS [484 version(s)]
[+] Checking version........................RISK [702 days old]
[+] Checking release time gap............PASS [68 days since last release]
[+] Checking author.........................PASS [[email protected]]
[+] Checking email/domain validity.......RISK [expired author email domain]
[+] Checking readme.........................PASS [26838 bytes]
[+] Checking homepage.......................PASS [https://github.com/browserify/browserify#readme]
[+] Checking downloads......................PASS [2M weekly]
[+] Checking repo URL.......................PASS [https://github.com/browserify/browserify]
[+] Checking repo data...................PASS [stars: 14189, forks: 1244]
[+] Checking if repo is a forked copy....PASS [original, not forked]
[+] Checking repo description............PASS [browser-side require() the node.js way]
[+] Checking repo activity...............PASS [commits: 2290, contributors: 207, tags: 413]
[+] Checking for CVEs.......................PASS [none found]
[+] Checking dependencies...................RISK [48 found]
[+] Downloading package from npm............PASS [163.83 KB]
[+] Analyzing code..........................RISK [needs 3 perm(s): decode,codegen,file]
[+] Checking files/funcs....................PASS [429 files (383 .js), 744 funcs, LoC: 9.7K]
[+] Installing package and tracing code.....PASS [found 5 process,1130 files,22 network syscalls]
=============================================
[+] 5 risk(s) found, package is undesirable!
=> Complete report: /tmp/packj_54rbjhgm/report_npm-browserify-17.0.0_hlr1rhcz.json
{
"undesirable": [
"old package: 702 days old",
"invalid or no author email: expired author email domain",
"generates new code at runtime",
"reads files and dirs",
"forks or exits OS processes",
]
}
ADVERTENCIA: Dado que los paquetes pueden ejecutar código malicioso durante la instalación, se recomienda usar solo
-to--tracecuando se ejecuta dentro de un contenedor Docker o una máquina virtual.
La auditoría también se puede realizar en contenedores Docker/Podman. Encuentre detalles sobre atributos arriesgados y cómo usar en Audit ReadMe.
Packj ofrece un sandboxing liviano para safe installation de un paquete. Específicamente, evita que los paquetes maliciosos exfiltren datos confidenciales, acceda a archivos confidenciales (por ejemplo, claves SSH) y malware persistente.
Sandboxes de instalación de scripts de tiempo, incluida cualquier cumplimiento nativo. Utiliza Strace (es decir, no se requiere VM/Contenedor).
Encuentre detalles sobre el mecanismo de sandboxing y cómo usar en Sandbox ReadMe.
$ python3 main.py sandbox gem install overcommit
Fetching: overcommit-0.59.1.gem (100%)
Install hooks by running `overcommit --install` in your Git repository
Successfully installed overcommit-0.59.1
Parsing documentation for overcommit-0.59.1
Installing ri documentation for overcommit-0.59.1
#############################
# Review summarized activity
#############################
[+] Network connections
[+] DNS (1 IPv4 addresses) at port 53 [rule: ALLOW]
[+] rubygems.org (4 IPv6 addresses) at port 443 [rule: IPv6 rules not supported]
[+] rubygems.org (4 IPv4 addresses) at port 443 [rule: ALLOW]
[+] Filesystem changes
/
└── home
└── ubuntu
└── .ruby
├── gems
│ ├── iniparse-1.5.0 [new: DIR, 15 files, 46.6K bytes]
│ ├── rexml-3.2.5 [new: DIR, 77 files, 455.6K bytes]
│ ├── overcommit-0.59.1 [new: DIR, 252 files, 432.7K bytes]
│ └── childprocess-4.1.0 [new: DIR, 57 files, 141.2K bytes]
├── cache
│ ├── iniparse-1.5.0.gem [new: FILE, 16.4K bytes]
│ ├── rexml-3.2.5.gem [new: FILE, 93.2K bytes]
│ ├── childprocess-4.1.0.gem [new: FILE, 34.3K bytes]
│ └── overcommit-0.59.1.gem [new: FILE, 84K bytes]
├── specifications
│ ├── rexml-3.2.5.gemspec [new: FILE, 2.7K bytes]
│ ├── overcommit-0.59.1.gemspec [new: FILE, 1.7K bytes]
│ ├── childprocess-4.1.0.gemspec [new: FILE, 1.8K bytes]
│ └── iniparse-1.5.0.gemspec [new: FILE, 1.3K bytes]
├── bin
│ └── overcommit [new: FILE, 622 bytes]
└── doc
├── iniparse-1.5.0
│ └── ri [new: DIR, 119 files, 131.7K bytes]
├── rexml-3.2.5
│ └── ri [new: DIR, 836 files, 841K bytes]
├── overcommit-0.59.1
│ └── ri [new: DIR, 1046 files, 1.5M bytes]
└── childprocess-4.1.0
└── ri [new: DIR, 272 files, 297.8K bytes]
[C]ommit all changes, [Q|q]uit & discard changes, [L|l]ist details:
TL; Dr Packj comenzó como un proyecto de investigación de doctorado. Está respaldado por varias subvenciones del gobierno.
Packj comenzó como un proyecto de investigación académica. Específicamente, las técnicas de análisis de código estático utilizados por PackJ se basan en la investigación de ciberseguridad de vanguardia: Proyecto Maloss de nuestro grupo de investigación en Georgia Tech.
Packj está respaldado por generosas subvenciones de NSF, GRA y Alinnovate.
Tl; dr Los escáneres de vulnerabilidad de vanguardia suponen que el código de código abierto de terceros es benigno. Por lo tanto, todas estas herramientas solo abordan las amenazas de los errores de programación accidentales en código benigno (también conocido como CVE como log4j). No protegen contra los ataques de la cadena de suministro de software moderno similar a SolarWinds del código deliberadamente malo (también conocido como malicioso) que es propagado por malos actores que utilizan nuevas vulnerabilidades en el canal de suministro, incluida la confusión de dependencia, el tipográfico tipográfico, el protestado (sabotaje), el secuestro de cuentas y la ingeniería social. Un ejemplo reciente (diciembre22) es el paquete Pytorch que se vio comprometido utilizando la vulnerabilidad de confusión de dependencia (sin CVE asignado).
Packj no solo auditoría para CVE, sino que también realiza un análisis de código dinámico STATIC+profundo, así como a las verificaciones de metadatos para detectar cualquier comportamiento y atributo "riesgoso", como el desove de shell, el uso de claves SSH, desajuste del código Github frente al código empaquetado (procedencia), falta de 2FA y varios más. Tales atributos inseguros no califican como CVE, por lo que ninguna de las herramientas existentes puede marcarlos. PACKJ puede marcar las dependencias maliciosas, escritas por error tipográfico, abandonado, vulnerable y otras dependencias inseguras (enlaces débiles) en su cadena de suministro de software.
El modelo actual de amenaza de la cadena de suministro de software supone que el código de código abierto de terceros es benigno y, por lo tanto, las vulnerabilidades de seguridad solo se rastrean para errores de programación accidentales (también conocidos como CVE). Como tal, todos los escáneres de vulnerabilidad de código abierto existentes solo informan CVE conocidos públicamente y abordan las amenazas de errores accidentales en código benigno.
Un ejemplo típico de un error de programación accidental es una verificación de límites faltantes en la entrada del usuario, lo que hace que el código sea vulnerable a los ataques de desbordamiento del búfer. Los ejemplos populares del mundo real incluyen Log4J y Heartbleed. Los atacantes deben desarrollar una exploit para activar CVE (por ejemplo, un paquete TCP/IP diseñado en caso de entrada de corazón o una entrada numéricamente alta para causar el desbordamiento del búfer). CVE se puede solucionar parchando o actualizando a una versión más nueva de la biblioteca (por ejemplo, la versión más nueva de LOG4J corrige la CVE).
El panorama de amenazas de la cadena de suministro de software moderna cambió después del ataque de Solarwinds. Los malos actores han encontrado nuevas vulnerabilidades, pero esta vez en el canal de suministro, no en el código. Estas nuevas vulnerabilidades, como la confusión de dependencia, el error tipográfico, el protestado (sabotaje), el secuestro de cuentas y la ingeniería social se están explotando para propagar malware. Se han informado miles de paquetes comprometidos de NPM/PYPI/Ruby.
A diferencia de CVE, el malware es deliberadamente malo (también conocido como malicioso). Además, el malware en sí es un exploit y no se puede parchear o solucionar actualizando a una versión más nueva. Por ejemplo, el ataque de confusión de dependencia fue intencionalmente malicioso; No explotó ningún error de programación accidental en el código. Del mismo modo, un autor del paquete popular saboteando su propio código para protestar contra la guerra es muy intencional y no explota ningún CVE. El tipográfico tipográfico es otro vector de ataque que usan los malos actores para propagar malware en los populares registros de paquetes de código abierto: explota errores tipográficos e inexperiencia de los desarrolladores, no errores de programación accidentales o CVE en el código.
Los escáneres existentes no pueden detectar estos ataques de cadena de suministro de software moderno similar a SolarWinds del código deliberadamente vulnerable (malicioso). Estas herramientas simplemente escanean el código fuente para dependencias de código abierto, compilan una lista de todas las dependencias que se utilizan y busquen cada uno <name de dependencia, dependencia-versión> en una base de datos (por ejemplo, NVD) para informar las versiones de paquetes afectadas (por ejemplo, la versión vulnerable de Log4J, la versión LIBSSL afectada por HeartLeed).
Packj no solo auditoría para CVE, sino que también realiza un análisis de código dinámico STATIC+profundo, así como a las verificaciones de metadatos para detectar cualquier comportamiento y atributo "riesgoso", como el desove de shell, el uso de claves SSH, desajuste del código Github frente al código empaquetado (procedencia), falta de 2FA y varios más. Tales atributos inseguros no califican como CVE, por lo que ninguna de las herramientas existentes puede marcarlos. PACKJ puede marcar las dependencias maliciosas, escritas por error tipográfico, abandonado, vulnerable y otras dependencias inseguras (enlaces débiles) en su cadena de suministro de software. Lea más en Audit ReadMe
Packj se puede personalizar fácilmente (ruido cero) a su modelo de amenaza. Simplemente agregue un archivo .packj.yaml en el director superior de su repositorio/proyecto y reduzca la fatiga alerta comentando atributos no deseados.
Encontramos más de 40 y 20 paquetes maliciosos en PYPI y Rubygems, respectivamente utilizando esta herramienta. Algunos de ellos fueron derribados. Consulte un ejemplo a continuación:
$ python3 main.py audit pypi:krisqian
[+] Fetching 'krisqian' from pypi...OK [ver 0.0.7]
[+] Checking version...OK [256 days old]
[+] Checking release history...OK [7 version(s)]
[+] Checking release time gap...OK [1 days since last release]
[+] Checking author...OK [[email protected]]
[+] Checking email/domain validity...OK [[email protected]]
[+] Checking readme...ALERT [no readme]
[+] Checking homepage...OK [https://www.bilibili.com/bangumi/media/md140632]
[+] Checking downloads...OK [13 weekly]
[+] Checking repo_url URL...OK [None]
[+] Checking for CVEs...OK [none found]
[+] Checking dependencies...OK [none found]
[+] Downloading package 'KrisQian' (ver 0.0.7) from pypi...OK [1.94 KB]
[+] Analyzing code...ALERT [needs 3 perms: process,network,file]
[+] Checking files/funcs...OK [9 files (2 .py), 6 funcs, LoC: 184]
=============================================
[+] 6 risk(s) found, package is undesirable!
{
"undesirable": [
"no readme",
"only 45 weekly downloads",
"no source repo found",
"generates new code at runtime",
"fetches data over the network: ['KrisQian-0.0.7/setup.py:40', 'KrisQian-0.0.7/setup.py:50']",
"reads files and dirs: ['KrisQian-0.0.7/setup.py:59', 'KrisQian-0.0.7/setup.py:70']"
]
}
=> Complete report: pypi-KrisQian-0.0.7.json
=> View pre-vetted package report at https://packj.dev/package/PyPi/KrisQian/0.0.7
Packj marcó a Krisqian (V0.0.7) como sospechoso debido a la ausencia de repositorio de origen y el uso de API confidenciales (red, generación de código) durante el tiempo de instalación del paquete (en Setup.py). Decidimos dar un aspecto más profundo y encontramos el paquete malicioso. Encuentre nuestro análisis detallado en https://packj.dev/malware/krisqian.
Más ejemplos de malware que encontramos se enumeran en https://packj.dev/malware, comuníquese con nosotros a [email protected] para obtener una lista completa.
Para obtener más información sobre la herramienta Packj o los ataques de la cadena de suministro de software de código abierto, consulte nuestros
Mirar ? Este repositorio para mantenerse al día.
¿Tiene una función o solicitud de soporte? Visite nuestra página de discusión de GitHub o únase a nuestra comunidad de Discord para discusión y solicitudes.
Packj ha sido desarrollado por investigadores de ciberseguridad en Ossillate Inc. y colaboradores externos para ayudar a los desarrolladores a mitigar los riesgos de los ataques de la cadena de suministro al obtener dependencias de software de código abierto de terceros no confiables. Agradecemos a nuestros desarrolladores y colaboradores. Muestre su agradecimiento dándonos un si le gusta nuestro trabajo.
Agradecemos las contribuciones del código con los brazos abiertos. Ver Directrices de MD. Encontrado un error? Abra un problema. Consulte nuestras pautas Security.MD para informar un problema de seguridad.
Packj actualmente puede examinar los paquetes de NPM, PYPI y Rubygems para atributos "riesgosos". Estamos agregando soporte para el óxido.
Packj utiliza análisis de código estático, rastreo dinámico y análisis de metadatos para una auditoría integral. El análisis estático por sí solo no es suficiente para marcar el malware sofisticado que puede esconderse mejor utilizando la ofuscación del código. El análisis dinámico se realiza instalando el paquete bajo strace y monitoreando su comportamiento de tiempo de ejecución. Lea más en Audit ReadMe.
Este es un comportamiento malicioso muy común. Packj detecta la ofuscación del código, así como el desove de los comandos de shell (llamada del sistema ejecutivo). Por ejemplo, Packj puede marcar el uso de la API getattr() y eval() al indicar "generación de código de tiempo de ejecución"; Un desarrollador puede ir y echar un aspecto más profundo entonces. Ver Main.py para más detalles.