徳丸本に学ぶ 安全なPHPアプリ開発の鉄則2011

13,050 views

Published on

Published in: Technology
0 Comments
11 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
13,050
On SlideShare
0
From Embeds
0
Number of Embeds
4,310
Actions
Shares
0
Downloads
1
Comments
0
Likes
11
Embeds 0
No embeds

No notes for slide

徳丸本に学ぶ 安全なPHPアプリ開発の鉄則2011

  1. 1. 徳丸本に学ぶ 安全なPHPアプリ開発の鉄則2011 2011年9月10日 HASHコンサルティング株式会社 徳丸 浩 twitter id: ockeghem
  2. 2. 本日お話しする内容• 鉄則10• 鉄則9• 鉄則8• 鉄則7• 鉄則6• 鉄則5• 鉄則4• 鉄則3• 鉄則2• 鉄則1 Copyright © 2011 HASH Consulting Corp. 2
  3. 3. 徳丸浩の自己紹介• 経歴 – 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 © 2011 HASH Consulting Corp. 3
  4. 4. 本を書きました 2011年3月5日初版第1刷 2011年7月28日 初版第4刷 4
  5. 5. 史上最強のレビュアー軍団大崎雅幸 太田良典 かいと(kaito834)加藤泰文 小邨孝明 坂井隆二 下岡葉子髙木正弘 竹迫良範 東内裕二 塙与志夫日野洋一郎 山崎圭吾 山下太郎Masahiro Yamada(masa141421356)山本陽平 Copyright © 2011 HASH Consulting Corp. 5
  6. 6. 鉄則10安全なPHP入門書で学習する Copyright © 2011 HASH Consulting Corp. 6
  7. 7. 安全なPHP入門書って? Copyright © 2011 HASH Consulting Corp. 7
  8. 8. そこそこでも安全なPHP入門書には 出会ったことがない (;´Д`) Copyright © 2011 HASH Consulting Corp. 8
  9. 9. せめてXSSとSQLインジェクションくらい は最初から正しく教えて欲しい(_ _) この2つは対策箇所が多いので後から直すも大変ですし Copyright © 2011 HASH Consulting Corp. 9
  10. 10. 一見対策している*つもり*の例 しかし、このプログラムではIDさえ指定すれば、誰でもどの投稿でも削除でき てしまいます。そこで、様々なチェックを行ってから削除しています。if (isset($_SESSION[id])) { $id = $_REQUEST[id]; // 投稿を検査する $sql = sprintf(SELECT * FROM posts WHERE id=%d, mysql_real_escape_string($id)); $record = mysql_query($sql) or die(mysql_error()); $table = mysql_fetch_assoc($record); if ($table[member_id] == $_SESSION[id]) { // 削除 mysql_query(DELETE FROM posts WHERE id= . mysql_real_escape_string($id)) or die(mysql_error()); }} よくわかるPHPの教科書、たにぐちまこと著、毎日コミュニケーションズ、2010より引用 10
  11. 11. 一見対策している*つもり*の例 しかし、このプログラムではIDさえ指定すれば、誰でもどの投稿でも削除でき てしまいます。そこで、様々なチェックを行ってから削除しています。if (isset($_SESSION[id])) { $id = $_REQUEST[id]; id=13 OR TRUE を指定 // 投稿を検査する 投稿のオーナーであることのチェック $sql = sprintf(SELECT * FROM posts WHERE id=%d, mysql_real_escape_string($id)); SELECT * FROM posts WHERE id=13 $record = mysql_query($sql) or die(mysql_error()); $table = mysql_fetch_assoc($record); if ($table[member_id] == $_SESSION[id]) { // 削除 このユーザの投稿であることを確認 mysql_query(DELETE FROM posts WHERE id= . mysql_real_escape_string($id)) or die(mysql_error()); DELETE FROM posts WHERE id=13 OR TRUE }} 全ての投稿を削除 よくわかるPHPの教科書、たにぐちまこと著、毎日コミュニケーションズ、2010より引用 11
  12. 12. 鉄則9入力-処理-出力で適切な処理を行うこと Copyright © 2011 HASH Consulting Corp. 12
  13. 13. Webアプリケーションの機能と脆弱性の対応徳丸本P68から引用 Copyright © 2011 HASH Consulting Corp. 13
  14. 14. 入力処理では何をするか• 文字エンコーディングの妥当性検証• 文字エンコーディングの変換• 入力値検証(バリデーション) – バリデーションはアプリケーションの正常な動作を担保するためで、 脆弱性対策ではない – 入力値の文字種と文字数のチェック – 必須項目が入力されているか• セキュリティの観点からは以下に注意 – 制御文字のチェック(ヌルバイト、改行、その他の制御文字) – いわゆるブラックリスト検査をするのではなく、正常系の文字種を定 義しよう(いわゆるホワイトリスト検査) • よくヌルバイトや改行を弾くサンプルを見かけるが、他の制御文字は許すこと になってしまう• 詳しくは、徳丸本4.2節で Copyright © 2011 HASH Consulting Corp. 14
  15. 15. 鉄則8安全なSQLライブラリを選定して正しく使う Copyright © 2011 HASH Consulting Corp. 15
  16. 16. 安全なSQLライブラリの基準は• 以下がポイント – 静的プレースホルダが使えること – 文字エンコーディング指定ができる – 文字エンコーディングが正しく反映される(5C問題など) – バックスラッシュのエスケープにDBの設定が反映される • MySQL: NO_BACKSLASH_ESCAPES バックスペースをエスケープしない • PostgreSQL: standard_conforming_strings• メンテナンスが継続されていること• 「安全なSQLの呼び出し方」に詳しく説明• 同書では、MDB2を推奨している• PHP5.3.8以降では、ようやくPDOも使えるレベルになった Copyright © 2011 HASH Consulting Corp. 16
  17. 17. 参考http://blog.tokumaru.org/2011/08/pdo.html 17
  18. 18. 18http://d.hatena.ne.jp/ajiyoshi/20100409/1270809525 より引用
  19. 19. 鉄則7XSS対策の第一歩はhtmlspecialcharsを正しく使うことから Copyright © 2011 HASH Consulting Corp. 19
  20. 20. みなさん、htmlspecialcharsを 正しく使っていますか? Copyright © 2011 HASH Consulting Corp. 20
  21. 21. htmlspecialcharの正しい使い方• 第2引数はENT_QUOTESでなくても本当はよい – ENT_QUOTESを使わないと脆弱性という人までいる(;´Д`) – 要素内容は、どれを指定してもOK – ダブルクオートで囲った属性値は、ENT_COMPATか ENT_QUOTES – シングルクォートで囲った属性値はENT_QUOTES – 属性値はダブルクォートで囲むことにすれば、ENT_COMPATで 統一してもOK – 参考:徳丸本P102• 第3引数は文字エンコーディングを正しく指定すること – 指定する文字エンコーディングはmbstring.internal_encoding – 省略時はISO-8859-1 (Latin-1) / 5.4 からはUTF-8• htmlentitiesの方が安全という説は間違い(根拠がない) Copyright © 2011 HASH Consulting Corp. 21
  22. 22. XSS対策の基礎の基礎• HTTPレスポンスヘッダに文字エンコーディングを指定する – header(Content-Type: text/html; charset=UTF-8);• 要素内容は前述のhtmlspecialcharsの使い方• 属性値はhtmlspecialcharsでエスケープした値をダブル クォートで囲む• src属性などにURLを動的生成する場合は、スキームに注意 – http:// か https:// か / で始まることを確認• JavaScriptのリテラルを動的生成することはとても危険 – イベントハンドラの場合は、JSエスケープした値をHTMLエスケープ – script要素内はとてもめんどくさいので、やらない方が賢明 – どうしてもやりたいなら、「過剰エスケープ」(徳丸本P113) – hiddenパラメータに書いてDOMで読むのが無難(徳丸本P114) Copyright © 2011 HASH Consulting Corp. 22
  23. 23. 鉄則6ファイルアップロードは罠がいっぱい Copyright © 2011 HASH Consulting Corp. 23
  24. 24. ファイルアップロードの危険性• アップロードしたファイルをPHPスクリプトとして実行される – PHPに限らず、JSP、ASPなどのスクリプトとして解釈される可能性 – CGIは実行権限が必要なので、通常は成立しない • 書き込みの際に権限を過剰に設定していると成立する可能性も• アップロードしたファイルをHTMLと誤認させるXSS – 不適切なContent-Type設定が主要因 – IEに注意。画像のマジックバイトのチェックは必須 • getimagesizeが便利 (徳丸本P278) • IE8以上は X-Content-Type-Options: nosniff が有効 (徳丸本には間に合わず)• 詳しくは徳丸本4.12 P258~ Copyright © 2011 HASH Consulting Corp. 24
  25. 25. PHP逆引きレシピのアップロードサンプル if (strlen($_FILES[uploadfile][name][$i]) > 0) { # 画像ファイルの拡張子を取得して判定します。 $imgType = $_FILES[uploadfile][type][$i]; $extension = ; if ($imgType == image/gif) { $extension = gif; } else if ($imgType == image/png || $imgType == image/x-png) { $extension = png; } else if ($imgType == image/jpeg || $imgType == image/pjpeg) { $extension = jpg; } else if ($extension == ) { $error .= 許可されていない拡張子です<br />; } # getimagesize()関数で画像かどうかの判定をします。 $checkImage = @getimagesize($_FILES[uploadfile][tmp_name][$i]); if ($checkImage == FALSE) { $error .= 画像ファイルをアップロードしてください<br />; } else if ($imgType != $checkImage[mime]) { $error .= 拡張子が異なります<br />; } else if ($_FILES[uploadfile][size][$i] > 102400) { # 画像ファイルのサイズ上限をチェックします。 $error .= ファイルサイズが大きすぎます。100KB以下にしてください<br />;かなり良い } else if ($_FILES[uploadfile][size][$i] == 0) { # 画像ファイルのサイズ下限をチェックします。のだが惜し $error .= ファイルが存在しないか空のファイルです<br />; } else if ($extension != gif && $extension != jpg && $extension != png) {いところも # 画像ファイルの拡張子をチェックします。 $error .= アップロード可能なファイルはgif、jpgまたはpngのみです<br />; } else { # ここでは格納ディレクトリの下に「"upfile_" + 現在のタイムスタンプ + 連番 + 拡張 子」で配置します。 $moveTo = $filePath . /upfile_ . time() . $i . . . $extension; 25
  26. 26. PHP逆引きレシピ・サンプルの残念なところ• チェックが厳しすぎて、IE8以前で、PNG画像のアップロード がエラーになる – IE8まで、ブラウザが送信するMIMEはimage/x-png – MIMEのチェック部分では考慮している – getimagesizeが返すMIMEはimage/pngなのでエラーになる(;´Д`)• ファイル名の生成に現在時刻(秒単位)を使っているので ファイル名の衝突の可能性 – 同一時刻であれば、「遅いもの勝ち」となる – 状況によっては脆弱性となる • 画像管理ソフトで、Aさんは「恥ずかしい画像」を非公開ファイルとして投稿、 Bさんは、画像を公開ファイルとして投稿 • たまたま同一時刻なのでファイル名が同一となる • Bさんの公開画像として、Aさんの「恥ずかしい画像」が公開 • Aさん、Bさんともに、恥ずかしいことに(;´Д`) Copyright © 2011 HASH Consulting Corp. 26
  27. 27. PHP逆引きレシピ・サンプルの残念なところ• チェックが厳しすぎて、IE8以前で、PNG画像のアップロード がエラーになる – IE8まで、ブラウザが送信するMIMEはimage/x-png でも、全体としては、 – MIMEのチェック部分では考慮している 逆引きレシピはかなりいいよ – getimagesizeが返すMIMEはimage/pngなのでエラーになる(;´Д`)• ファイル名の生成に現在時刻(秒単位)を使っているので ファイル名の衝突の可能性 – 同一時刻であれば、「遅いもの勝ち」となる – 状況によっては脆弱性となる • 画像管理ソフトで、Aさんは「恥ずかしい画像」を非公開ファイルとして投稿、 Bさんは、画像を公開ファイルとして投稿 ユニークなファイル名生成 • たまたま同一時刻なのでファイル名が同一となる の例は、徳丸本P266参照 • Bさんの公開画像として、Aさんの「恥ずかしい画像」が公開 • Aさん、Bさんともに、恥ずかしいことに(;´Д`) Copyright © 2011 HASH Consulting Corp. 27
  28. 28. 鉄則5今時文字コードのセキュリティ気にしなくていいのは小学生までだよね Copyright © 2011 HASH Consulting Corp. 28
  29. 29. 文字コードのセキュリティまとめ• 文字コードの基本的なところを勉強しよう(徳丸本6章) – 文字集合:ASCII、ISO-8859-1、JIS X 0208、…Unicode – 文字符号化形式:Shift_JIS、EUC-JP、UTF-8、UTF-16• 文字コードを正しく扱う基本 – 入力:文字エンコーディングの妥当性チェック – 処理:処理中に文字集合を変更しない マルチバイト対応の関数を使う(mbstring系) – 出力:文字コードの指定を正しく行う • HTTPレスポンスヘッダの文字エンコーディング指定 • SQL接続時の文字エンコーディング指定 – 設定:php.iniの正しい文字コード設定• 文字エンコーディングの妥当性チェックで防げない脆弱性に 注意 Copyright © 2011 HASH Consulting Corp. 29
  30. 30. 文字コードの妥当性チェックで防げない脆弱性の例~5C問題によるSQLインジェクション~ PHP5.3.5までのPDOの話 現在は、DB接続時に文字エンコーディングを指定すれば問題ない Copyright © 2010 HASH Consulting Corp. 30
  31. 31. 鉄則42010年代のWebサイトはクリックジャッキング対策しよう Copyright © 2011 HASH Consulting Corp. 31
  32. 32. クリックジャッキング攻撃• ターゲットの画面をiframe上で「透明に」表示する• その下にダミーの画面を表示させる。ユーザにはダミーの画 面が透けて見える• 利用者がダミーの画面上のボタンを押すと、実際には全面の ターゲット画面のボタンが押される 本当の画面(前面、透明) ダミーの画面(後面)• 続きはデモで Copyright © 2011 HASH Consulting Corp. 32
  33. 33. クリックジャッキングの対策• クリックジャッキングの影響はクロスサイト・リクエストフォー ジェリ(CSRF)と同等 – ユーザの意識とは無関係に、ユーザの権限で操作が行われる• クリックジャッキングされると困るページには、X-FRAME- OPTIONSヘッダを指定する(徳丸本P63) – frame/iframeを禁止して良い場合 – header(X-FRAME-OPTIONS, DENY); – frame/iframeを禁止できないが単一ホストの場合 – header(X-FRAME-OPTIONS, SAMEORIGIN);• CSRF対策のトークン発行しているページが対象となる• メタ要素によるX-FRAME-OPTIONS指定は無効です。 徳丸本第3刷までの記述は間違いです(_ _) Copyright © 2011 HASH Consulting Corp. 33
  34. 34. 鉄則3パスワードの保存はhash(pass . salt)の繰り返し(Stretching) Copyright © 2011 HASH Consulting Corp. 34
  35. 35. どうして暗号化ではなくてハッシュなの?• 暗号化の場合、鍵の管理が難しい• アプリケーションは鍵を使わなければならないが、攻撃者には鍵を見せ たくない• PSNの事件では、権限昇格されたことになっているので、暗号鍵も盗ま れていると想定せざるを得ない• ハッシュだと鍵を使わないので、鍵管理のわずらわしさがない• パスワードをサイト管理者にも知られたくないというニーズも – 暗号化されたパスワードだと、サイト管理者やヘルプデスク担当者がパスワードを 知り得るのが嫌だ – ヘルプデスクに見せないようにするには、サポート用画面の機能次第で可 – 管理者の悪事は総合的な対策が必要で、パスワードの問題だけではない• PCI-DSS2.0 8.4項には「8.4 強力な暗号化を使用して、すべてのシス テムコンポーネントでの伝送および保存中のすべてのパスワードを読 み取り不能にする」とあり、ハッシュを求めてはいない Copyright © 2011 HASH Consulting Corp. 35
  36. 36. ハッシュで保存されたパスワードは本当に安全なの?• 一般的に、(暗号論的)ハッシュ値から平文を「復元する」ことはできな い – 「password」のMD5ハッシュ: 5f4dcc3b5aa765d61d8327deb882cf99• しかし、パスワードの場合は特別な事情がある• 例:4桁の暗証番号をハッシュ値で保存している場合 – 全ての可能性は1万通りしかないのだから、総当たりで確認すれば、平文の暗証 番号はすぐに判明する• 原理は8桁パスワードでも同じ• ハッシュ保存の場合、アルゴリズムは攻撃者が知っている前提で安全 な設計とする – 平文パスワード以外は、すべて「ばれている」想定を置く• 攻撃者にとって未知であることが保証された情報があれば、それを鍵と して暗号化すればよい。現実にはそのような保証がないから暗号化を 用いない Copyright © 2011 HASH Consulting Corp. 36
  37. 37. Saltってなに?• ソルト(Salt)とは、ハッシュの元データ(パスワード)に追加する文字列• 見かけのパスワードの長さを長くする – 公開されたレインボーテーブルは10文字までのパスワードに対応しているので、 パスワードとソルトを合わせて20文字以上にしておけば、当面は大丈夫• ユーザ毎にソルトを変えることで、パスワードが同じでも、異なるハッ シュ値が得られる• ソルトの要件 – ある程度の長さを確保すること – ユーザ毎に異なるものにすること• ソルトには乱数を用いることが多いが、乱数が必須というわけではない (暗号論的に安全な乱数である必要はもちろんない)• ソルトは秘密情報ではない。ソルトは、通常ハッシュ値と一緒に保存す る Copyright © 2011 HASH Consulting Corp. 37
  38. 38. Stretchingってなに?• ストレッチング(Stretching)とは、ハッシュの計算を繰り返すこと• ハッシュの計算を遅くすることにより、辞書攻撃や総当たり攻撃に対抗 する• 1万回ストレッチすると、「 GPU で 7 時間である」が7万時間になる計算 – 7万時間 = 2916日 = 約8年• 「悪い」パスワードまで救えるわけではない – 「password」というパスワードをつけていたら、100万回ストレッチしてもすぐに解 読されてしまう• 十分長いパスワードをつけてもらえば、ストレッチングは必要ない – 1文字パスワードを長くすることは、約100回のストレッチングに相当する。パス ワードを2文字長くしてもらえば… – でも、中々難しいのでストレッチングの値打ちがある• ストレッチングはメリットとデメリットがあるので、導入の有無と回数をよ く検討すること Copyright © 2011 HASH Consulting Corp. 38
  39. 39. 鉄則2PHPのバージョンアップにとことん付き合う信念 Copyright © 2011 HASH Consulting Corp. 39
  40. 40. PHPのバージョンアップにタイムリーに追随しよう• PHPは脆弱性もあるが、基本的には迅速に対応している• 基本的にはバージョンアップによりPHPの脆弱性対応を行う – Linuxディストリビューションの配布するパッチを利用することも可• サイト稼働中のPHPメジャーバージョンアップの可能性を考 慮しておくこと PHP5.x PHP4.x PHP3.x 3.5年 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 Copyright © 2011 HASH Consulting Corp. 40
  41. 41. 鉄則1徳丸本を買ってよく読め ご清聴ありがとうございました Copyright © 2011 HASH Consulting Corp. 41

×