7.2K Views
April 21, 12
スライド概要
PHPカンファレンス北海道にて
2012/04/21
PHPカンファレンス北海道 徳丸本に載っていない Webアプリケーションセキュリティ 2012年4月21日 徳丸 浩
本日お話しする内容 • キャッシュからの情報漏洩に注意 • クリックジャッキング入門 • Ajaxセキュリティ入門 • ドリランド カード増殖祭りはこうしておこった…かも? Copyright © 2012 HASH Consulting Corp. 2
徳丸浩の自己紹介 • 経歴 – 1985年 京セラ株式会社入社 – 1995年 京セラコミュニケーションシステム株式会社(KCCS)に出向・転籍 – 2008年 KCCS退職、HASHコンサルティング株式会社設立 • 経験したこと – 京セラ入社当時はCAD、計算幾何学、数値シミュレーションなどを担当 – その後、企業向けパッケージソフトの企画・開発・事業化を担当 – 1999年から、携帯電話向けインフラ、プラットフォームの企画・開発を担当 Webアプリケーションのセキュリティ問題に直面、研究、社内展開、寄稿などを開始 – 2004年にKCCS社内ベンチャーとしてWebアプリケーションセキュリティ事業を立ち上げ • その他 – 1990年にPascalコンパイラをCabezonを開発、オープンソースで公開 「大学時代のPascal演習がCabezonでした」という方にお目にかかることも • 現在 – HASHコンサルティング株式会社 代表 – 京セラコミュニケーションシステム株式会社 技術顧問 http://www.hash-c.co.jp/ http://www.kccs.co.jp/security/ – 独立行政法人情報処理推進機構 非常勤研究員 http://www.ipa.go.jp/security/ Copyright © 2012 HASH Consulting Corp. 3
本を書きました 2011年3月5日初版第1刷 2011年12月13日 初版第5刷 Copyright © 2012 HASH Consulting Corp. 4
キャッシュからの情報漏洩に注意 Copyright © 2012 HASH Consulting Corp. 5
Webアプリケーションとキャッシュ • フレームワークのキャッシュ機能 • リバースプロキシ • フォワードプロキシ • ブラウザのキャッシュ機能 • キャッシュは、Webアプリケーションの負荷を軽減し、応答を 高速化するために用いられる • サイト運営側が設置するキャッシュと、閲覧側(ISP等を含 む)が設置するものがある Copyright © 2012 HASH Consulting Corp. 6
キャッシュからの情報漏洩とは? • いわゆる「別人問題」 • 秘密情報がキャッシュされて、それを別人が見る状況 – 最初のアクセスは正当な権限あり →表示内容がキャッシュされるに – 次のアクセスは権限のないユーザ →同一URLを参照すると、キャッシュされた情報を閲覧してしまう • 続きはデモで Copyright © 2012 HASH Consulting Corp. 7
Demoの構成 ブラウザ PROXY squid refresh_pattern ^ftp: 1440 20% 10080 refresh_pattern ^gopher: 1440 0% 1440 refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 refresh_pattern (Release|Package(.gz)*)$ 0 20% refresh_pattern . 1440 20% 4320 override-lastmod OpenPNE 3.4.12.1 PHP/MySQL Ubuntu 10.04LTS 2880 ※デモ環境では、WebサーバーとProxyサーバーは同一VM上で稼働 Copyright © 2012 HASH Consulting Corp. 8
サトーさん タナカさん Demo Copyright © 2012 HASH Consulting Corp. 9
ブラウザキャッシュのデモ デフォルト Copyright © 2012 HASH Consulting Corp. 10
そもそもこれは脆弱性なのか? • PROXY設定の問題ではないのか? – PROXY設定の問題とは言い切れない – squidの標準的な機能の範囲である – PROXY設定の基準が明確にあるわけではない • RFC2616 13.4 Response Cacheability – (原文)A response received with a status code of 200, 203, 206, 300, 301 or 410 MAY be stored by a cache and used in reply to a subsequent request, subject to the expiration mechanism, unless a cache-control directive prohibits caching. – (日本語訳)200, 203, 206, 300, 301, 410 のステータスコードと共 に受信されたレスポンスは、cache-control 指示子がキャッシングを 禁止していなければ、キャッシュによって保存され、以降のリクエス トへの応答に使用され、期限メカニズムに従う事ができる。 http://tools.ietf.org/html/rfc2616#section-13.4 http://www.studyinghttp.net/cgi-bin/rfc.cgi?2616#Sec13.1.3 より引用 Copyright © 2012 HASH Consulting Corp. 11
ブラウザのキャッシュはどうか • ブラウザのキャッシュも同様だが • そもそも、ブラウザを共有することが問題 • Windows95,98,MEの時代ならともかく、2012年の時点では、 端末は共有しても、ユーザは別にすべし。そうすれば問題は 発生しない • つまり、「はてなブックマークでのデモ事例」は許容可能 • とはいえ、Webサイト提供者としては対策することが望ましい Copyright © 2012 HASH Consulting Corp. 12
対策 • HTTPレスポンスヘッダで「キャッシュを禁止するヘッダ」を応答すること が根本対策 • セキュアプログラミング講座には… 1. Cache-Control: private Webサーバから返されるコンテンツがただ一人のユーザのためのものであることを示す。 このコンテンツは、複数のユーザが共有されるキャッシュに記録されるべきではないこと を表している。ただし、これは、一人のユーザのみが利用するキャッシュ(ブラウザのキャ ッシュ等)への記録を禁じるものではない。Cache-Control: private のみが指定されてい る場合、何らかのキャッシュへの記録が行われるおそれがある。 2. Cache-Control: no-store このヘッダは、Webサーバから返されてくるコンテンツをキャッシュに記録するな、という 指示である。 3. Cache-Control: no-cache 一見「キャッシュを使うな」のように見えるこのヘッダが実際に意味するところは少々ニュ アンスが異なる。このヘッダの意味は、いちどキャッシュに記録されたコンテンツは、現在 でも有効か否かを本来のWebサーバに問い合わせて確認がとれない限り再利用しては ならない、という意味である。 4. Cache-Control: must-revalidate このヘッダは、キャッシュに記録されているコンテンツが現在も有効であるか否かをWeb サーバに必ず問い合わせよ、という指示である。 http://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/405.html より引用 13
対策(続き) • HTTP/1.0対策として – Pragma: no-cache – 非標準の方法であり、確実なものではない • その他の手法 – 「現場の知恵」としてURL(クエリ文字列)にランダムな数字を付加す ることが行われる • 例: http://example.jp/private.php?rand=8314329428479210 – HTTPSにする • 通常のPROXYはHTTPSのメッセージをキャッシュしない(できない) • リバースPROXY、ブラウザはキャッシュする可能性があるので過信しないこと – テストする • 別ユーザ or 非ログイン状態で、同じURLをアクセスする Copyright © 2012 HASH Consulting Corp. 14
乱数をURLにつける例 Copyright © 2012 HASH Consulting Corp. 15
クリックジャッキング入門 Copyright © 2012 HASH Consulting Corp. 16
クリックジャッキング攻撃 • ターゲットの画面をiframe上で「透明に」表示する • その下にダミーの画面を表示させる。ユーザにはダミーの画 面が透けて見える • 利用者がダミーの画面上のボタンを押すと、実際には全面の ターゲット画面のボタンが押される 本当の画面(前面、透明) ダミーの画面(後面) • 続きはデモで Copyright © 2012 HASH Consulting Corp. 17
クリックジャッキングの対策 • クリックジャッキングの影響はクロスサイト・リクエストフォージ ェリ(CSRF)と同等 – ユーザの意識とは無関係に、ユーザの権限で操作が行われる • クリックジャッキングされると困るページには、X-FRAMEOPTIONSヘッダを指定する(徳丸本P63) – frame/iframeを禁止して良い場合 header('X-FRAME-OPTIONS', 'DENY'); – frame/iframeを禁止できないが単一ホストの場合 header('X-FRAME-OPTIONS', 'SAMEORIGIN'); • CSRF対策のトークン発行しているページが対象となる • メタ要素によるX-FRAME-OPTIONS指定は無効です。 徳丸本第3刷までの記述は間違いです(_ _) Copyright © 2012 HASH Consulting Corp. 18
CSRF対策との関係 入力/確認画面 更新・実行画面 更新してよろしいですか? 更新しました トップへ 実行 •トークン埋め込み •X-FRAME-OPTIONS ヘッダ出力 •トークン確認 トークン埋め込みしている画面に、X-FRAME-OPTIONS ヘッダを出力する(全ての画面で出力しても良い) Copyright © 2012 HASH Consulting Corp. 19
Ajaxセキュリティ入門 Copyright © 2012 HASH Consulting Corp. 20
Ajaxはあたりまえになったけど、Ajaxの セキュリティは当たり前になってない Copyright © 2012 HASH Consulting Corp. 21
たとえば入門書の問題 Copyright © 2012 HASH Consulting Corp. 22
とある入門書のサンプル Copyright © 2012 HASH Consulting Corp. よくわかるJavaScriptの教科書、たにぐちまこと著、2012 P228より引用 23
この本です 24
動かしてみる Copyright © 2012 HASH Consulting Corp. 25
結果 Copyright © 2012 HASH Consulting Corp. 26
JSON作成をPHPに 生成されるJSON [{"image":"img\/1.jpg","image_big":"i mg\/1_big.jpg","caption":"\u30ad\u30e 3\u30d7\u30b7\u30e7\u30f31"}] Copyright © 2012 HASH Consulting Corp. 27
結果 Copyright © 2012 HASH Consulting Corp. 28
データにJavaScriptを入れてみる
生成されるJSON
[{"image":"img\/1.jpg","image_big":"i
mg\/1_big.jpg","caption":"\u30ad\u30e
3\u30d7\u30b7\u30e7\u30f31<script>ale
rt(1)<\/script>"}]
Copyright © 2012 HASH Consulting Corp.
29
結果 Copyright © 2012 HASH Consulting Corp. 30
脆弱性の原因と対策 • htmlメソッドによりHTMLテキストを設定しているにも関わら ず、データをHTMLエスケープしていない • ただし、元文献は固定テキストなので、必ずしも脆弱性とは 言えない • HTMLエスケープするタイミングは、以下の候補がある – ブラウザでレンダリングする箇所 – JSONを組み立てる段階で、あらかじめHTMLエスケープしておく Copyright © 2012 HASH Consulting Corp. 31
次の話題 evalインジェクション Copyright © 2012 HASH Consulting Corp. 32
JSON解釈をevalでやってみる Copyright © 2012 HASH Consulting Corp. 33
JSON作成も自前で
<?php
$image = 'img/1.jpg';
$image_big = 'img/1_big.jpg';
$caption = 'キャプション2';
$a = '[{"image":"' . $image . '","image_big":"' .
$image_big . '","caption":"' . $caption . '"}]';
echo $a;
生成されるJSON
[{"image":"img/1.jpg","image_big":"img/1_b
ig.jpg","caption":"キャプション2 "}]
Copyright © 2012 HASH Consulting Corp.
34
結果 Copyright © 2012 HASH Consulting Corp. 35
データにJavaScriptを入れてみる
<?php
$image = 'img/1.jpg';
$image_big = 'img/1_big.jpg';
$caption = 'キャプション2x"+alert("1")+"';
$a = '[{"image":"' . $image . '","image_big":"' .
$image_big . '","caption":"' . $caption . '"}]';
echo $a;
生成されるJSON
[{"image":"img/1.jpg","image_big":
"img/1_big.jpg","caption":
"キャプション2x"+alert("1")+""}]
Copyright © 2012 HASH Consulting Corp.
36
結果 Copyright © 2012 HASH Consulting Corp. 37
脆弱性の原因と対策 • JSON/JavaScriptとしての適切なエスケープを怠っているこ とが根本原因 • 根本単位策:JSON生成を自前でしないで、信頼できるライブ ラリを用いる • 保険的対策(強く推奨):evalでJSONを解釈しない。 Copyright © 2012 HASH Consulting Corp. 38
次の話題 json.phpを直接ブラウズしてみる Copyright © 2012 HASH Consulting Corp. 39
データを少しいじりましょう Copyright © 2012 HASH Consulting Corp. 40
さまざまなブラウザでの結果 Copyright © 2012 HASH Consulting Corp. 41
で、IE9は? Copyright © 2012 HASH Consulting Corp. 42
大丈夫なのか Copyright © 2012 HASH Consulting Corp. 43
でも、だめ http://example.jp/json.php/a.html Copyright © 2012 HASH Consulting Corp. 44
Copyright © 2012 HASH Consulting Corp. http://d.hatena.ne.jp/hasegawayosuke/20110106/p1 より引用 45
Copyright © 2012 HASH Consulting Corp. http://d.hatena.ne.jp/hasegawayosuke/20110106/p1 より引用 46
X-Content-Type-Options: nosniff を入れてみる
生成されるJSON
X-Content-Type-Options: nosniff
Content-Length: 125
Content-Type: application/json; charset=utf8
[{"image":"img\/1.jpg","image_big":"img\/1_b
ig.jpg","caption":"\u30ad\u30e3\u30d7\u30b7\
u30e7\u30f31<body onload=alert(1)>"}]
Copyright © 2012 HASH Consulting Corp.
47
IE9だとOK(IE8以上) Copyright © 2012 HASH Consulting Corp. 48
IE7だとだめ Copyright © 2012 HASH Consulting Corp. 49
50
対策
• 必須対策(全ブラウザ共通)
– レスポンスがブラウザによりtext/htmlと解釈されないようにする
X-Content-Type-Options: nosniff
Content-Type: application/json; charset=utf8
• IE6,7対策
– IE7以前をサポートしない
– ブラウザからの直接リクエストを受け付けない
– 「<」、「>」などもエスケープする
Copyright © 2012 HASH Consulting Corp.
51
Json_encodeのパラメータを追加 生成されるJSON [{"image":"img\/1.jpg","image_big":"img\/1_bi g.jpg","caption":"\u30ad\u30e3\u30d7\u30b7\u3 0e7\u30f31\u003Cbody onload=alert(1)\u003E"}] Copyright © 2012 HASH Consulting Corp. 52
今度は大丈夫 Copyright © 2012 HASH Consulting Corp. 53
次の話題はJSONハイジャック Copyright © 2012 HASH Consulting Corp. 54
Firefox3などで発現。現在の主要ブラ ウザでは対策されている Copyright © 2012 HASH Consulting Corp. 55
JSONハイジャックとは
• JSONを罠サイトからscript要素で読み出す
• 利用者のブラウザからは、正規のCookieが送信されるので、
認証ずみの状態でJSONが取得できる
• なんらかの手法で、このJSONの中味を読むのがJSONハイ
ジャック
これは罠サイト
<script>
ここにJSONを読み出す仕掛けを置く
// script要素で読み出したJSON
[{"name":"Yamada", "mail":"[email protected]"}]
</script>
Copyright © 2012 HASH Consulting Corp.
56
サンプルスクリプト(罠) Copyright © 2012 HASH Consulting Corp. 57
結果 Copyright © 2012 HASH Consulting Corp. 58
Firefox11.0だと問題なし Copyright © 2012 HASH Consulting Corp. 59
Androidの標準ブラウザでハイジャック成功 Xperia ARC(SO-01C) Android 2.3.4 でキャプチャ Galaxy Nexus Android 4.0.3では取得できず Copyright © 2012 HASH Consulting Corp. 60
対策 • script要素からのリクエストにはレスポンスを返さないように する – XMLHttpRequestからのリクエストに特別なヘッダを入れておき、 JSON提供側でチェックするなど Jqueryの以下のヘッダを使っても良いかも X-Requested-With: XMLHttpRequest – POSTにのみ応答(個人的には好みません) • JSONデータを、JavaScriptとして実行できない形にする – 1行目に for(;;) ; を置く(個人的には好みません) – JSONデータをJavaScriptとして実行できない形にする(同上) • JSONハイジャック可能なブラウザを使わない(利用者側でと れる対策) Copyright © 2012 HASH Consulting Corp. 61
まとめ • HTML5の話題が盛り上がる中、HTML4のAjaxのセキュリテ ィが当たり前になっていない • 分かっている人と分かってない人の二極化が進んでいる? • どうすればよいか、よく考えよう • CSRF等もふつーに発生するので、ふつーに対策すること Copyright © 2012 HASH Consulting Corp. 62
ドリランド カード増殖祭りはこうしておこ った…かも? Copyright © 2012 HASH Consulting Corp. 63
https://help.gree.jp/app/answers/detail/a_id/3231 より引用 64
こんな感じだった? 必要なもの 携帯もしくはPCを二台 gleeアカウント二つ 二台の機器でそれぞれのgleeアカウントでログインしてドリランド起 動後お互いでトレードさせる トレード(受け取りはしない)が終わったら片方の機器はログアウトし て二つの機器のアカウントを同じにする それぞれトレード品受け取り画面にして受け取るボタン同時押し カード毎にID振って無いのかよ。。。。 馬鹿じゃねぇの? >>277 ちゃんとふってあるけど、トレード時にトレードされる側とする側で ちゃんとアイテムIDが変わる仕様だったw http://jin115.com/archives/51849925.html より引用 65
こんな感じだった? ⚫DBからトレード元のカードのデータを読み取る ⚫新しいIDをつけてトレード先に保存する ⚫トレード元のデータを削除する http://bakera.jp/ebi/topic/4722 より引用 66
作ってみた
// トレードするカードのidと新オーナーのidがパラメータ
$item_id = (int)$_GET['item_id'];
$newowner = (int)$_GET['newowner'];
// カード情報を取得
$stmt = $pdo->query(
"SELECT * FROM cards WHERE item_id=$item_id");
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$kind = $row['kind'];
$owner_id = $row['owner_id'];
// トレード後のカードを作成
$stmt = $pdo->exec("INSERT INTO cards VALUES (NULL, $kind,".
"$newowner, $item_id, $owner_id, NOW())");
// 元のカードを削除
$stmt = $pdo->exec(
"DELETE FROM cards WHERE item_id= $item_id ");
※デモスクリプトはプレースホルダをちゃんと使っています!
Copyright © 2012 HASH Consulting Corp.
67
DEMO Copyright © 2012 HASH Consulting Corp. 68
中ではこうなった Copyright © 2012 HASH Consulting Corp. 69
対策 • トランザクションを使う – PDOの場合は、begeinTransaction ~ commit / rollbackの間 • ロック(排他制御) – SELECT … FOR UPDATE など • 上記の両方が必須 – トランザクションを使うだけでは排他制御にならない場合が多い 厳密にはDB依存 および モードに依存 • 「クリティカルセクション」に注意 – このスクリプトの場合は、SELECT ~ DELETE FROMまではクリテ ィカルセクションであり、同一カードIDについては並行動作してはい けない • ちゃんとRDBを基礎から勉強しよう Copyright © 2012 HASH Consulting Corp. 70
トランザクションと行ロックで対策
try {
$pdo->beginTransaction();
$item_id = (int)$_GET['item_id'];
$stmt = $pdo->query(
"SELECT * FROM cards WHERE item_id=$item_id FOR UPDATE");
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (! $row) throw new DataNotFoundException();
$kind = $row['kind'];
$owner_id = $row['owner_id'];
$stmt = $pdo->exec("INSERT INTO cards VALUES (NULL, $kind,".
"$newowner, $item_id, $owner_id, NOW())");
$stmt = $pdo->exec(
"DELETE FROM cards WHERE item_id=$item_id");
$pdo->commit();
} catch (DataNotFoundException $e) {
$pdo->rollback();
} catch (Exception $e) {
// ……
※上記は概要でありデモスクリプトはプレースホルダをちゃんと使っています!
Copyright © 2012 HASH Consulting Corp.
71
中ではこうなる Copyright © 2012 HASH Consulting Corp. 72
トランザクションを難しくする要因 • NoSQL • Memcached • データベースのパーティショニング、シャーディング • データベースのレプリケーション • LDAP、ファイル等トランザクション非対応のストレージ • … • 完全なロールバックが難しい場合でも、排他制御だけなら比 較的容易に実装できる場合がある Copyright © 2012 HASH Consulting Corp. 73
まとめ • 徳丸本に載っていない脆弱性をいくつか紹介しました • 「徳丸本に載っていることだけやっていればおk」ではない • プログラミングの基礎(並行処理、トランザクション、etc)を勉強しよう • そうは言っても、まずは「徳丸本」のマスターから始めよう(宣伝) Copyright © 2012 HASH Consulting Corp. 74
Thank you! Copyright © 2012 HASH Consulting Corp. 75