金利0無利息キャッシング – キャッシングできます

2012-04-26

jQueryのXSS引き起こしやすい問題に対する動的パッチ

22:52 | jQueryのXSS引き起こしやすい問題に対する動的パッチ  - 金利0無利息キャッシング – キャッシングできます を含むブックマーク はてなブックマーク - jQueryのXSS引き起こしやすい問題に対する動的パッチ  - 金利0無利息キャッシング – キャッシングできます

この問題 http://subtech.g.hatena.ne.jp/mala/20110624/1308881526

このパターンのXSSは未だに非常に多く見かける。jQueryを最新版にすれば、#が含まれるパターンは防げるのだけど、$("a[rel=" + user_input_string +"]")といったケースが防げない。1/3ぐらいはアップデートしても問題があるという印象。

ついでに、jQuery Mobileの古いバージョンを使ってるサイトも非常に多い印象。http://subtech.g.hatena.ne.jp/mala/20110711/1310391177

jQueryXSSは「知らないとXSSを引き起こす可能性が高い」というもの(ポテンシャル)だけど、jQuery Mobileのbeta1より以前のバージョンは素のまま使っていれば、読み込んだだけで必ずXSSがあるというものです。jQuery Mobileの古いバージョンを使ってるサイトは基本的に必ずXSSがあります。

というわけでjQuery本体に手を入れずに直すパッチを書いた。こんな人が使うと良いです。

  • jQuery本体をバージョンアップして平気かどうか分からない。
  • jQueryに起因するXSS脆弱性が見つかっていますぐ何とかしたいが修正箇所が分からない。
  • 保険的対策として予期せぬタグ生成を抑止したい。

jQueryを読み込んだ直後に実行すればok。$ではなくjQuery.fn.initを書き換えてるので、$やjQueryがコピーされてても反映される。DOMReadyの前に適用されてれば、jQueryセレクタ誤認問題に起因するXSSは防げるはず(このコード読みこむ前にjQuery.fn.initを直接コピーして実行してるコードがあるとNG)

内容は見ての通り

  • タグ生成だと判別されるsyntaxで、開始が "<" もしくは スペース + "<" でなければエラーにします。
  • classNameに< >を使ってる場合のCSSセレクタなんかも問答無用でエラーになりますが、元から正常に引く方法が無いので気にしない。

副作用は殆ど無いはず。

https://gist.github.com/2499522

(function(){
    jQuery.fn.__init = jQuery.fn.init;
    var old_expr = /^(?:[^<]*(<[\w\W]+>)[^>]*$)/;
    var strict_expr = /^\s*</;
    jQuery.fn.init = function(selector, context, rootjQuery){
        if (typeof selector === "string") {
            // console.log(selector);
            if (old_expr.test(selector) && !strict_expr.test(selector)) {
                throw 'Syntax error, html string must start with "<"';
            }
        }
        return new jQuery.fn.__init(selector, context, rootjQuery);
    };
})();

2012-04-05

Shibuya.XSSで発表してきました

19:12 | Shibuya.XSSで発表してきました  - 金利0無利息キャッシング – キャッシングできます を含むブックマーク はてなブックマーク - Shibuya.XSSで発表してきました  - 金利0無利息キャッシング – キャッシングできます

http://atnd.org/events/25689

以下資料、適当に口頭で補足しながらしゃべりました。オフレコ部分は抜いてあります + 参考URL等を少し足しました。

----

DOM Based XSSの傾向と対策

DOM Based XSS

  • 基礎的な説明は省略
  • 機械的なスキャンで見つからない
  • 人間が読んでも見つけにくい

ログに残らないことがある

  • location.hash経由で発火が多い
  • サーバー側のアクセスログに残らず
  • ビーコン等でlocation.hash記録するものも有り
    • XSS発動が先なら妨害できる

location.hash経由

どうやると見つけられるか?

どんなときに見つけにくい?

  • パラメータパースして利用しているとソース読まないと無理
  • どこに起因する入力かわかりにくい
  • 難読化されてると異常に見つけにくい
    • レガシーコードも・・・

どう直すのが良いのだろう?

  • バリデーションせよ?
  • バリデーションが必要な状況になったら疑え!!

バリデーションが必要な状況

  • openにファイル名渡す → パイプでコマンド実行可能
  • ファイル開く関数とコマンド実行と分けろ!!
  • 役割に応じて「それしかできない」ようにする

バリデーションが必要なライブラリ

  • 直接使うインターフェースは安全側に倒す
  • 何でも出来るメソッドにはrawとかつけとけばいい

そもそも安全にすることを考える

  • 外部リソース読み込めないように → XHR無理・・・
  • jQuery本体で対応 → 一部未対応のまま

コーディング規則での対応

  • jQueryの場合
  • HTML使う必要ないなら.text()で出力
  • $("#id").find でセレクタとしてしか機能しない
  • $()関数は汎用的すぎ → どの機能が発動するか分からない

コーディング規則での対応 2

  • XHRのリクエスト先には必ず 絶対パス + 動的部分
  • 絶対パスが / だけだと突破可能
  • /api/ + 動的 とか。

問題点

  • 攻撃手法を知らないと問題のないコードに見えてしまう
  • XHR level2で今まで平和だったコードが突如危険に
  • HTML5API設計そのものに問題が・・・

DOM XSS撲滅装置

  • location.hashにタグ含まれていたら消す etc
  • その文字列を使わないことが保証できてるなら割と効果ある
  • 広告やブログパーツ等、自分で直せない場合の応急処置に。

パスワードを盗めるか?

  • ブラウザのパスワード保存機能と組み合わせてパスワードを自動で盗めることがある
  • ログインページにXSSがある、ログインフォームがあるドメインにXSSがある
  • http://subtech.g.hatena.ne.jp/mala/20110428/1303982930
  • 組み合わせでリスクが増加 セッション乗っ取り → 恒久的な乗っ取り

パスワードの盗み方

  • 自動フィルインされた値を読み取る → 自動的に発動
  • 自動フィルイン + クリックジャッキング → 半自動
  • フォームの宛先を変える + 気付かずに入力

事例

  • ログイン後のURL指定でjavascript:が可能
  • 気付かないでログインしたらパスワードが取得可能
  • パスワード自動フィルイン + クリックジャッキングでパスワード取得

そもそもの対策

  • パスワード入力させるドメインをサブドメインにして独立させる
  • login.example.com
  • そのドメインには全力でXSSが無いようにする
  • 余計な機能を付けない、外部jsを入れない

そもそもの対策 2

  • XSSがあってもcookie読めないように
  • SSLページはセッション分けてcookieにsecure属性つける
  • httponlyつける → JavaScriptからcookie抜けないようになる

パスワード盗める事例

  • パスワード保存機能使ってるユーザーの場合、可能性はある
  • 実際に盗まれた可能性は低い → 全ユーザーのパスワード変更?
  • パスワード保存は自己責任?ブラウザの責任?

XSSでパスワード盗めてしまうと

  • 脆弱性があった場合のリスクが増加する
  • 公表、周知が難しくなる → 悪循環
  • 影響が限定的になるようなデザインを

フェイルセーフ設計

  • サンドボックス度合いの調整が必要
  • パスワード入力、個人情報表示するドメイン
  • アプリ動いてるドメイン
  • 新米エンジニアがアプリ書くゾーン
  • ユーザーが自由にHTML書けるゾーン

必要なセキュリティレベルに応じたポリシーを

  • 例えば
    • パスワード入力するようなページでは外部js絶対ダメ!!
    • アプリ動かすドメイン: ある程度信用できるならOK
  • など

ブラウザ側でのリスク軽減

  • XSSフィルタ、不審なリダイレクトの検知。
  • パスワードの自動フィルイン対策(OperaやSecureLogin拡張)
  • もともと危険だったものが更に危険になる → 理解されないことが多い

攻撃者視点で考える

  • ユーザーに気付かれないようにするに悪用したい場合
  • 1. iframeで埋め込む → サードパーティCookie有効なら発動
  • 2. 短縮URL + history.replaceStateでURLを偽装して通常通りに見せる
  • 3. ポップアップWindowで攻撃URLを開いてすぐ閉じる → サードパーティCookie無効でも死ぬ

ログに残さないテクニック

  • eval(location.hash.substring(1)) されると何されたか分かんない
  • eval(name) も

ユーザー側で出来ることは何なのか?

  • NoScript?
  • 複雑なルールを設定しなければ安全に利用できない
  • 攻撃者が嫌う設定を使う
    • サードパーティCookieオフ、popup常に確認、リダイレクト抑止
  • 初見のURLは全部シークレットモードで開くとか

まとめ

  • DOM Based XSSはたくさんあります
  • XSSがあっても安全にすることを考える
トラックバック - http://subtech.g.hatena.ne.jp/mala/20120405

2012-03-27

localStorageをサードパーティCookieの代用として使う人々に伝えたいこと

00:34 | localStorageをサードパーティCookieの代用として使う人々に伝えたいこと - 金利0無利息キャッシング – キャッシングできます を含むブックマーク はてなブックマーク - localStorageをサードパーティCookieの代用として使う人々に伝えたいこと - 金利0無利息キャッシング – キャッシングできます

セキュリティ的なことについて

  • localStorageにデータを保存して別ドメインからpostMessageで読み出すというものなのだけど、保存したデータをどのドメインからでも参照可能になってる事例を3件連続で見た。
  • これ読んで欲しい https://developer.mozilla.org/ja/DOM/window.postMessage#.E3.82.BB.E3.82.AD.E3.83.A5.E3.83.AA.E3.83.86.E3.82.A3.E3.81.AB.E9.96.A2.E3.81.99.E3.82.8B.E3.81.93.E3.81.A8
  • 1件は知り合いが働いてたり、まあ言えばすぐ直りそうだなと思って伝えたら当日中に直った。あと2件は放ってあってまだ連絡してない(自主的に直ると良いと思う)
  • サードパーティCookieを使っている場合、意図的にそういうコードを書いていなければ第三者から参照されることがない。
  • localStorage + postMessageは、意図的にsame origin policyを破壊したい時に使うテクニックだ。
  • どのドメインに対して許可するかは「自前で面倒を見なくてはいけない」
  • Cookie MatchingとかCookie Syncとか呼ばれる技術があることは知ってるけど、生のトラッキングidを直接交換する必然性はないはず。

モラル的なことについて

  • localStorageをcookie代わりに使うな!!!と言えば簡単なのだけど
  • Safaricookieに関するポリシーは腐っているし、俺はAppleを快く思ってない。
    • そもそもSafariは特定のドメインだけ許可するようなことが出来ない。
    • 常にユーザーに選択肢が与えられるべきだと思っている。
  • トラッキング目的での使用が横行した場合、そのうちサードパーティCookieオフの場合にはサードパーティのlocalStorageもブロックされるようになるだろう(Google Chromeみたいに)
  • localStorageは「そういうコードを書かない限り」サーバーに送られないので、ブラウザ側でCookieと同列に扱われるのは間違いで、独立した設定を持つべきだと考えている。
  • しかしトラッキングに使われるのが横行すると、区別がされなくなってしまう。

はー、なんか色々言いたいことあるけど、面倒くさいのであとで書くわ。

トラックバック - http://subtech.g.hatena.ne.jp/mala/20120327

2012-03-16

クライアントサイドでのDoNotTrackの使い道とその違和感について

13:44 | クライアントサイドでのDoNotTrackの使い道とその違和感について - 金利0無利息キャッシング – キャッシングできます を含むブックマーク はてなブックマーク - クライアントサイドでのDoNotTrackの使い道とその違和感について - 金利0無利息キャッシング – キャッシングできます

https://developer.mozilla.org/en/DOM/navigator.doNotTrack

function some_tracking_code(){
	if (navigator.doNotTrack && navigator.doNotTrack == "yes") return;
	...
}

こういう使い方をすると、サーバー側で「DNTが守られているのか?」なんてことを気にせずに、そもそもトラッキングされていないことがユーザーから確認できて便利。DoNotTrackが「お願い」ではなく、ユーザーから見てちゃんと何が起きているのか分かる。

Googleがパーソナライズド広告の有無によって広告の数を調整しているように http://gyazo.com/58419e766c579c24e16f74ebbf793d99

トラッキングされている場合は、効果的な広告が出せるから広告の数を減らして、DNTが有効の場合は広告の数を増やすというのも考えられる。けど多分DNTを有効化するような人は、そもそもあまり広告をクリックしないんじゃないかとも思う。

ただ、この手の実装(クライアントサイドでdoNotTrackを見る)には問題がいくつかある

  • DNTの値が常に一律であることを前提にしてる。
  • 「サイトオーナーによるアクセス解析」は許容してるけど「広告屋のトラッキング」は望んでいないという場合もあるだろう
  • JavaScriptが実行されるドメインと、サードパーティによるトラッキングでデータが送信されるドメインが多くの場合異なる。

「ドメインごとにDoNotTrackの有無を切り替える」と「クライアントサイドでそもそもトラッキングを行わない実装」を両立するのは困難で、真面目に実装しようとすると実行しているJavaScriptがどのソースに起因するかに応じて、navigator.doNotTrackの値を切り替えるとか、そういうすごく面倒くさいことになる。そういう面倒くさい実装は多分好まれないし、ユーザーがドメインごとに使い分けるみたいなのも、UIが複雑になるので多分起こらない。任意のドメインに対してDoNotTrackを有効化してるかどうか調べられる、なんてAPIを備えたらそれはそれでクロスドメイン制約を突破してるし、ブラウザフィンガープリントに使えることになったりして問題だろう。

透明性を確保するためにはクライアント側でDoNotTrackの値を見て、そもそもトラッキングが行われていないのを確認できる実装が望ましいけれど、それを実現するためには(現実的には)全てのサイトに対して一律DoNotTrack有効ってことになっちゃう。DoNotTrack自体がそもそもトラッキング拒否する人はだいたい全部拒否を望んでるだろ、って方向性で設計されるんじゃないかと思う(あんまり詳しく議論追ってないけど)。少なくともブラウザの実装上はそうなっているし、より細かく制御したかったら拡張機能で、みたいな感じになるんじゃないかな。

まあそもそも、トラッキングを行なっている会社が100社あったとして、100社のうちどれか一つでもユーザーにとって許容が出来無い事をやっていて、DoNotTrackに対応してますと言った場合、他の会社はとばっちりを受ける。運命共同体だ。自分はそれが(ユーザーの意志を反映させるシステムとして)正しい方向性なのかよく分かっていない。

近い将来に、DoNotTrackを有効にしている人が○○%、みたいな統計データが出て、トラッキングを望まない人が○○%います、みたいになると思うけど、それは実状を反映したデータには決してならない。無関心な人は無関心なままだし、大体許容してるけど一社でもマズイことをやってたら困るのでDoNotTrackを有効にせざるを得ない、という状況もあるだろうから。

まとめ

広告業界はとばっちりを受けないように同業他社を見はったほうがいい

トラックバック - http://subtech.g.hatena.ne.jp/mala/20120316

2012-03-05

Echofonに見るクライアント/サーバーの境界線と認証の問題

00:27 | Echofonに見るクライアント/サーバーの境界線と認証の問題 - 金利0無利息キャッシング – キャッシングできます を含むブックマーク はてなブックマーク - Echofonに見るクライアント/サーバーの境界線と認証の問題 - 金利0無利息キャッシング – キャッシングできます

どういう問題があったのか

あとで書く

修正案

  • サーバーサイドへの認可が必要であるならば、サーバーに対して認可を与えれば良い。
  • 秘密の情報を受け取らなければ本人確認として機能しない。
  • 通信内容の暗号化や、アプリケーションの難読化などは(攻撃が困難にはなるだろうが)根本的な対策ではない。

アプリ内から「Twitterアカウントの所有者であること」と「そのデバイスの持ち主であること」の両方を証明するには

  • アプリ内で乱数を生成してサーバーに送り、セッションid Aを受け取る
  • セッションid Aを付加してブラウザ(またはUIWebView)を開く。OAuthを使って認証する(Twitterアカウントの持ち主であると証明される)
  • この際にセッションid Bを取得する。セッションid Aに保存された乱数をセッションid Bに対しても保存しておく。
  • セッションid Bを付加してアプリケーションに戻り、最初に生成した乱数とセッションid Bで認証を行う。

ポイント

  • セッションid Bを攻撃者は知りえないので、セッション固定攻撃が出来ない。
  • セッションid BをURLスキーム上書きなどで違うアプリに渡してしまっても、単体では機能しない。
トラックバック - http://subtech.g.hatena.ne.jp/mala/20120305