
Инструмент статического и динамического анализа, который проверяет пакеты с открытым исходным кодом на наличие вредоносных, уязвимых и рискованных атрибутов, с изолированной установкой для предотвращения атак на цепочку поставок.
Packj (произносится как «пакедж») — это инструмент, помогающий смягчать атаки на цепочки поставок программного обеспечения. Он может обнаруживать вредоносные, уязвимые, заброшенные, с тайпо-сквоттингом и другие «опасные» пакеты из популярных реестров пакетов с открытым исходным кодом, таких как NPM, RubyGems и PyPI. Его можно легко настроить для уменьшения шума. Packj начинался как исследовательский проект в рамках докторской диссертации и в настоящее время разрабатывается при поддержке различных государственных грантов.
Примечание Самостоятельно размещаемый веб-сервер Packj и несколько интеграций появятся позднее в этом месяце 👊 Следите за этим репозиторием, чтобы быть в курсе.

Мы поддерживаем несколько моделей развертывания:
Используйте Packj для аудита зависимостей в pull request'ах.```yaml
Посмотреть на GitHub [marketplace](https://github.com/marketplace/actions/packj-security-audit). Пример [запуска PR](https://github.com/ossillate-inc/packj-github-action-demo/pull/3#issuecomment-1274797138).
### 2. Docker-образ (рекомендуется)
Самый быстрый способ попробовать/протестировать Packj — использовать Docker. Podman также поддерживается для контейнеризированных (изолированных) запусков.```
docker run -v /tmp:/tmp/packj -it ossillate/packj:latest --help
Клонируйте этот репозиторий,``` git clone https://github.com/ossillate-inc/packj.git && cd packj
Установите зависимости```
bundle install && pip3 install -r requirements.txt
Начните с справки:``` python3 main.py --help
# Поддерживаемые экосистемы #
Packj может проверять опубликованные пакеты из реестров пакетов NPM, PyPI, Rust, PHP и Rubygems. Поддержка Rust и PHP находится в разработке. Мы активно добавляем поддержку реестров.
Также поддерживается проверка локальных (неопубликованных) пакетов NPM и PyPI.
| Реестр | Экосистема | Поддерживается |
| ---------- | ---------- | ---------------- |
| NPM | JavaScript | :white_check_mark: |
| PyPI | Python | :white_check_mark: |
| Cargo | Rust | :white_check_mark: |
| Rubygems | Ruby | :white_check_mark: |
| Packagist | PHP | :white_check_mark: |
| Docker | Docker | :x: |
| Nuget | .NET | :white_check_mark: |
| Maven | Java | :white_check_mark: |
| Cocoapods | Swift | :x: |
# Функциональность #
Packj предлагает следующие инструменты:
* [Audit](#auditing-a-package) – для проверки пакета на «рискованные» атрибуты.
* [Sandbox](#sandboxed-package-installation) – для безопасной установки пакета.
## Аудит пакета ##
Packj проверяет пакеты открытого исходного кода на «рискованные» атрибуты, которые делают их уязвимыми для атак на цепочку поставок. Например, пакеты с истекшими доменами электронной почты (отсутствие 2FA), большим временным разрывом между релизами, чувствительными API или разрешениями доступа и т.д. помечаются как рискованные.
Поддерживается аудит:
- нескольких пакетов: `python3 main.py audit -p pypi:requests rubygems:overcommit`
- файлов зависимостей: `python3 main.py audit -f npm:package.json pypi:requirements.txt`
По умолчанию `audit` выполняет только статический анализ кода для обнаружения рискованного кода. Вы можете передать флаг `-t` или `--trace`, чтобы также выполнить динамический анализ кода, который установит все запрошенные пакеты под strace и отследит их поведение во время установки. Пример вывода приведён ниже.
<details>
<summary><h4>Показать пример запуска/вывода</h4></summary>
$ 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",
]
}
</details>
> ВНИМАНИЕ: поскольку пакеты могут выполнять вредоносный код во время установки, рекомендуется использовать `-t` или `--trace` ТОЛЬКО при запуске внутри контейнера Docker или виртуальной машины.
Аудит также можно выполнять в контейнерах Docker/Podman. Подробнее о рискованных атрибутах и использовании см. в [Audit README](https://github.com/ossillate-inc/packj/blob/main/packj/audit/README.md).
## Установка пакетов в песочнице ##
Packj предлагает легковесную изоляцию для `безопасной установки` пакета. В частности, он предотвращает кражу конфиденциальных данных, доступ к чувствительным файлам (например, ключам SSH) и сохранение вредоносного ПО вредоносными пакетами.
Он изолирует скрипты установки, включая любую нативную компиляцию. Используется **strace** (т.е. **НЕ** требуется ВМ/контейнер).
Подробнее о механизме изоляции и использовании см. в [Sandbox README](https://github.com/ossillate-inc/packj/blob/main/packj/sandbox/README.md).
<details>
<summary><h4>Показать пример запуска/вывода</h4></summary>
$ 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:
</details>
# Наша история
**Кратко:** Packj начинался как исследовательский проект PhD. Он поддерживается различными государственными грантами.
<details>
<summary><h4>Показать развёрнутый ответ</h4></summary>
Packj начинался как академический исследовательский проект. В частности, методы статического анализа кода, используемые Packj, основаны на передовых исследованиях в области кибербезопасности: проект [MalOSS](https://github.com/osssanitizer/maloss) нашей исследовательской [группы](http://cyfi.ece.gatech.edu) в Технологическом институте Джорджии.
<a href="https://arxiv.org/pdf/2002.01139v1.pdf" target="_blank">
<img src="https://assets.kitploit.com/production/public/readmes/5562/c4061028051de04a9aebaf4188c08fdd1bcdb47efa8a818e959d3b3fc7bc5dc7.png" width="300" alt="academic paper">
</a>
Packj поддерживается щедрыми грантами от [NSF](https://www.sbir.gov/node/2083473), [GRA](https://gra.org/company/227/OSSPolice.html) и [ALInnovate](https://innovatealabama.org).
</details>
# Почему Packj
**Кратко:** Современные сканеры уязвимостей предполагают, что сторонний код с открытым исходным кодом является БЕЗОПАСНЫМ. Следовательно, все такие инструменты рассматривают ТОЛЬКО угрозы от случайных ошибок программирования в безопасном коде (известных как CVE, например Log4J). Они НЕ защищают от современных атак на цепочку поставок программного обеспечения типа SolarWinds, исходящих от намеренно плохого (т.е. вредоносного) кода, который распространяется злоумышленниками с использованием новых уязвимостей в канале поставок, включая путаницу зависимостей, тайпсквоттинг, протестное ПО (саботаж), захват учётных записей и социальную инженерию. Недавний пример (декабрь 2022 г.) — пакет PyTorch, скомпрометированный с помощью уязвимости путаницы зависимостей (CVE не присвоено).
Packj не только проверяет на CVE, но и выполняет глубокий статический+динамический анализ кода, а также проверку метаданных для выявления любого «рискованного» поведения и атрибутов, таких как запуск оболочки, использование ключей SSH, несоответствие кода GitHub и упакованного кода (происхождение), отсутствие 2FA и многие другие. Такие небезопасные атрибуты не являются CVE, поэтому ни один из существующих инструментов не может их обнаружить. Packj может выявлять вредоносные, тайпсквоттинговые, заброшенные, уязвимые и другие небезопасные зависимости (слабые звенья) в вашей цепочке поставок ПО.
<details>
<summary><h4>Показать развёрнутый ответ</h4></summary>
Текущая модель угроз цепочки поставок ПО **предполагает**, что сторонний код с открытым исходным кодом является безопасным, и поэтому уязвимости отслеживаются только для случайных ошибок программирования (известных как CVE). Таким образом, все существующие сканеры уязвимостей с открытым исходным кодом **ТОЛЬКО** сообщают об общеизвестных CVE и рассматривают угрозы от случайных ошибок в безопасном коде.
Типичный пример случайной ошибки программирования — отсутствие проверки границ ввода, что делает код уязвимым для атак переполнения буфера. Известные реальные примеры включают Log4J и HeartBleed. Злоумышленникам необходимо разработать эксплойт для использования CVE (например, специально сформированный TCP/IP-пакет в случае HeartBleed или численно большой ввод для вызова переполнения буфера). CVE можно исправить с помощью патча или обновления до новой версии библиотеки (например, новая версия Log4J исправляет CVE).
Ландшафт угроз современной цепочки поставок ПО **изменился** после атаки SolarWinds. Злоумышленники нашли новые уязвимости, но на этот раз в канале поставок, а не в коде. Эти новые уязвимости, такие как путаница зависимостей, тайпсквоттинг, протестное ПО (саботаж), захват учётных записей и социальная инженерия, используются для распространения вредоносного ПО. Сообщается о тысячах скомпрометированных пакетов NPM/PyPI/Ruby.
В отличие от CVE, вредоносное ПО — это намеренно плохой (то есть вредоносный) код. Более того, сам вредоносный код является эксплойтом и не может быть исправлен или устранён обновлением до новой версии. Например, [атака путаницы зависимостей](https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610) была намеренно вредоносной; она не эксплуатировала никакой случайной ошибки программирования в коде. Аналогично, автор популярного пакета, саботирующий свой собственный код в знак [протеста](https://en.wikipedia.org/wiki/Peacenotwar) против войны, действует намеренно и не использует никакие CVE. Тайпсквоттинг — ещё один вектор атаки, который злоумышленники используют для распространения вредоносного ПО в популярных реестрах пакетов с открытым исходным кодом: он использует [опечатки и неопытность разработчиков](https://discuss.python.org/t/improving-risks-and-consequences-against-typosquatting-on-pypi/5090), а не случайные ошибки программирования или CVE в коде.
Существующие сканеры **НЕ СПОСОБНЫ** обнаружить эти современные атаки на цепочку поставок ПО, подобные SolarWinds, от намеренно уязвимого (вредоносного) кода. Эти инструменты просто сканируют исходный код на наличие зависимостей с открытым исходным кодом, составляют список всех используемых зависимостей и проверяют каждое <имя-зависимости, версия-зависимости> в базе данных (например, NVD), чтобы сообщить о затронутых версиях пакетов (например, уязвимая версия Log4J, версия LibSSL, затронутая HeartBleed).
Packj не только проверяет на CVE, но и выполняет глубокий статический+динамический анализ кода, а также проверку метаданных для выявления любого «рискованного» поведения и атрибутов, таких как запуск оболочки, использование ключей SSH, несоответствие кода GitHub и упакованного кода (происхождение), отсутствие 2FA и многие другие. Такие небезопасные атрибуты не являются CVE, поэтому ни один из существующих инструментов не может их обнаружить. Packj может выявлять вредоносные, тайпсквоттинговые, заброшенные, уязвимые и другие небезопасные зависимости (слабые звенья) в вашей цепочке поставок ПО. Подробнее см. в [Audit README](https://github.com/ossillate-inc/packj/blob/main/packj/audit/README.md#faq).
</details>
# Настройка #
Packj легко настраивается (без лишнего шума) под вашу модель угроз. Просто добавьте файл [.packj.yaml](https://github.com/ossillate-inc/packj/blob/main/.packj.yaml) в корневую директорию вашего репозитория/проекта и уменьшите усталость от предупреждений, закомментировав ненужные атрибуты.
# Обнаруженные вредоносные программы #
С помощью этого инструмента мы обнаружили более 40 вредоносных пакетов на PyPI и 20 на Rubygems. Многие из них были удалены. Пример ниже:
<details>
<summary><h4>Показать пример вредоносного ПО</h4></summary>
$ 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
</details>
Packj пометил KrisQian (v0.0.7) как подозрительный из-за отсутствия исходного репозитория и использования чувствительных API (сеть, генерация кода) во время установки пакета (в setup.py). Мы решили провести более глубокий анализ и обнаружили, что пакет является вредоносным. Подробный анализ доступен по адресу [https://packj.dev/malware/krisqian](https://packj.dev/malware/krisqian).
Больше примеров вредоносного ПО, обнаруженного нами, перечислены на [https://packj.dev/malware](https://packj.dev/malware). Свяжитесь с нами по адресу [[email protected]](mailto:[email protected]) для получения полного списка.
# Ресурсы #
Чтобы узнать больше об инструменте Packj или атаках на цепочку поставок открытого ПО, обратитесь к нашим
[](https://www.youtube.com/watch?v=Rcuqn56uCDk)
[](https://www.youtube.com/watch?v=a7BfDGeW_jY)
- [Доклад](https://www.youtube.com/watch?v=Rcuqn56uCDk) и [слайды](https://speakerdeck.com/ashishbijlani/pyconus22-slides) PyConUS'22.
- [Презентация](https://www.blackhat.com/asia-22/arsenal/schedule/#mitigating-open-source-software-supply-chain-attacks-26241) на BlackHAT Asia'22 Arsenal.
- [Доклад](https://www.youtube.com/watch?v=PHfN-NrUCoo) и [слайды](https://speakerdeck.com/ashishbijlani/mitigating-open-source-software-supply-chain-attacks) на PackagingCon'21.
- Доклад на BlackHat USA'22 Arsenal: [Обнаружение тайпсквоттинга, бэкдоров, заброшенных и других «рискованных» пакетов с открытым исходным кодом с помощью Packj](https://www.blackhat.com/us-22/arsenal/schedule/#detecting-typo-squatting-backdoored-abandoned-and-other-risky-open-source-packages-using-packj-28075).
- Академическая [диссертация](https://cyfi.ece.gatech.edu/publications/DUAN-DISSERTATION-2019.pdf) по безопасности открытого исходного кода и [статья](https://www.ndss-symposium.org/wp-content/uploads/ndss2021_1B-1_23055_paper.pdf) нашей группы в Технологическом институте Джорджии, положившая начало этому исследованию.
- Доклад на Open Source Summit Europe'22: [Оценка зависимостей для выявления «слабых звеньев» в цепочке поставок открытого ПО](https://osseu2022.sched.com/overview/type/SupplyChainSecurityCon) — видео презентации на [YouTube](https://www.youtube.com/watch?v=a7BfDGeW_jY).
- [Видео](https://www.youtube.com/watch?v=PgvlSjl-mrY) и [слайды](https://drive.google.com/file/d/1qLXIXzsIhRlS0mo8nwWI9KmD12CImZY9/view?usp=sharing) презентации на NullCon'22: [Обнаружение вредоносных и других «рискованных» пакетов с открытым исходным кодом с помощью Packj](https://archive.nullcon.net/website/goa-2022/speakers/unearthing-malicious-and-other-risky-open-source-packages-using-packj.php).
# План развития функций #
* Добавить анализатор Rust. Rust в разработке [Ожидаемая дата: февраль 2024 г.].
* Добавить функциональность для обнаружения нескольких (TODO) «рискованных» участков кода и атрибутов метаданных [Ожидаемая дата: февраль 2024 г.].
* Собственный веб-сервер Packj и несколько полезных интеграций (например, GitLab runner) [Ожидаемая дата: апрель 2024 г.].
Следите :eyes: за этим репозиторием, чтобы быть в курсе.
Есть запрос функции или поддержки? Пожалуйста, посетите нашу [страницу обсуждений на GitHub](https://github.com/ossillate-inc/packj/discussions/) или присоединяйтесь к нашему [сообществу в Discord](https://discord.gg/qFcqaV2wYa) для обсуждения и запросов.
# Команда и участники #
Packj был разработан исследователями в области кибербезопасности из [Ossillate Inc.](https://packj.dev/team) и внешними соавторами, чтобы помочь разработчикам снизить риски атак на цепочку поставок при использовании ненадёжных сторонних зависимостей с открытым исходным кодом. Мы благодарим наших разработчиков и соавторов. Выразите свою признательность, поставив нам :star:, если вам нравится наша работа.
Основатели:
* Ashish Bijlani
* Devdutt Patnaik
* Ajinkya Rajput
Мы с радостью принимаем вклад в код. Ознакомьтесь с руководством [CONTRIBUTING.md](https://github.com/ossillate-inc/packj/blob/HEAD/CONTRIBUTING.md). Нашли ошибку? Пожалуйста, откройте issue. Обратитесь к нашему руководству [SECURITY.md](https://github.com/ossillate-inc/packj/blob/HEAD/SECURITY.md), чтобы сообщить о проблеме безопасности.
# FAQ #
<details>
<summary><b>Какие менеджеры пакетов (реестры) поддерживаются?</b></summary>
Packj в настоящее время может проверять пакеты NPM, PyPI и RubyGems на «рискованные» атрибуты. Мы добавляем поддержку Rust.
</details>
<details>
<summary><b>Какие методы использует Packj для обнаружения рискованных/вредоносных пакетов?</b></summary>
Packj использует статический анализ кода, динамическое трассирование и анализ метаданных для всестороннего аудита. Одного статического анализа недостаточно для выявления сложного вредоносного ПО, которое может лучше маскироваться с помощью обфускации кода. Динамический анализ выполняется путём установки пакета под `strace` и отслеживания его поведения во время выполнения. Подробнее см. в [Audit README](https://github.com/ossillate-inc/packj/blob/main/packj/audit/README.md).
</details>
<details>
<summary><b>Работает ли это с обфусцированными вызовами? Например, строка, зашифрованная в base64, которая расшифровывается и затем передаётся в оболочку?</b></summary>Это очень распространённое вредоносное поведение. Packj обнаруживает обфускацию кода, а также запуск команд оболочки (системный вызов exec). Например, Packj может пометить использование API `getattr()` и `eval()`, так как они указывают на «генерацию кода во время выполнения»; разработчик может затем более подробно изучить это. Подробнее см. в [main.py](https://github.com/ossillate-inc/packj/blob/main/packj/audit/main.py#L512).
</details>