Paraquire、またはライブラリの信頼を停止

TL DR



NodeJSパッケージマネージャーであるnpmを使用すると、セキュリティの問題が発生します。 通常の方法では、ライブラリに付与されるアクセス権を制御することは不可能です。 豊富なマイクロモジュールと一緒に、これは予測不可能な結果を​​もたらす可能性があります。すでに起こったことの一部をここで説明します 。npmエコシステムの最高の伝統では、私はそれを参照します。













猫の下では、Androidでアプリケーションに特定の許可を発行できるように、許可を設定する機能を持つnpmモジュールをロードするメカニズムを実装する概念実証ライブラリが説明されています。



代わりに



var lib = require('untrusted-lib');
      
      





どこかに書くように誘われた



 var paraquire = require('paraquire')(module);
      
      





そして



 var lib = paraquire('untrusted-lib');
      
      





または



 var lib = paraquire('untrusted-lib', {builtin:{https:true}});
      
      





ソースコードは LGPLv3の下のgithubで入手できます。



さらに、私はかなり経験豊富なNodeJS開発者ではないので、コミュニティにアドバイスや議論を求めます。



簡単な履歴分析



現在、npmおよびそのパッケージに対するいくつかの攻撃ベクトルが知られています。 攻撃のための最も魅力的なパッケージは、他の多くのパッケージが依存しているパッケージです。



  1. パッケージのリコール。 左パッドのパッケージを思い出したAzer Kochuluによって壊滅的なデモンストレーションが行われました。 現在、実現不可能です パッケージのリコールは非常に限られています。

  2. 悪意のあるプレインストールおよびポストインストールスクリプト。 現在、主な攻撃方法(上記のリンクを参照)。 理論的には、シェルスクリプトを実行する前に警告が表示されるnpm installフラグによって簡単に抑制できるため、プログラマー自身が提案されたスクリプトを実行するかどうかを決定できます。 プレインストールスクリプトがPhantomJS(ヘッドレスブラウザー)を実行しようとする場合と、小さなライブラリで行の左側にスペースを追加する必要がある場合は、まったく別の問題です。 このようなフラグがまだ導入されていない理由は不明です。

    UPD:行う機会についてのコメントをくれたSDSWandererに感謝



     npm install --ignore-scripts
          
          





    ただし、対話型オプション(できればスクリプトの内容を表示)も見逃せません。

  3. そして最後に、 ここでコミック形式説明されているように、パッケージの実行可能コードに悪意のある負荷を直接隠すことができます 。 パッケージバージョンをハードに修正するnpm shrinkwrapコマンドは、たとえば特定の日付を待機している「スローモーション鉱山」には役立ちません(「チェルノブイリ」を思い出してください)。 さらに、現在の依存関係が豊富なため、目的のパッケージの1つのバージョンのソースコードと、このパッケージが使用するすべてのソースコードの監査は、もちろん実行可能なタスクですが、明らかに日常的ではありません。



paraquireライブラリが作成された最後のベクトルと戦うことです。 信頼できないライブラリコードは、個別の実行コンテキストで分離されます。 モジュール管理のためにNodeJSの内部ツールを積極的に使用しました。 言い換えると、代替モジュール管理システムが作成され、その可能性はNodeJS開発者自身によって明確に示されています。



使用する



現在、APIは非常に貧弱です。



したがって、まずは、paraquireライブラリ自体を比較的信頼できるコードのどこかにロードします。 私たちのアプリケーションコード:



 var paraquire = require('paraquire')(module);
      
      





「(モジュール)」に注意してください。 paraquireはモジュールを管理するため、依存関係を接続する必要があるモジュールを知る必要があるため、paraquireの接続はやや珍しいように見えます。 paraquireは、プロジェクトの任意の数のモジュールに接続できます。



次に、依存関係を接続します。 たとえば、untrusted-libをライブラリとして、理論上は何も必要としないようにします(たとえば、 leftpadimurmurhash )。 次に、次のように接続することで、彼女に何にもアクセスできないようにします。



 var lib = paraquire('untrusted-lib');
      
      





それだけです。untrusted-libコードでrequire( 'fs')を作成しようとすると、エラーがスローされます。



paraquire関数には、2番目のオプションのオブジェクトパラメーターもあります。 たとえば、これは、untrusted-libライブラリに組み込みのhttpモジュールとhttpsモジュール、およびconsoleとprocess.argvへのアクセスを許可する方法です。



 var lib = paraquire('untrusted-lib', { builtin: { http: true, https: true, }, sandbox: { console: console, process: {argv:process.argv} }, });
      
      





ところで、特にprocess.envおよびprocess.bindings( 'fs')のため、プロセス全体へのアクセスを強くお勧めしません。



アドバイスをお願いします



前述のように、私は十分な経験のある開発者ではないため、この短い出版物は、より迅速に議論を開始することを目的としています。 このトピックは関連性がありますか? このような問題は、他の言語、特にRubyやPythonでどのように解決されますか? 誰かがパラクレアを回避して昇格した特権を取得する方法を提案できるでしょうか?



APIはどの方向に開発されるべきですか? たぶん、あなたは外国のマスターの一人と相談する必要がありますか? 今後の記事で取り上げるべき質問は何ですか?



All Articles