
静的および動的分析ツール。オープンソースパッケージの悪意のある、脆弱性のある、リスクのある属性を監査し、サプライチェーン攻撃を防ぐためにサンドボックス化されたインストールを備えています。
Packj(パッケージと発音)は、ソフトウェアサプライチェーン攻撃を軽減するためのツールです。NPM、RubyGems、PyPIなどの人気のあるオープンソースパッケージレジストリから、悪意のあるもの、脆弱なもの、放棄されたもの、タイポスクワッティング、その他の「リスクのある」パッケージを検出できます。簡単にカスタマイズしてノイズを最小限に抑えることができます。Packjは博士研究プロジェクトとして始まり、現在はさまざまな政府助成金のもとで開発されています。
注記 セルフホスト型のPackjウェブサーバーと複数の統合機能が今月中にリリース予定です 👊 このリポジトリをウォッチして最新情報を入手してください。

複数のデプロイモデルをサポートしています:
Packjを使用してプルリクエスト内の依存関係を監査します。```yaml
GitHub [marketplace](https://github.com/marketplace/actions/packj-security-audit) で見る。例: [PR run](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 は以下のツールを提供します:
* [監査](#auditing-a-package) - パッケージの「リスクのある」属性を精査します。
* [サンドボックス](#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** を使用します(つまり、**VM/コンテナは不要** です)。
サンドボックス化の仕組みと使用方法の詳細は [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 は博士課程の研究プロジェクトとして始まりました。さまざまな政府助成金に支えられています。
<details>
<summary><h4>詳細を表示</h4></summary>
Packj は学術研究プロジェクトとして始まりました。具体的には、Packj が使用する静的コード解析技術は、ジョージア工科大学の私たちの研究 [グループ](http://cyfi.ece.gatech.edu) による最先端のサイバーセキュリティ研究 [MalOSS](https://github.com/osssanitizer/maloss) プロジェクトに基づいています。
<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) からの generous な助成金によって支えられています。
</details>
# なぜ Packj なのか
**要約** 現在の最先端の脆弱性スキャナーは、サードパーティのオープンソースコードが **良性** であると仮定しています。したがって、そのようなツールはすべて、良性コードの偶発的なプログラミングバグ(別名 Log4J などの CVE)からの脅威のみに対処します。それらは、依存関係の混乱、タイポスクワッティング、プロテストウェア(サボタージュ)、アカウント乗っ取り、ソーシャルエンジニアリングなど、新しいサプライチェーンの脆弱性を利用して悪意のあるコードを拡散する悪意のある攻撃者による、SolarWinds に似た現代のソフトウェアサプライチェーン攻撃からは保護しません。最近(2022年12月)の例として、依存関係の混乱の脆弱性(CVE は割り当てられていません)を利用して侵害された PyTorch パッケージがあります。
Packj は CVE の監査だけでなく、深い静的+動的コード解析とメタデータチェックを実行し、シェルの起動、SSH キーの使用、GitHub コードとパッケージ化コードの不一致(来歴)、2FA の欠如など、あらゆる「リスクのある」動作や属性を検出します。このような安全でない属性は CVE として認定されないため、既存のツールはどれもフラグを立てることができません。Packj は、ソフトウェアサプライチェーンにおける悪意のある、タイポスクワッティング、放棄された、脆弱な、その他の安全でない依存関係(弱いリンク)をフラグできます。
<details>
<summary><h4>詳細を表示</h4></summary>
現在のソフトウェアサプライチェーンの脅威モデルは、サードパーティのオープンソースコードが **良性** であると **仮定** しており、そのためセキュリティの脆弱性は偶発的なプログラミングバグ(別名 CVE)についてのみ追跡されます。そのため、既存のすべてのオープンソース脆弱性スキャナーは、**公開されている CVE のみを報告** し、良性コードの偶発的なバグからの脅威に対処します。
偶発的なプログラミングバグの典型的な例は、ユーザー入力に対する境界チェックの欠落であり、これによりコードがバッファオーバーフロー攻撃に対して脆弱になります。実際の一般的な例としては Log4J や HeartBleed があります。攻撃者は CVE をトリガーするためのエクスプロイトを開発する必要があります(HeartBleed の場合は細工された TCP/IP パケット、バッファオーバーフローを引き起こす数値的に高い入力など)。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 に似た現代のソフトウェアサプライチェーン攻撃を **検出できない** のです。これらのツールは単にオープンソースの依存関係のソースコードをスキャンし、使用されているすべての依存関係のリストをコンパイルし、各 <依存関係-NAME, 依存関係-VERSION> をデータベース(例:NVD)で検索して、影響を受けるパッケージバージョンを報告します(例:Log4J の脆弱なバージョン、HeartBleed の影響を受ける LibSSL バージョン)。
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) ファイルを追加し、不要な属性をコメントアウトしてアラート疲れを軽減してください。
# 発見されたマルウェア #
このツールを使用して、PyPI で 40 以上、Rubygems で 20 以上の悪意のあるパッケージを発見しました。その多くは削除されています。以下の例を参照してください:
<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) を、ソースリポジトリの欠如と、パッケージインストール時(setup.py)の機密性の高い API(ネットワーク、コード生成)の使用により、疑わしいとしてフラグを立てました。私たちはさらに詳しく調査することにし、パッケージが悪意のあるものであることを発見しました。詳細な分析は [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)
- PyConUS'22 [トーク](https://www.youtube.com/watch?v=Rcuqn56uCDk) および [スライド](https://speakerdeck.com/ashishbijlani/pyconus22-slides)。
- BlackHAT Asia'22 Arsenal [プレゼンテーション](https://www.blackhat.com/asia-22/arsenal/schedule/#mitigating-open-source-software-supply-chain-attacks-26241)
- PackagingCon'21 [トーク](https://www.youtube.com/watch?v=PHfN-NrUCoo) および [スライド](https://speakerdeck.com/ashishbijlani/mitigating-open-source-software-supply-chain-attacks)
- BlackHat USA'22 Arsenal トーク [Detecting typo-squatting, backdoored, abandoned, and other "risky" open-source packages using 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 トーク [Scoring dependencies to detect "weak links" in your open-source software supply chain](https://osseu2022.sched.com/overview/type/SupplyChainSecurityCon) - [YouTube](https://www.youtube.com/watch?v=a7BfDGeW_jY) のプレゼンテーションビデオ
- NullCon'22 でのプレゼンテーション [Unearthing Malicious And Other “Risky” Open-Source Packages Using Packj](https://archive.nullcon.net/website/goa-2022/speakers/unearthing-malicious-and-other-risky-open-source-packages-using-packj.php) の [ビデオ](https://www.youtube.com/watch?v=PgvlSjl-mrY) と [スライド](https://drive.google.com/file/d/1qLXIXzsIhRlS0mo8nwWI9KmD12CImZY9/view?usp=sharing)
# 機能ロードマップ #
* Rust アナライザーを追加。Rust は作業中 [ETA: 2024年2月]。
* いくつかの(TODO)「リスクのある」コードおよびメタデータ属性を検出する機能を追加 [ETA: 2024年2月]。
* セルフホスト型 Packj ウェブサーバーといくつかの有用な統合(例:Gitlab ランナー) [ETA: 2024年4月]。
このリポジトリを :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は `getattr()` および `eval()` APIの使用をフラグ付けできます。これらは「実行時コード生成」を示すため;開発者はさらに詳しく調査することができます。詳細は [main.py](https://github.com/ossillate-inc/packj/blob/main/packj/audit/main.py#L512) を参照してください。
</details>