RequestPolicyを試してみる

「NoScript」をやめて「RequestPolicy」にした で紹介されていたので、RequestPolicy (0.5.5) を使ってみた。

このプラグインは、訪問先のドメイン*1ごとに、別ドメインへの(ユーザが明示的に行った場合以外の)リクエストの許可/不許可を設定できる、というもの。RequestPolicy は無許可での他ドメインのコンテンツのロードを禁止してくれるので、JavaScriptがオフでも防げないclickjacking のような攻撃も防御できるし、NoScriptの「信頼して何でも許可していたサイトがクラックされたら、やりたい放題」という点をカバーできる。公式サイトのFAQにあるとおり、NoScriptの対抗馬というわけではなく、別のアプローチからセキュリティとプライバシーを守りましょう、という感じらしい。あと、リクエストのログが確認できるので、どんなリクエストがブロックされたかを確認でき、要不要の判断もしやすい。なかなかいい感じ。

一応以下のようなページで、いくつかのパターン

  • onload
  • ユーザの操作がトリガーにはなるけど、無関係のformを送信
  • ユーザの操作がトリガーで、さらに同一のformを送信
<html>
<body onload="document.forms[0].submit();">
<a href="#" onclick="document.forms[0].submit();">ただのリンクですよ</a>

<form action="http://example.com/">
<input type="text" onkeypress="this.form.submit();" />
<input type="submit" />
</form>
</body>
</html>

も試したけど、きちんとブロックしてくれた。submitボタンを押したときだけは確認なしに送信が行われるけど、これは明示的なリクエストの結果だから問題ないと思う*2

ただ、よくわからない挙動もある。たとえば上のページを訪問した際、最初はきちんとブロックしてくれるんだけど、一回 submit ボタンを押して能動的にform送信を行うと、もう一度上記のページを訪問したときには、何も許可設定を追加していないのに今度は勝手にフォーム送信が行われてしまった。

ユーザが明示的にsubmitを行うと、「安全な送信先」だということを一時的に記憶してくれたりしているんだろうか。個人的には、余計な機能だと思うんだけど……。まあ、Firefoxを再起動するともう一度ブロックしてくれるみたいだし、別ページの同一送信先へのフォームや、同じフォームの送信先を書き換えたりした場合もブロックしてくれるので、問題にはならないのかな。

追記

ちょこっと見てみたら、「能動的なリクエストか自動リクエストか」を判断するのは、やっぱりRequestPolicyががんばっているみたい。たとえばこんなことが書いてあった(以下、chrome/requestpolicy.jar/content/overlay.js から引用)。

        // Add a submit handler so we can register all form submissions and be
        // able to allow them.
        // As far as I can tell, calling a form's submit() method from
        // javascript will not cause this event listener to fire even though it
        // will submit the form, which makes things easier in that we don't have
        // to find another way to tell if the user submitted the form or if it
        // was done by javascript. However, I'm not sure on the specifics of why
        // submit() from javascript doesn't end up calling this. I can only
        // conclude it's the ame difference as with link clicks by humans vs.
        // click(), but that the documentation just doesn't state this (with the
        // exception that nonprivileged code can call submit(), but it just
        // doesn't result in a submit event going through the DOM).
        appcontent.addEventListener("submit", function(event) {
              if (event.target.nodeName.toLowerCase() != "form") {
                return;
              }
              requestpolicyOverlay._rpService.registerFormSubmitted(
                  event.target.ownerDocument.URL, event.target.action);
            }, true);

上で書いた「よくわからない挙動」の仕組みとしては、

  • 上のように、イベントを監視して、正当なリクエストと判断したらその送信元と送信先を RequestPolicy 内部に登録する。例えば RequestPolicyService の registerFormSubmitted は RequestPolicy が内部で持っている「ちゃんと送信されたフォーム一覧」に送信元と送信先を登録するもの。
  • その後、実際にリクエストを送ろうとするところを全てキャッチして、送信内容が「ちゃんと送信されたフォーム一覧」に含まれているならOKとする。

という感じの流れがあった上で、「ちゃんと送信されたフォーム一覧」はブラウザ再起動までクリアされないから、というのが理由っぽい。「ちゃんと送信されたフォーム一覧」に登録された「送信元」と「送信先」にはドメインだけでなくパス情報も含まれるから、別ページに置かれたフォームだったりするときちんとブロックされる。

なるほどねー。

*1:厳密には、設定によってポート番号も含めた制御も可能

*2:こういう「能動的なリクエストか自動リクエストか」を判断するのは、Firefoxなんだろうか、RequestPolicy ががんばっているんだろうか? Firefox側だったらいいんだけど、詳しくないのでよくわからない