Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
第 7回の目次
前回: セッションと脆弱性 (XSS, CSRF),TLS
今回:
ブラウザでのプログラミング (クロスオリジン)Same Origin PolicyJSONと JSONPCORSセキュアプログラミング(Google Analytics)
【参考書: 徳丸「安全なWebアプリケーションの作り方」】
1 / 24
本日のソースコード
iframe err.html: 別ドメインの iframeをアクセスすると
same origin.html: iframe err.htmlとセット
mashup.html: twitterと google検索のマッシュアップ (もう動かない)
json test.rb: rubyで JSONパーサーを使う
xhr2.html: XHR2の例
gbook.html
gmap.html
2 / 24
何から何を守りたいのか?
クライアント PCのデータや計算リソースActiveXや Pluginは危険 → 利用者による認証ブラウザの実装は信頼できるのか (よく考えると根拠なし)
サーバー上のデータや計算リソース単純なサーバー浸入セッションの乗っ取り (Webアプリに特徴的)通信の盗聴 → httpsブラウザ内の盗聴 → Same Origin Policy
詐欺,フィッシング (表示されているものは信用できるか?)
さまざまな攻撃手段
盗聴,なりすまし:Sniffing, Man-in-the-Middle (MITM), MITB, Replay
誘導:Spoofing (IP address, ARP, DNS), DNSへの種々の攻撃
サービス妨害: DDoS3 / 24
OWASP Top 10 - 2013
OWASP: Open Web Application Security Project
A1 インジェクション攻撃
A2 不適切 (broken)な認証とセッション管理
A3 クロスサイトスクリプティング (XSS)
A4 オブジェクトの安全でない直接参照例: ファイルを外部から見える所に置いてしまった
A5 セキュリティに関する誤設定
A6 機密データの露出 (exposure)
A8 機能レベルでのアクセス制御の不備利用者の認証だけでなく機能のレベルで制御をする
A8 クロスサイトリクエストフォージェリ (CSRF)
A9 脆弱性が既知なコンポーネントの利用
A10 未検証のリダイレクトとフォーワード
OWASP:Webシステム/Webアプリケーションセキュリティ要件書より
4 / 24
クライアントサイドマッシュアップ
いろんなサービスを混ぜたい (→実はある意味セキュリティ破り)imgだってある意味混ぜてるあるいは iframe
1
典型的なWebの提供形態
ブラウザ サーバー
サーバー
サーバー
サーバー
ブラウザ
1ページ1サイト
1ページ複数サイト
フレームでサイトを区分け
LAMP
L: LinuxA: ApacheM: MySQLP: PHP,Perl
HTMLhttp
例: facebookのいいねボタン<iframe src="http://www.facebook.com/plugins/like.php?href=~&layout=standard&show_faces=true&width=300&action=like
&colorscheme=light&height=80"
scrolling="no" frameborder="0" style="border:none; overflow:hidden;
width:300px; height:80px;" allowTransparency="true"></iframe>
もっともこれは普通は「混ぜた」とは言わない(X-Frame-Optionsで拒否されることもあるし)
複数のサービスをデータレベルで混ぜる→ same origin policyが壁5 / 24
Same Origin Policy
Same Origin Policyとは「Same Originからの操作だけを許す」こと
Same Originとは「2つのコンテンツのダウンロード元が同じ」こと「同じ」の判定:
同一ホスト (同一 FQDN.ドメインレベルにまで緩和可能)
同一スキーム (httpと httpsは違う)
同一ポート番号
6 / 24
異なるオリジンのデータを混在させうる要素
つまり通信をし得る要素ということ
IFRAME, FRAME, FORM・異なるサイトへもリクエストできる・その場合,その DOMを操作できなくなる
IMG・異なるサイトへもリクエストできる (Webビーコン)・画像データにはアクセスできない(幅と高さはいじれる)
SCRIPT,CSS・異なるサイトへもリクエストできる・結果は same originとみなされる (JSONPの理由)
XmlHttpRequest (要素ではないが)・異なるサイトへはリクエスト不可・XHR2なら可能 (後述)
7 / 24
例
別のドメインの iframeには触れない
<iframe id="if1" src=同じサイトの html>
</iframe>
<iframe id="if2" src=別サイトの html>
</iframe>
if1と if2の iframeは見かけは似ているが,JSにとってはまったく別物.
実験:iframe err.htmlと same origin.htmlを sicに置いてアクセス
8 / 24
なぜサイトが管理単位なのか?
あるサイトの中のコンテンツはすべて same originになる
その中に悪意があるものが置かれていたらアウト
なぜこんな仕様か? 例えば path まで見るとか
実際,例えば cookieは pathを見ている
pathのどの階層で分けるのかはサイト毎に違う
利用者が URLを見て確実に判断できるのはサイト
Same origin policyを少し緩める手段
document.domain
X-FRAME-OPTIONS
Cookieの場合は domain属性
xhrの場合は XHR2 (後述)
9 / 24
Cookieのセキュリティ
cookieにも same origin policyが適用される異なる originの JSからは cookieは参照できない
pathを付けても共有サイトでは危ない.別パスの iframeを作ると,そっちの document.cookieにクッキーデータが入る.JSは originしか見ないので,別パスの iframeのクッキーも参照可能.
cookieに secure属性を付けると httpsでのみ送られるようになる
httponly属性を付けると JSからのアクセスが禁止される
別の問題: サードパーティクッキー
first party cookiethird party cookie<img src="...">
ブラウザには,サードパーティを禁止する設定がある.(ツール→オプション→プライバシー→記憶させる履歴を詳細設定)
自分のブラウザの cookieを見てみる同上→ Cookieを表示 10 / 24
JSONPとクロスオリジン
JSONPとは第 3者サーバからデータを貰う方法の一つ最も基本的な JSONPの書き方:
<script src="http:...?jsonp=callback">
function callback(data){~}
</script>
(jsonp=のところは APIによって違う)
ポイント: script要素はオリジンに関係なく実行可能
11 / 24
JSONPを使ったクロスオリジン
APIを公開しているほとんどのサイトは JSONP対応
例:はてなハイクから人気ワードをもってきて yahooで検索する【→ mashup.html ただし静的な JSONP】
12 / 24
参考: iframeを使ったクロスオリジン (昔のテクニック)
2つの iframeを使う.別の frameの locationのハッシュにセットすることはできることは利用html ⇔ iframe A ⇔ iframe B ⇔ Web server
見えない iframe Aを一つ作る.その iframeの中で,もう一つ作る.
iframe Bの中身(プログラム)は web server上に用意されている.
iframe Bは,クロスドメインでなくなるので,Web serverと xhrでやりとりできるようになる.
iframe A → iframe B:iframe Bの location.hashを使う親は子供の locationを自由に書き換えられる(参照はできない)
iframe A ← iframe B:iframe Aの location.hashを使う子は親の locationを自由に書き換えられる(参照はできない)
Aも Bもポーリングで自分の hashを見る.(子を resizeして,resizeイベントを飛ばす方法もある.)
Aは全部のデータが揃ったら,親に返す.
13 / 24
CORS (Cross-Origin Resource Sharing)
既にほとんどのブラウザに入っている (W3C Recommendation)
Same origin policyの目的: ブラウザであるドメインのページを見ているときに,第 3のサイトに何らかの情報が洩れることを防ぐ.
CORSの目的: ある特定のオリジンのWebアプリにだけ情報を見せること.
それを強制するのはブラウザの仕事
XMLHttpRequest level 2, Server-sent eventなどで用いられる
【ソースは xhr2.htmlだが見てもあまり意味はない】
14 / 24
CORSの仕組み
www.3rdparty.comのサーバでの準備: .htaccessの設定Header set Access-Control-Allow-Origin "*"
(上は全ドメインからの xhr2の許可.普通は個別に指定する)
www.example.com/webapp.htmlの中で,http://www.3rdparty.com/data.jsonへの XHR2を実行
UA → www.3rdparty.comのサーバGET /data.json HTTP/1.1
Origin: www.example.com
www.3rdparty.comのサーバ → UA
Access-Control-Allow-Origin: *
ブラウザは上記ヘッダを見てレスポンスを exposeするか決定(expose を特定の意味で使っているので,W3C CORS を読む時注意)
XHR2の結果が見えるようになる
15 / 24
CORS preflight
クロスオリジンでの PUT/DELETEは,preflightしてから実行する
preflightを送る(OPTIONメソッドを使う)Access-Control-Request-Methodヘッダを付ける
OKが返ってきたらヘッダーをチェック:Access-Control-Allow-Methods ヘッダがあれば OK
本当の CORS PUT/DELETEを送る
理由:PUT/DELETEは元々Same Originしかありえなかったレガシーサーバーは CORS PUT/DELETEが来るなんて考えていないもし来たら,どんな動作をするか分からない実行できないと言ってくれれば良いが,実行したと言って実は実行してないとか
レガシーサーバーを改変せずに CORS対応・非対応を確実に知るため
16 / 24
CORSの credential
credentialとは,クッキーや HTTP認証 (一旦した後の話)
omit credentials flag: UA内の制御フラグ.立つのがデフォルト.立つと user credentialを付けず,レスポンスの cookieも無視APIは次のように書くと flagが落ち, credentialを送るxhr.withCredentials=true;
サーバーは credentialを確認した上で(しなくても良いが)Access-Control-Allow-Credentials: true
このヘッダを返す.これがないと JSには exposeされない.
(なお,preflightでは credentialは送られない)
17 / 24
google analyticsのトラック方法
次のスニペットを解析対象のページに貼る (サーバーが生成する)
<script>(function(i,s,o,g,r,a,m){ i[’GoogleAnalyticsObject’]=r; i[r] = i[r] || function(){(i[r].q=i[r].q||[]).push(arguments)}, i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0]; a.async=1; a.src=g; m.parentNode.insertBefore(a,m)})(window, document,’script’,’//www.google-analytics.com/analytics.js’,’ga’);
ga(’create’, ’UA-XXXX-Y’, ’auto’);ga(’send’, ’pageview’);</script>
動作は次のようになる
window[’GoogleAnalyticsObject’]=’ga’;
window[’ga’] = window[’ga’] || // 関数 ga の定義function(){ // これが関数本体
(window[’ga’].q=window[’ga’].q||[]).push(arguments)
},
window[’ga’].l=1*new Date();
a=s.createElement(’script’), m=s.getElementsByTagName(’script’)[0];
a.async=1;
a.src=’//www.google-analytics.com/analytics.js’;
m.parentNode.insertBefore(a,m) // 他の script より前に insert
ga(’create’, ’UA-XXXX-Y’, ’auto’);
ga(’send’, ’pageview’);
gaという関数オブジェクトの属性 qに値を pushしているだけ18 / 24
analytics.jaの中の実際に送る部分
関数 Ga の定義:Ga=function(a,b,c,d){ // a が URL,b が送る値
c=c||L;d&&(d=c,O[oa].sendBeacon?O[oa].sendBeacon(a,b)?(d(),d=!0):d=!1:d=!1);// sendBeacon という関数は,最近 W3C で標準化されたものif(!d) // sendBeacon がない時
if(2036>=b[y]) wc(a,b,c); // 2036 バイト以下の時 wc() を呼ぶelse if(8192>=b[y]){ // 2036~8192 の時はこっち
if(0<=O[oa].userAgent[t]("Firefox")&&![].reduce) throw new Ea(b[y]);wd(a,b,c)||xd(a,b,c)||Fa(b,c)||c()
} else throw new Da(b[y]); // ??},
関数 wc の定義:wc=function(a,b,c){ var d=Ca(a+"?"+b); ~ }
関数 Ca の定義:function Ca(a){
var b=M[u]("img"); // M=document, u="createElement".b.width=1; // img の大きさを 1x1 にするb.height=1;b.src=a;return b
}
後は簡単に (興味があれば自分で):・wd() は XHR で POST を送る.XHR が失敗した時は false.(たぶん Measurement Protocol)・xd() は IE 用で,XDomainRequest で送る.IE でない時は false.・Fa() は大きさ 0x0 で見えない iframe を作り,そいつに GET させている.
19 / 24
google analytics (ga) の扱う ID
次の関数で紐付けるga("create", トラッキング ID, {"userID": ユーザ ID });
トラッキング ID: "UA-アカウント ID-プロパティ番号"
アカウント ID: gaの利用者 (=分析者) ごとの ID
プロパティ番号: gaサイトでプロパティを作ると割当てられる数字
ユーザ ID: サーバーが認証した利用者の IDサーバーが上記スニペットに埋める.クッキーには保存されない.
クライアント ID: ブラウザを識別するための ID(実際は乱数)サーバーの first party cookieとして保存(cookie名は"_ga")クッキー_gaがない時に analytics.jsが生成する
20 / 24
何を追跡できるか?
次のようにして情報を送るga(’send’, ’pageview’);
第 2引数には次のようなものが渡せるpageview: pageが見られたevent: button を 何回 click した等social: Facebookのいいね,Twitterのツイートの回数timing: 要した時間を送る (重いライブラリロードなど)
analytics.jsが自動収集してくれるわけではない.プログラムを書くのは自分であって,ga()は情報を送るだけ.解析方法に上の 4つの分類があるということ.
解析例:http://www.google.com/intl/ja_ALL/analytics/index.html
21 / 24
Defensive Programming, Secure Coding
Top 10 Secure Coding Practices (CERT)
Validate input
Heed compiler warnings (Heed = 注意する)
Architect and design for security policies (policyに従って作れ)
Keep it simple
Default deny
Adhere to the principle of least privilege (最低の権限で)
Sanitize data sent to other systems
Practice defense in depth (多層防御)
Use effective quality assurance techniques (品質保証技術)
Adopt a secure coding standard
22 / 24
最近の話題: DNTヘッダ
Don’t Track Meヘッダ.
DNT: 1
ブラウザが httpヘッダに入れて送る(送るかどうかはユーザがオプションで決める)まだ RFCにはなってないサーバーがどう動作するかも明確には決まっていない一部ブラウザでは実装済み
23 / 24
ブラウザのこれから
コンテンツ提供者もプラットフォーム屋もブラウザは嫌
なぜ?
ブラウザは重い → 一部本当
セキュリティが不十分 → 多くはサーバ側が原因
GUIの能力不足 → Canvas, WebGLがある
ブラウザはオープン過ぎる → これは本音
どうやって?
ネイティブ: いわゆる「アプリ」今はこれが全盛
共通化: packaged web apps, node-webkit, Apache cordova
逆?の方向 (全部 HTMLの中でやる)
Chrome OS, Firefox OS
Node.js (サーバーも JS)
24 / 24