158

HTML ページで実行されている JavaScript コードで通常使用できる機能へのアクセスを防ぐために、ブラウザーで実行されている JavaScript をサンドボックス化することは可能かどうか疑問に思っています。

たとえば、「興味深いイベント」が発生したときに実行するイベント ハンドラーをエンド ユーザーが定義できるようにする JavaScript API をエンド ユーザーに提供したいが、それらのユーザーがwindowオブジェクトのプロパティや関数にアクセスできないようにしたいとします。私はこれを行うことができますか?

最も単純なケースでは、ユーザーが を呼び出さないようにしたいとしましょうalert。私が考えることができるいくつかのアプローチは次のとおりです。

  • window.alertグローバルに再定義します。ページで実行されている他のコード (つまり、イベント ハンドラーでユーザーによって作成されていないもの) が を使用する可能性があるため、これは有効なアプローチではないと思いますalert
  • イベント ハンドラー コードをサーバーに送信して処理します。イベント ハンドラーはページのコンテキストで実行する必要があるため、コードをサーバーに送信して処理する方法が適切かどうかはわかりません。

おそらく、サーバーがユーザー定義関数を処理し、クライアントで実行されるコールバックを生成するソリューションはうまくいくでしょうか? そのアプローチが機能したとしても、この問題を解決するためのより良い方法はありますか?

4

15 に答える 15

54

Google Cajaはソースからソースへのトランスレーターであり、「信頼できないサードパーティの HTML と JavaScript をページにインラインで配置しても、安全なままにすることができます」。

于 2008-10-12T07:35:28.843 に答える
33

Douglas Crockford の ADsafeをご覧ください。

ADsafe を使用すると、ゲスト コード (サードパーティのスクリプト広告やウィジェットなど) を Web ページに安全に配置できます。ADsafe は、悪意のあるまたは偶発的な損傷や侵入を防止しながら、ゲスト コードが貴重な対話を実行できるようにするのに十分強力な JavaScript のサブセットを定義します。ADsafe サブセットは JSLint などのツールによって機械的に検証できるため、ゲスト コードの安全性を確認するために人による検査は必要ありません。ADsafe サブセットは、適切なコーディング プラクティスも実施し、ゲスト コードが正しく実行される可能性を高めます。

プロジェクトの GitHub リポジトリ にあるtemplate.htmlファイルとtemplate.jsファイルを見ると、ADsafe の使用方法の例を確認できます。

于 2008-10-12T20:56:33.547 に答える
23

Web ワーカーを使用して評価されたコードをサンドボックス化するjsandboxというサンドボックス化ライブラリを作成しました。また、他の方法では取得できないサンドボックス化されたコード データを明示的に与えるための入力メソッドもあります。

API の例を次に示します。

jsandbox
    .eval({
      code    : "x=1;Math.round(Math.pow(input, ++x))",
      input   : 36.565010597564445,
      callback: function(n) {
          console.log("number: ", n); // number: 1337
      }
  }).eval({
      code   : "][];.]\\ (*# ($(! ~",
      onerror: function(ex) {
          console.log("syntax error: ", ex); // syntax error: [error object]
      }
  }).eval({
      code    : '"foo"+input',
      input   : "bar",
      callback: function(str) {
          console.log("string: ", str); // string: foobar
      }
  }).eval({
      code    : "({q:1, w:2})",
      callback: function(obj) {
          console.log("object: ", obj); // object: object q=1 w=2
      }
  }).eval({
      code    : "[1, 2, 3].concat(input)",
      input   : [4, 5, 6],
      callback: function(arr) {
          console.log("array: ", arr); // array: [1, 2, 3, 4, 5, 6]
      }
  }).eval({
      code    : "function x(z){this.y=z;};new x(input)",
      input   : 4,
      callback: function(x) {
          console.log("new x: ", x); // new x: object y=4
      }
  });
于 2009-06-21T20:39:46.457 に答える
8

js.jsはここで言及する価値があると思います。JavaScript で書かれた JavaScript インタープリターです。

ネイティブ JavaScript よりも約 200 倍遅いですが、その性質上、完璧なサンドボックス環境になっています。もう 1 つの欠点はそのサイズです。ほぼ 600 KB で、場合によってはデスクトップでは許容できますが、モバイル デバイスでは許容できません。

于 2014-07-03T20:01:48.640 に答える
6

すべてのブラウザー ベンダーと HTML5 仕様は、サンドボックス化された iframe を許可する実際のサンドボックス プロパティに向けて取り組んでいますが、それでも iframe の粒度に制限されています。

一般に、どの程度の正規表現などでも、ユーザーが提供する任意の JavaScript を安全にサニタイズすることはできません。

于 2008-10-12T07:25:44.043 に答える
2

独立した JavaScript インタープリターは、組み込みのブラウザー実装のケージ バージョンよりも堅牢なサンドボックスを生成する可能性が高くなります。

Ryan はすでに js.jsについて言及していますが、より最新のプロジェクトはJS-Interpreterです。ドキュメントには、さまざまな関数をインタープリターに公開する方法が記載されていますが、それ以外の場合、その範囲は非常に限られています。

于 2016-08-11T13:44:30.017 に答える
0

2019 年の時点で、vm2はNode.js でJavaScript を実行するための最も人気があり、最も定期的に更新されているソリューションのようです。フロントエンドのソリューションを知りません。

于 2019-08-07T09:46:08.013 に答える
-3
  1. 実行するコードがあるとします。

     var sCode = "alert(document)";
    

    ここで、サンドボックスで実行するとします。

     new Function("window", "with(window){" + sCode + "}")({});
    

    「アラート」機能は「サンドボックス」からは利用できないため、これらの 2 行を実行すると失敗します。

  2. そして今、あなたの機能を使用して window オブジェクトのメンバーを公開したいと考えています:

     new Function("window", "with(window){" + sCode + "}")({
         'alert':function(sString){document.title = sString}
     });
    

確かに、引用符のエスケープを追加したり、その他の磨きをかけることができますが、アイデアは明らかだと思います。

于 2008-10-12T09:32:36.220 に答える
-4

このユーザー JavaScript コードはどこから来たのですか?

ユーザーがページにコードを埋め込んで、それをブラウザから呼び出すことについてできることはあまりありません ( Greasemonkeyを参照)。それはブラウザが行うことです。

ただし、スクリプトをデータベースに保存し、それを取得して eval() すると、実行前にスクリプトをクリーンアップできます。

すべてのウィンドウを削除するコードの例。とドキュメント。参照:

 eval(
  unsafeUserScript
    .replace(/\/\/.+\n|\/\*.*\*\/, '') // Clear all comments
    .replace(/\s(window|document)\s*[\;\)\.]/, '') // Removes window. Or window; or window)
 )

これにより、次の実行が防止されます (テストされていません)。

window.location = 'http://example.com';
var w = window;

安全でないユーザー スクリプトに適用しなければならない多くの制限があります。残念ながら、JavaScript で使用できる「サンドボックス コンテナー」はありません。

于 2008-10-12T06:44:04.690 に答える
-5

私は、ユーザーが自分のサイトのアプレットを作成できるようにするための単純な JavaScript サンドボックスに取り組んできました。私はまだDOMアクセスを許可することでいくつかの課題に直面していますが(parentNodeは物事を安全に保つことができません=/)、私のアプローチはウィンドウオブジェクトをいくつかの有用な/無害なメンバーで再定義し、次にユーザーをeval()することでしたこの再定義されたウィンドウをデフォルトのスコープとしてコードします。

私の「コア」コードは次のようになります...(完全には示していません;)

function Sandbox(parent){

    this.scope = {
        window: {
            alert: function(str){
                alert("Overriden Alert: " + str);
            },
            prompt: function(message, defaultValue){
                return prompt("Overriden Prompt:" + message, defaultValue);
            },
            document: null,
            .
            .
            .
            .
        }
    };

    this.execute = function(codestring){

        // Here some code sanitizing, please

        with (this.scope) {
            with (window) {
                eval(codestring);
            }
        }
    };
}

そのため、サンドボックスをインスタンス化し、そのexecute()関数を使用してコードを実行できます。また、eval されたコード内で新しく宣言されたすべての変数は、最終的に execute() スコープにバインドされるため、名前が衝突したり、既存のコードを台無しにしたりすることはありません。

グローバル オブジェクトには引き続きアクセスできますが、サンドボックス化されたコードに認識されないようにする必要があるオブジェクトは、Sandbox::scope オブジェクトでプロキシとして定義する必要があります。

于 2009-05-20T14:10:09.137 に答える
-6

禁止されたオブジェクトをパラメーターとして再定義する関数でユーザーのコードをラップできます。これらは、undefined呼び出されたときに次のようになります。

(function (alert) {

alert ("uh oh!"); // User code

}) ();

もちろん、巧妙な攻撃者は、JavaScript DOM を検査し、ウィンドウへの参照を含むオーバーライドされていないオブジェクトを見つけることで、これを回避できます。


もう 1 つのアイデアは、JSLintなどのツールを使用してユーザーのコードをスキャンすることです。事前設定された変数がない (または、必要な変数のみが含まれる) ように設定されていることを確認してから、グローバルが設定またはアクセスされている場合は、ユーザーのスクリプトを使用しないでください。繰り返しになりますが、DOM のウォークに対して脆弱である可能性があります。ユーザーがリテラルを使用して構築できるオブジェクトは、サンドボックスをエスケープするためにアクセスできるウィンドウ オブジェクトへの暗黙的な参照を持っている可能性があります。

于 2008-10-12T06:26:01.213 に答える