目に見えないnpmマルウェア:特定のバ,ジョン表現でセキュリティチェックを回避

npm CLIには,非常に便利でよく知られたセキュリティ機能があります。npmパッケージをインストールする際、CLI はパッケージとその依存関係をすべてチェックして、既知の脆弱性がないか調べます。

このチェックはパッケ、ジの、ンスト、ル時(npm安装実行時)に自動で行われますが,npm审计を実行することで手動で行うことも可能です。
これは,既知の脆弱性を持つパッケージを使用しないよう,開発者に警告を発する重要なセキュリティ対策につながります。
最近,セキュリティに影響を与える可能性のあるnpmルによる予期せぬ動作を検知しました。それは,npm安装とnpm审计の両方において,特定のバージョン形式になっている場合,パッケージに対する脆弱性に関する警告が表示されないというもので,これらのパッケージを使用している開発者は重大な脆弱性やマルウェアを自分のシステムやnpmパッケージの間接的な依存関係として持ち込んでしまう可能性があります。
このブログでは,この問題の詳細,そして攻撃者が公開した悪意のあるパッケージのセキュリティチェックを回避するためにこの問題をどのように利用するのか,また開発者がこの問題に混乱させられないようにするにはどうすればよいのかについて詳しく説明します。
思いがけない結果
いくつかのnpmパッケージで作業している際,npm CLIとJFrog x光で報告された脆弱性の間に興味深い不一致があることに気が付きました。
特定のパッケジ”cruddl 2.0.0-update.2“をaapl . aapl .ンスト.ルすると,npmとx射线から異なる脆弱性の報告を受け取りました。”


同じパッケージに対して,npmの発見した脆弱性は0件でしたが,x光は脆弱性を1件(cve - 2022 - 36084)発見しました。これがバグの可能性があるものなのか,それとも別のものなのか,調べてみることにしました。
課題に関する詳細調査
いくつかの試行錯誤とパッケージのインストールを行ったところ,この不一致はインストールしたパッケージのバージョンにダッシュ/ハ瑙フン文字(例:1.2.3-a)が含まれている場合のみ発生することに気づきました。ではなぜこのようなことが起こるのでしょうか?
パッケ,ジをアップロ,ドするとき,npmはセマンティックバ,ジョニング(语义版本控制)に準拠した厳密なバ,ジョン形式を推奨しており,node-semverで解析可能でなければなりません。例えば,これら2:5.6.7,5.6.7-a。
npm-install /审计ツールは,依存するすべてのパッケージとそのバージョンをjson(辞書形式)に収集し,批量咨询端点という名前のnpm APIエンドポントに送ります。このエンドポイントは各パッケージとバージョンを調べ,バージョンをアドバイザリの影響範囲と一致させることで関連するアドバイザリを見つけようとします。そして,apiエンドポaaplントから返されるリストに,これらすべての関連するアドバaaplザリを追加します。
今回確認したのは,大部分顾问端点はバージョンにハイフン(-)の後に追加文字を含むパッケージのセキュリティアドバイザリの取得に失敗するということです。
“ハ▪フン付きバ▪ジョン”って何のこと??
セマンティックバ,ジョニング(语义版本控制)の仕様によると,バ,ジョンの形式はmajor.minor.patchです(例:5.6.7)。ただし,第9項にあるように,プレリリ,スバ,ジョンは”パッチバージョンの直後にハイフンとドット区切りの一連の識別子を付加する”ことで指定することができます(例:5.6.7-a)。
動作の原因を推測
npmエンドポイントのコードはクローズドソースであるため,問題がどこに起因しているかは推測するしかありません。
各アドバ▪▪ザリには(サンプルはこらから)、影響を受けるバ、ジョンの範囲を表す論理式(例:> 6.6.0)を格納する"影響を受けるバ,ジョン"フィ,ルドがあります。あるバ,ジョンが論理式のいずれかを満たした場合,そのバ,ジョンは脆弱であるとみなされます。
node-semverの記録によると(そしておそらく他のプログラミング言語でのsemver(npmjpのドキュメントの“预发布标签”セクションを参照)。
例えば,デフォルトでは,
semver. satisfy ("1.2.3-a", "> 0")
假と戻ってきます。アドバイザリの作成者の意図としては全てのバージョンのパッケージをカバーすることだったので,これは非常に予想外なことかもしれません(例えば悪意のあるパッケージに対するアドバイザリを作成する場合など)。
また,npmjp上のドキュメントには,“选项对象”にincludePrereleaseのフラグを設定することで,この動作を抑制できることも記載されています(レンジマッチングの目的,ですべてのプレリリースバージョンを通常版と同じように扱う)。
そこで,フラグを設定した状態で同じチェックを実行すると,
semver.satisfies(“1.2.3-a”、“> 0 ",{“includePrerelease”:1})
真正的と戻ってきます。
大部分咨询端点でこのフラグを有効にすると,通常のnpmパッケージのバージョンとプレリリースバージョンの間の不整合が解消されるはずです。
JFrogの公開した情報を受けて,この機能が期待される動作であることをnpmのメンテナー(管理者)から学んだので,この動作が変更されることはないと考えています。
実証実験(概念验证)
実際に致命的な脆弱性を持っていたパッケ,ジであるcruddlを例にとってみましょう(cve - 2022 - 36084)。
cruddlのバジョン2.0.0をンストルすると,想定通り重大な脆弱性が発見されたことがわかります。

上記の代わりに,同じパッケ,ジのプレリリ,スを,ンスト,ルすることを選択した場合,

バ,ジョン2.0.0-update.2はcve - 2022 - 36084の影響を受けているにもかかわらず,誤って”脆弱性が見つからなかった”と表示されます(修正版は2.7.0)。
攻撃者はどのようにこの動作を悪用するのか
攻撃者は,無害に見えるパッケージに脆弱性や悪意のあるコードを意図的に仕込み,他の開発者が価値のある機能,あるいは受害や依存関係の混乱などの感染技術によるミスとして取り込まれるなどの方法でこの動作を悪用することができます(例は,過去のブログ記事をご覧ください)。
上記のように,攻撃者がプレリリ,スバ,ジョン形式のパッケ,ジを使用している場合,そのコ、ドが悪意のあるコ、ド·脆弱性として報告され、アドバ、ザリが作成されていたとしても, npm CLIはそのような勧告の存在については報告しないため,悪意のあるコード・脆弱性の含まれたパッケージに依存している開発者は何も知らされないままになります。
問題を回避するために開発者ができることは?
開発者やDevOpsエンジニアに推奨するのは,そのパッケージが極めて信頼できるソースから提供されていると100%確信している場合を除き,プレリリスバジョンのnpmパッケジをンストルしないことです。その場合でも,できるだけ早くプレリリ,スバ,ジョンでないパッケ,ジに戻すことをお勧めします。
次のコマンドラインを使用して,現在プレリリースバージョンのnpmパッケージがインストールされているかどうかを以下の方法で確認することができます。
Linux用:
npm list -a | grep - e @[0-9]+\.[0-9]+\.[0-9]+-
Windows用:
NPM list -a | findstr -r @[0-9]*\.[0-9]*\.[0-9]*-
JFrogセキュリティ·リサ,チの最新情報
JFrogセキュリティ·リサ,チチ,ムからの最新の情報は,セキュリティ·リサ,チのブログ記事や推特@JFrogSecurityからご覧ください。