--- layout: old_post title: 自由にアクセス制御可能なJavaScriptサンドボックスを作る permalink: /tatsuya/show/407-javascript ---
追記:早速破られた!
safeCall("var w=(function(){return this;}).call();w.alert(w.document.cookie);"); id:kazuhooku - http://b.hatena.ne.jp/kazuhooku/20071206#bookmark-6709542
サイ本よく見ると確かに「オブジェクトのメソッドとして呼び出された関数内でも、入れ子にされた関数内のthisはグローバルオブジェクトを参照します」て書いてあった。あとMDCにも http://developer.mozilla.org/ja/docs/Core_JavaScript_1.5_Reference:Operators:Special_Operators:this_Operator
=========
面白い記事があった、GreasemonkeyのunsafeWindowを安全にすることは可能か
[JavaScript] GM_xmlhttpRequestを使えなくする - 実用
GM評価のsandbox - ゼロメムはてな支店
この記事はGreasemonkeyのunsafeWindowについて(GM実行中サイトが悪意を持っていた場合 or XSSの穴が合った場合対策)だけど 自分もちょうど、JavaScriptを安全に実行する方法が無いか考えていたので、ここに書いてみる。まず目的は
・自サイト上でユーザにJavaScriptを(限定的に)許可したい
例えば、はてなダイアリー等でユーザがブログパーツを張れるよう許可するとか。但し
・document.cookie等、危険な機能は操作不能にする
・あくまでサイト上でJSを許可する(iframeは不可)
で、幾つか考えられるのが以下。
・iframe内で実行
iframeを生成して、そのwindowの中で実行させる。これなら確実に安全なサンドボックスが用意できそうだなと思うけど、今回はスルー
・Facebookアプローチ(変数・関数名にプレフィックスを付けて無害化)
Facebookがユーザに許可するJSでは、変数・関数名にプレフィックスを付けて無害化するらしい
[Facebook] FBJSでFacebookアプリ内でJavaScriptを利用 - Kawa.netブログ(川崎有亮)
面白いな、とも思うけど無害化するロジックに穴があるとセキュリティホールになりそうな気がする。
で、色々調べていて一つ思ったんだけど、こんなのどうだろう
function safeCall(users_code){ var sandbox = { window: null, document: null, alert: null }; with(sandbox){ console.log(eval(users_code)); } }
これならsandboxオブジェクト内に列挙したwindow, document, alert,,,等は、無効化してevalできる筈
確かに列挙したオブジェクトはnullになる、逆に許可したいオブジェクトは含めなければ良い筈。Sandbox.myDocument.myGetElementByIdみたいに許可するネームスペース/クラスを決めてそれを叩いて貰えば制御可能になるかな。と思ったけど、deleteでプロパティ削除されると意味ない
じゃあvarで宣言すればどうだろ?
function sandbox(){ var window = null; var document = null; var alert = null; this.do = function(code){ with(this){ console.log(eval(code)); } } }
原則varで宣言した変数はdelete不可能な筈、これで一応大丈夫?
どうだろ、やっぱり抜け穴がある気がしてならない。。 あと、実際にはwindowのプロパティを列挙する必要がある。
で実際に運用する時は、無害なタグとして記述して貰ってsandbox経由に実行すれば良いかな。今流行の俺俺スクリプト風に
<script type="text/my-safe-javascript"> alert("Hello world from sandbox!!"); </script>
とか書いて貰って、ページ起動時に //script[@type="text/my-safe-javascript"] な要素を探してsandbox経由で実行みたいな。//script[@type="text/javascript"] はサーバ側のフィルタで潰す
うーん、どうだろ?やっぱ何か抜けがあるかな、ある気がする。きっとあるな。