パスワードを忘れた? アカウント作成
41559 journal

okkyの日記: Widget と Gadget 5

日記 by okky

ここでいう Widget も Gadget も X11 の用語としてのそれ。ブログパーツの事でもなければ、小型の電子パーツの事でも無い。ちなみに最近は Gadget は RectObj と言うらしい。昔はガジェットだった気がするんだが…。

X11のシステムと言うのはhttp://ja.wikipedia.org/wiki/X_Window_Systemを見てもらえば判るとおり、1987年(21年も前だよ!!年を食ったわけだ)に作られたウィンドウシステムだ。こいつの特徴はhttp://ja.wikipedia.org/wiki/X_Window_System_%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB%E3%81%A8%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3にあるように、Xserverはひたすらウィンドウという名の矩形領域を管理してウィンドウを描画する事にある。各矩形領域に何をどう描くのかは基本的にはクライアントが決める。サーバはひたすらその指示通りに描画する(文字を描くとかそういう部分はサーバが頑張るが)。

で、そんな単純なシステムで、Gnomeのようなものを動かそうとする場合、Clientは膨大な量の「ウィンドウ」をServer上に作り続ける。Window Manager なんかはその酷い例で枠を含めた全体で1つ、右上や左上などにある「ボタン」ごとに1つ、枠も縦横それぞれ2つづつ…もちろん、管理「される」側のウィンドウもいくつもウィンドウを作り、それぞれがその下にあるウィンドウに対する相対位置で制御されていた。おかげで、大昔の非常に遅いマシンでウィンドウを動かすと、root window に近い側から順に再描画し直すのが全部見えるという…

もちろん、そのような仕様になっているのには理由があって、ウィンドウごとにXserverがイベントを管理してくれたのだ。「最大化ボタン」を押したら「最大化ボタンを表示しているウィンドウ」にクリックイベントが発生し、それがクライアントに飛ぶ…と言う具合だ。クライアント側がいちいち「全体におけるカーソル位置がここだからこれは最大化ボタンで…」などと考えなくてよくなる。負荷バランスと言う観点からは非常に優れている。

で、このウィンドウをぐりぐりつくりまくるときに、1つ1つのウィンドウをクライアント側では Widget というデータ構造で管理する。すごく乱暴に言うと1つのウィジェットは1つのウィンドウにマップしていて、クライアントはウィジェットに「あれして、これして」と頼むわけだ。

が、ウィジェットは重たい。そこで、Xtライブラリはウィジェットの上に一層だけ「仮想的な矩形領域」を用意した。これが RectObj とか Gadget と呼ばれるものだ。Gadgetの存在を X11 サーバは知らない。Gadget の Widget への命令変換(主に座標変換だが)はクライアント側で行われる。ウィンドウの形が変更されると Gadget は大騒ぎになり、クライアントのCPUパワーとメモリを喰いまくるのだが、その結果だけがXserverに送られるのでXserverの負荷は軽くて済む。通信量と、server, client のそれぞれの負荷状況によっては Gadget の方が実装としてはよい負荷バランスをもたらしたりする(が、そのバランスは3年もすると崩れる。この辺りはなかなか難しい)。

.

えー、なぜこんな昔話(いや、まだ現役ですって)を延々したかというと。「はてなブックマークの新しい登録ブックマークレットは危険」という表の記事。これの「
はてなはそういうインターフェースにするべきではない、というのはいいのだが…」。これに対するコメントに
http://srad.jp/security/comments.pl?sid=428647&cid=1463656

うわー、なんかものすごい危険な大発明しちゃってませんか?
ブラウザごとにそれぞれの標準スキンそっくりの嘘URL表示することだってできちゃいそう。

というのがあったからだ。

X11を知っている人からすれば、これは出来て当たり前の機能だ

ウェブブラウザというのは、大きなウィンドウ上に文字やら絵やらを配置して描画してくれている。これは強大なGadgetレンダラだ。間違いではない。WidgetではなくGadget。存在する Widget は、本来たった一つ。あなたが見ているページ全体を矩形領域として管理している、Widget だけだった。

Gadgetは Gecko なら Gecko が大雑把に1つのソースからやってきた HTML を元に描画を行う。画像はあっちからとかムービーはこっちからとか、その辺はばらばらだろうが、本質的に全体を制御しているのは1つの html ファイルで、ここは揺るがない。1つの html は 1つのWidget に対応し、そのhtmlをどこから持ってきたかは、上部のアドレスバーに書いてある。

しかし、擬似ウィンドウは「Gadget 上に搭載されたWidget」だ。Javascript を用いて全く違う所から持ってきた描画エンティティを、root Widget 上に描かれた「絵」とは独立したWindowとして描画できるようになっている。

ということは、擬似ウィンドウの上には、Window Manager から何から何まで、全部、root Widget とは別の所から持ってきたものを描ける、と言うことだ。しかも root Widget に対する相対位置は常に制御可能。

ウィンドウマネージャーのように外枠をつけて動かす事もできるし、画面上の一定場所に固定して動かさない事もできる。描画面に対して動かないようにする事もできるけれど、「1つのページ」として定義された矩形領域に対しての相対位置を動かさないようにする事もできる。

さらに言えば、その矩形領域を「透明」にしておいて、なおかつ入力領域に対するキー入力等だけは拾う…なんて事も自在なわけだ。

.

高木先生はGUIが悪いという。安全性を確認できないから、と。でもブラウザ上で複数の Widget が動くようになってしまった今、安全性はどのみち確保できない。

乱暴な話、入力領域にカーソルを載せて「プロパティ」を確認しない限り、余計な「透明Widget」が存在しない保証などどこにもないのだ。

擬似ウィンドウは「確かに」URLを確認しにくい、と言う意味においてよいインターフェースに見えないかもしれない。が、ポップアップウィンドウだろうが、別途ログイン画面に飛ぶのだろうが、インターフェースがどうであれ、その「ウィンドウ」上に複数の Widget が存在できるだんかいで、「プロパティ」をチェックする以外、安全性の確認方法は無い。

というわけで。

実は高木先生のソース記事には解決策は書かれていない。あれでは全然足りないし、もはや打てる手は無いのだ。全てのページを SSL 通信にして、鍵と署名を全部でチェックするのでも無い限り…。

この議論は、okky (2487)によって ログインユーザだけとして作成されたが、今となっては 新たにコメントを付けることはできません。
  • 擬似ウィンドウは、少なくともInternet Explorer 7とOpera 9.62とSafari 3.2.1とGoogle ChromeではGadgetです。FirefoxだけがまだiframeをWidgetで実装していますが、Gadget化する計画 [mozilla.org]があります。WidgetとGadgetが混じるとCSSの仕様に忠実なZ orderの処理などで破綻することが多いので、どのブラウザもどんどんGadget化を進めています。

    さらに言えば、その矩形領域を「透明」にしておいて、なおかつ入力領域に対するキー入力等だけは拾う…なんて事も自在なわけだ。

    こういうことはDOMイベントを監視することでGadgetベースでも問題なく可能なので、なんでWidget対Gadgetという話になるのかよくわかりません。

    ちなみに歴史的経緯からプラグインは原則としてWidgetとして実装されていますが、プラグインによってはオプションでGadgetにすることも可能です。そのプラグインによるクリックジャック [srad.jp]でも、使われているのはGadgetです。

    ポップアップウィンドウだろうが、別途ログイン画面に飛ぶのだろうが、インターフェースがどうであれ、その「ウィンドウ」上に複数の Widget が存在できるだんかいで、「プロパティ」をチェックする以外、安全性の確認方法は無い。

    については、

    (ある人が信用しているWebサイトが、危険な「ページ内JavaScriptウィンドウ」を表示させることがあるかもしれないが、それが悪意あるサイトならば信用するのが誤りであるし、悪意あるサイトでないならば、それはそのWebサイトのセキュリティ脆弱性であって、修正されるべきものである。修正されないようなサイトならば、信用するのが誤りということになる。)

    で十分答えになっている気がするのですが。これは通信路の改ざんなどがないという前提ですが、あったとしても安全なWebサイト利用の鉄則 [aist.go.jp]に従えば十分で、

    鍵と署名を全部でチェックする

    必要などは全くありません。ていうかそもそもWidget対Gadgetとは全く関係ない話だと言わざるを得ません。

    • こういうことはDOMイベントを監視することでGadgetベースでも問題なく可能なので、なんでWidget対Gadgetという話になるのかよくわかりません。

      それは「実装にX11のWidgetを使うかGadgetを使うか」という話と「Widget/Gadgetとはそもそも何か」の違いを理解してらっしゃらないのではないかと。

      X11のWidget/Gadget問題に関しては、おっしゃるとおり。独立したレンダラを必要とするhtmlブラウザの世界では、わざわざX11のWidgetを使わなくてもGadgetで十分ですし、Gadgetの方が厳密に描画ルールを制御できますし、動作性能も保証できます。そもそも「最終イメージにいたるレンダリング処理の、どこまでを、どこでやればいいのか」と言うのはXに限らずグラフィックの世界では常に問題になります。

      しかし、X11においても「同じXserver」が異なるクライアントから来たWidgetを描画する事ができるように、単一のレンダラが2つ以上の情報源から来た描画オブジェクトを1つの描画プレーンに描くことが出来ます。これもWidgetです。HTMLレンダラがそれを単一Widget上に描画してX11(やMS-Windows)に描画せよ、と言っていたとしても、HTMLレンダラのレベルではWidgetです。「Geckoレベルで2つのWidgetがあり、それをGeckoはレンダリングして単一GadgetとしてX11に描画させている」という状態に過ぎません。

      そして今回セキュリティ上の問題をもたらしているのはHTMLレンダラから見てのWidgetです。X11レベルでのWidget/Gadgetではありません。

      .

      ここでいう「描画する」の中には「透明なデータを描画する」事が含まれます。透明なデータというのはいくとおりも実装方法がありますが、ようするに最終病が結果としてそのオブジェクトが存在するのかしないのか、区別する方法が無ければよい。必ずしも「何も描画しない」ばかりが「透明」ではありません。

      (ある人が信用しているWebサイトが、危険な「ページ内JavaScriptウィンドウ」を表示させることがあるかもしれないが、それが悪意あるサイトならば信用するのが誤りであるし、悪意あるサイトでないならば、それはそのWebサイトのセキュリティ脆弱性であって、修正されるべきものである。修正されないようなサイトならば、信用するのが誤りということになる。

      で十分答えになっている気がするのですが。


      なりません。全くもってなりません。

      上記の記述は「ページ内Javascriptウィンドウを表示させる」かどうかを、ブラウザが表示する内容から推定できる、と言う前提があります。しかし「透明なデータを描画できる」と言うことは「あるオブジェクトが描画されているのかいないのか、見てくれから知る術は無い」と言うことです。と言うことは全てのWebサイトは信頼ならないと言っているだけです(もちろん、「自分で作ったページは別にして」という意味ですが)。これはWebなんて信頼ならぬと言っているだけです。信頼できるかどうかを評価するためには毎回ソースを精査する必要があるのですから。

      .

      この問題はX11の時にもあった問題です。X11も初期の段階では「Xserverは全てのマシンからの描画リクエストを受け付ける」状態になっていました。このため、透明なWidgetを作り上げてイベントを全て横取りする事が可能でした。XのときはXserver側でアクセス制限を設定する事でこの問題に対処しました。信頼できるサーバをXserverの利用者が定義していたわけです。Xの場合はこれも可能でした。

      しかし、Webはそもそも html などのソースをあちらこちらから取ってきて、それを手元で描画する事に意味があります。レンダラレベルでは描画データの送り元は多岐に渡らなくてはいけない、X11のときのようにアクセス制御をかければオッケー、とはいかないと言うことです。

      .

      もちろん、透明なWidget以外にも擬態の方法はさまざまあります。ポップアップウィンドウに擬態する擬似ウィンドウ。レンダラの画面全体を覆いつくして「クラシックな見てくれ」を演出する擬似ウィンドウ。

      これらの擬態は一旦始まったら最後、いつ終了しているのか知る術がありません。乱暴な話、
      「ログインとか全く関係ないページで、ファンキーな画面を楽しんだら、実はそこで擬態ウィンドウを仕掛けられた。
        その後ではてなに移動したら、ログイン情報を全部盗まれた。
        はてなが独自の擬似ウィンドウを開く仕様になっていたら、別の擬似ウィンドウからは手の出しようがなかったのに、クラシックな画面デザインだったためにキーストロークイベントを盗まれたのが悪い」
      なんて事だってありえるわけです。信頼できないサイトにアクセスしたら最後、一旦ブラウザを止めない限り、ブラウザ自体が信頼できる状態に戻らない。これはレンダラレベルで複数のWidgetを描画する状態に陥っているからです。

      .

      この問題は Javascriptが高機能化した瞬間に発生しているんです。HTMLレンダラが複数Widgetを描画するようになったのはJavascriptの高機能化に対応するために過ぎません。故に手遅れなんです。
      --
      fjの教祖様
      親コメント
      • by Anonymous Coward
        ふと思ったのですが、
        ブラウザ側が特定の領域を監視して、その上にあるJavaScriptのWidget/Gadgetにマウスカーソルが入ったら、
        当該Widget/Gadgetの枠線を表示するというのはいかがでしょうか。
        加えて、枠線の右上隅に耳をつけて、耳にカーソルを当てると当該Widget/Gadgetの情報をポップアップするようにすれば、
        さらに判断がしやすくなるかと思います。
        • root window サイズ…と言えばいいんだろうか…ようするにブラウザが表示している画面いっぱい+1pixelづつ外側に広がるようにサイズを作られると、結構難しいと思います。

          逆に入力領域ぴったりに作られると「今どこにフォーカスが当っているのか判りやすくしているんだ」としか判断されないかもしれません。Google Chrome の input 領域って、今フォーカスがあたっている部分だけふちの色が違いますよね? こういう機能との区別がつかない可能性がある。

          それでも適用したとしても「色盲対策」なども含まねばなりません。赤と緑が区別できない人に「ふちが赤と緑で点滅している」などというインターフェースを与えてもうれしくないわけです。

          .

          高木先生が問題にしている問題の本質は
          「信頼できないページから、信頼したいページへジャンプしたときに、
            信頼できないページの『信頼できなさ』ぶりが『信頼したいページ』にまで波及するのをどう防ぐか」
          というこの一点に尽きます。

          この問題をUI側で解決するのはとても難しいんです。アドレスを表示させる等の機能はそりゃいくらでも実装できますが、
          「ユーザがそれをチェックしてくれなくなるぐらいアドレスを山のように表示」
          させられたら、結局ノーチェックと同じ状態に陥ります。そして、悪さをしたい側はそういう「物量作戦」と「目の錯覚」を利用して、ユーザを騙しにかかるでしょう。

          可能なのは『信頼できるポイント』から手繰っていくデータが全て信頼できるよう、必要な URL を徹底的に ssl 化するしかないと思います。<script src="http://xxxxx" などという記述は論外という事ですが… /.Jも含めてほとんどのサイトは http ですよね。こういうのを直すほうがUIを直すよりも何億倍も重要です。

          逆にそれらが信頼できるなら、擬似ウィンドウを使うUIでも問題ないと思うんですよ。もちろん、チェックできないという弱点はあるのですが「そもそも信頼できるという前提が立つならチェックする必要は無いだろう」と。
          --
          fjの教祖様
          親コメント
  • by Anonymous Coward on 2008年12月02日 14時12分 (#1465902)
    万一、当事者が気付いていないとつまらないので。

    http://srad.jp/~hylom/journal/460075 [srad.jp]
typodupeerror

日々是ハック也 -- あるハードコアバイナリアン

読み込み中...