Skip to main content

セキュリティパッチで脆弱性に先手を打つ

著者

2019年7月31日

0 分で読めます

従来、ソフトウェア開発のワークフローでは、セキュリティ問題が発生すると、チームは通常、パッケージやアプリの新しいバージョンをリリースして修正していました。

一方、オープンソースプロジェクトでは、メンテナーは通常ボランティアであり、日常の仕事などに時間を取られることもあるため、パッケージの修正版が公開されるまで時間がかかる場合があります。その結果、脆弱性の発見から修正の適用と公表までに大きな隔たりが生じることがあります。また、そのソフトウェアコンポーネントの修正版が正式に公開されていないと、悪用されるリスクが高まります。

こうした状況に対処するため、SnykはnpmエコシステムのオープンソースJavaScriptプロジェクト向けにセキュリティパッチを提供しています。これにより、メンテナーがすぐに自力でセキュリティ問題を修正できない場合でも、パッケージの安全性を保ち、セキュリティリスクに先手を打てるよう支援します。Snykはメンテナーと連携し、影響を受けるnpmパッケージにセキュリティ修正を直接適用します。そのため、問題に対処する正式リリースがない場合(また、そのリリースによってビルドが壊れる可能性がある場合)でも、安心してご利用いただけます。

セキュリティパッチが重要な理由

オープンソースのメンテナーがセキュリティ修正をリリースするまでの時間差は、深刻な影響を及ぼす可能性があります。そのため、セキュリティパッチは不可欠です。その重要性を示す例として、人気のJavaScriptライブラリlodashで最近発見されたプロトタイプ汚染の脆弱性が挙げられます。

Snykのセキュリティリサーチチームは、lodashのプロトタイプ汚染の脆弱性(CVE-2019-10744)を発見しました。この脆弱性はすべてのバージョンに影響します。発見後、責任ある情報開示のプロセスを通じてlodashのメンテナーであるJohn Daltonと連携し、調査結果を伝えるとともに、脆弱性に対処するセキュリティ修正を提供しました。

lodashリポジトリで問題を修正するPull Requestが公開されると、修正を含むlodashの正式リリースまでのカウントダウンが始まりました。

脆弱性情報は2019年7月2日に公開されましたが、正式リリースは1週間遅れ、2019年7月9日にようやく公開されました。

Snykの仕組みで提供するセキュリティパッチは、すべてのユーザーが無料で利用できます。パッチを適用して脆弱性を修正し、プロジェクトを保護するため、Snykが事前にPull Requestを作成します。

Snykはどのようにセキュリティパッチを適用するのか

Snykのモジュールパッチ適用の仕組みは、npmのpackage.jsonスクリプトによるライフサイクルイベントのサポートと連携して動作します。npmのプロセスでは、ビルドのさまざまな段階(npmのインストール時やレジストリへの公開時など)で、修正プログラムをnpmのライフサイクル管理にシームレスに組み込めます。

npmのドキュメントページでは、利用可能なすべてのnpmライフサイクルイベントと、その動作や実行タイミングについて詳しく説明しています。

Snykはprepublishのpackage.jsonライフサイクルイベントを使用して、パッケージのパックと公開の前にパッチを適用します。また、追加の引数を指定せずにnpm installをローカルで実行する場合にも適用します。_._仕組みをさらに確認するため、ローカルでいくつかのパッケージを作成し、ローカルnpmレジストリとしてverdaccioを使って、モジュールの公開とインストールを試してみましょう。

npm init -yを実行し、実験用モジュールaaaにprepublishスクリプトを追加すると、コードは次のようになります。


{
  "name": "aaa",
  "version": "1.1.0",
  "description": "",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "prepublish": "echo hello little green world"
  },
  "main": "index.js",
  "keywords": [],
  "author": "",
  "license": "ISC"
}

コマンドプロンプトでnpm installを実行すると、次のように表示されます。

非推奨の警告やパッケージの出力、「up to date」のステータスが表示された、npm installコマンド実行中のターミナル。

npmのライフサイクルイベントが実行され、短いテキストがコンソールに表示されます。同時に、Snykが必要なパッチも適用します。

Snykによって、pre-publishイベントの設定は次のように更新されます。


"scripts": {
  "snyk-protect": "snyk protect",
  "prepublish": "npm run snyk-protect"
}

npm installを実行すると、Snykはコードに存在する脆弱性を特定し、データベースから修正用のパッチをダウンロードして、node_modulesフォルダー内の脆弱なモジュールに適用します。

つまり、プロジェクトをクローンしてすべての依存関係をインストールし、実行すると、モジュールのインストール中にSnykが呼び出され、セキュリティ脆弱性にパッチが適用されます。

Node.jsプロジェクトでは、アプリケーションを実行する時点ですでに保護されています。webpack、babel、typescriptなどのモジュールバンドラーを使ってコードをトランスパイルする一般的なJavaScriptライブラリでは、dist/に生成されるバンドルにも、脆弱性へのパッチが含まれます。

npm prepublishの仕組み

単純にプロジェクトでnpm installを実行するのではなく、異なるワークフローを採用していて、prepublishイベントをスキップしている場合もあるでしょう。そのような場合、Snykのパッチは適用されません。

npmのprepublishスクリプトイベントがどのように呼び出されるか、詳しく見ていきましょう。

  • npm install

  • npm install --dev

  • npm ci

  • yarn

  • yarn install

  • yarn install --frozen-lockfile

npmのprepublishイベントが呼び出されない場合

  • npm install --prod

  • yarn install --prod

前述のとおり、追加の引数を指定してnpm installを実行すると、prepublishは含まれません。そのため、npmモジュールの依存関係をインストールするワークフローでnpm install --prodを実行する場合は、代わりにSnykのsnyk protectを直接呼び出すことができます。

たとえば、次のTravis CI設定を見てみましょう。


install:
  - npm install --prod
  - snyk protect

ライブラリ向けのSnykセキュリティパッチ

npmパッケージの実験では、次の2つのライブラリを使用しました。

  • aaa - 依存関係にセキュリティ脆弱性があり、メンテナーが公式修正を含む新しいバージョンをリリースしていません。Snykのパッチは、これらの脆弱性を修正します。

  • bbb - aaaを依存関係として使用します

この例では、aaaプロジェクトがbbbを使用しています。bbbがnpm installを実行するなどして依存関係をインストールしても、prepublishのaaaライフサイクルイベントは実行されません。

つまり、aaaがすべての依存関係を含むトランスパイル済みバンドルとしてレジストリに公開されていない限り(これはフロントエンドライブラリでのみ一般的です)、aaaにbbbをインストールしても、aaaのネストされたライブラリには、既知のセキュリティ脆弱性が残ります。

このような場合、親ライブラリbbbのメンテナーがパッチを提供してセキュリティ脆弱性に対処することで、aaaのネストされた依存関係も修正できます。

まとめ

まとめると、メンテナーがセキュリティ修正を含む新バージョンを十分な速さでリリースできない場合、さらに深刻なケースでは、プロジェクトへの関与をやめて対応しなくなった場合、セキュリティ脆弱性が長期間残るリスクが高まります。こうした理由から、的確なセキュリティパッチは、未修正の脆弱性に先手を打つための重要な手段です。

CTFを始めよう

オンデマンドのバーチャル入門ワークショップを視聴して、CTFの課題の解き方を学びましょう。