タイポスクワッティングとは?npmの悪意あるモジュールを生み出す攻撃の仕組み
2021年1月12日
0 分で読めます悪意のあるDockerコンテナや、さまざまなエコシステムの公開レジストリに登録された悪意のあるオープンソースパッケージなど、悪意のあるパッケージについて耳にしたことがあるかもしれません。Snykは、SourMintと名付けた、モバイルアプリのマルウェアに関する詳細な調査結果も公開しています。
これまでに、こうしたセキュリティインシデントをいくつか取り上げてきました。影響を受けたエコシステムは1つだけではありません。
JavaScriptのnpmエコシステムで、悪意のあるバージョンが公開された人気パッケージevent-streamのインシデント
人気のRuby gemプロジェクトbootstrap-sassとstrong_passwordで発生した、悪意のあるリモートコード実行
ただし、悪意のあるパッケージはすべて同じ性質を持つわけではありません。エコシステムのレジストリに関して、大きく次のいずれかに分類できます。
タイポスクワッティング攻撃 - 攻撃者がユーザーをだましてインストールさせようと、悪意のあるパッケージをレジストリに公開する攻撃です。PyPIとNode.jsのレジストリの両方で、こうしたパッケージが確認されています。なかでも特に注目されたのがcrossenvです。人気パッケージcross-envによく似た名前を使い、同じ機能を提供しながら、環境変数を収集して攻撃者が管理するリモートサーバーに送信していました。
アカウントの侵害 - オープンソースプロジェクトのメンテナーが、他の開発者よりセキュリティに詳しいとは限りません。そのため、公開権限に関わるシークレットの取り扱いが不適切になることがあります。複数のメンテナーがいるプロジェクトでは、全員にプロジェクトのポリシーを徹底する必要があり、状況はさらに複雑になります。一部のレジストリで適切な認証制御が不足していることも、アカウント侵害の原因になり得ます。それでも、侵害されたアカウントが管理するプロジェクトは非常に人気がある場合があり、エコシステムにすぐさま影響を及ぼすため、深刻なセキュリティインシデントにつながる可能性があります。
依存関係グラフを利用したソーシャルエンジニアリング - オープンソースは、コラボレーションを積極的に受け入れ、歓迎しています。しかし、プルリクエストに悪意のあるコードが1行追加されれば多くの人がすぐに気づくでしょう。一方、プロジェクトの依存関係に悪意のあるコードが追加された場合は、話が異なります。
タイポスクワッティング攻撃
前述のように、リポジトリに公開される悪意のあるパッケージやバージョンの中でも、タイポスクワッティングは特に一般的です。攻撃者が参入するハードルが非常に低く、対抗策もあまりないためです。
タイポスクワッティング攻撃とは?
タイポスクワッティング攻撃とは、攻撃者がユーザーをだましてインストールさせようと、悪意のあるパッケージをレジストリに公開する攻撃です。npmやPyPIなどの公開ソフトウェアレジストリでは、すでにこうした試みが確認されています。
これは、入力ミスを利用するウェブサイトのフィッシング攻撃によく似ています。たとえば、誤ってhttps://bankofamerca.comと入力し、本来のhttps://bankofamerica.comとは異なるサイトにアクセスしてしまうケースです。前者のドメインを攻撃者が管理していれば、本物のサイトを装った偽サイトを作り、認証情報や銀行口座などの機密性の高い金融情報を盗み出すことができます。
2017年までさかのぼる、Snykの脆弱性データベースで確認されたタイポスクワッティングによる悪意のあるモジュールの例です。脆弱性は次々と報告されています。

2020年にはタイポスクワッティングはなくなったと思っているなら、考え直してください。

crossenvの事例
特に注目すべきタイポスクワッティング攻撃の事例が、crossenvです。攻撃者は人気パッケージcross-envによく似た名前を使い、元のモジュールとまったく同じ機能を実装していました。そのため、問題なく動作するパッケージだと思わせることができました。しかし実際には、環境変数を収集し、攻撃者が管理するリモートサーバーに送信していました。
7月19日、npmユーザーのhacktaskは、被害者がインストールするよう仕向けて環境変数を盗み出すために使われた、30を超える他の悪意のあるパッケージの1つとしてcrossenvを公開しました。
C J Silverioがブログで紹介したとおり、npmの公開レジストリに存在していた期間中のダウンロード数とともに、パッケージの全リストを掲載します。
crossenvのような悪意のあるパッケージは、どのようなものなのでしょうか?
悪意のあるパッケージcrossenvの事例を詳しく見るため、まずはpackage.jsonファイルから確認しましょう。

package.jsonファイルを見ただけでも、いくつか不自然な点に気づきます。
2行目:パッケージ名が明らかに誤っています。ただし、見過ごされたと仮定しましょう。
13行目:本物のcross-envパッケージをバンドルしています。ご覧のとおり、バージョンもモジュール自体のバージョン(3行目の6.1.1)とは異なる5.0.1です。
8行目:ここで疑いの目を向けるべきです。
package-setup.jsには何が書かれているのでしょうか?また、このパッケージにどのようなセットアップが必要なのでしょうか?
node package-setup.jsの全容に踏み込む前に、いったん立ち止まり、この行がなぜ重要なのかを説明しましょう。postinstallというrun-scriptは、npmに組み込まれたパッケージのライフサイクルフックの1つで、パッケージのインストール時に自動実行されます。
postinstallのrun-scriptに指定されたコマンドは、スクリプトを自分のコードから呼び出しているかどうかにかかわらず、npm installの実行時に実行されます。
第1幕:npmパッケージに仕込まれた悪意のあるペイロード
調査を進め、package-setup.jsファイルの内容を確認すると、悪意ある仕組みが明らかになります。

このスクリプトはnpmパッケージのインストール処理中に実行され、process.envを使ってすべての環境変数を収集します。それらをBase64でエンコードしたペイロードに変換し、HTTP POSTリクエストで攻撃者が管理するリモートサーバーに送信できる状態にします。
悪意のある処理はインストール時に一度だけ実行されます。その後もcrossenvパッケージは、本物のcross-envパッケージをラップして、もともとインストールされた目的の機能を提供し続けるため、問題が見過ごされてしまいます。
第2幕:悪意のあるパッケージの影響を考える
このセキュリティ脆弱性を発見し、明らかにすることは重要ですが、それだけでは十分ではありません。どのような被害が起こり得たのか、この攻撃を受けた場合に何が起きるのかを理解するため、いくつか考えてみましょう。
環境変数には、どのような情報を保存していますか?
開発者がこれをブランチにマージし、CIサーバーで実行していたらどうなっていたでしょうか?さらに、本番サーバーにデプロイされていたらどうでしょうか?
環境変数を読み取るだけで攻撃が終わらず、バックドアの設置や、自己複製するワームによる環境の感染など、さらに悪質な手口に及んでいたら、どのような影響があったでしょうか?
終幕:npmでこの悪意のあるパッケージをどうやって発見したのか?
スウェーデンのソフトウェアエンジニア、Oscar Bolmstenは、crossenvパッケージに悪意のある活動の可能性があるとツイートしました。どうやら2週間もの間、気づかれていなかったようです。
https://twitter.com/o\_cee/status/892306836199800836?ref\_src=twsrc%5Etfw
対策として何ができるでしょうか?
環境変数には、機密情報を保存しないでください。
リポジトリをSnykに接続すると、プロジェクトの依存関係を毎日監視し、悪意のあるパッケージやその他の脆弱性が見つかった場合にお知らせします。修正可能なセキュリティ脆弱性が見つかった場合は、修正用のプルリクエスト(またはマージリクエスト)をリポジトリに自動で作成します。
パッケージをインストールする前にSnyk Advisorを確認すれば、パッケージの健全性、人気度、メンテナンス状況、セキュリティなどの情報を把握できます。
パッケージをインストールする際は、npm CLIの
--ignore-scriptsフラグを使うと、インストール中にサードパーティパッケージのスクリプトが実行されるのを防げます。実際にインストールする前にパッケージの健全性を確認し、安全にインストールする方法として、npqの利用を検討してください。
npmのセキュリティに関するベストプラクティスやヒントについては、npmセキュリティチートシートをご覧ください。



