Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

13,371 views

Published on

Published in: Technology
  • Be the first to comment

徳丸本に学ぶ 安全な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

×