セキュアコーディング方法論再構築の試み

10,504 views
8,910 views

Published on

「オワスプデイ in TOKYO 2016 Spring!!」発表資料

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

No Downloads
Views
Total views
10,504
On SlideShare
0
From Embeds
0
Number of Embeds
589
Actions
Shares
0
Downloads
83
Comments
0
Likes
71
Embeds 0
No embeds

No notes for slide

セキュアコーディング方法論再構築の試み

  1. 1. セキュアコーディング方法論再構築の試み HASH コンサルティング株式会社 徳丸 浩
  2. 2. 徳丸浩の自己紹介 • 経歴 – 1985年 京セラ株式会社入社 – 1995年 京セラコミュニケーションシステム株式会社(KCCS)に出向・転籍 – 2008年 KCCS退職、HASHコンサルティング株式会社設立 • 経験したこと – 京セラ入社当時はCAD、計算幾何学、数値シミュレーションなどを担当 – その後、企業向けパッケージソフトの企画・開発・事業化を担当 – 1999年から、携帯電話向けインフラ、プラットフォームの企画・開発を担当 Webアプリケーションのセキュリティ問題に直面、研究、社内展開、寄稿などを開始 – 2004年にKCCS社内ベンチャーとしてWebアプリケーションセキュリティ事業を立ち上げ • 現在 – HASHコンサルティング株式会社 代表 http://www.hash-c.co.jp/ – 独立行政法人情報処理推進機構 非常勤研究員 http://www.ipa.go.jp/security/ – 著書「体系的に学ぶ 安全なWebアプリケーションの作り方」(2011年3月) 「徳丸浩のWebセキュリティ教室 」(2015年10月) – 技術士(情報工学部門) Copyright © 2016 HASH Consulting Corp. 2
  3. 3. セキュアコーディングに対する問題意識 • 原則論 v.s. 各論 – 雑多な「詰め合わせセット」のようなイメージ – レイヤーがまちまちだし – 原則から各論が導かれていない – 優先順位に納得感が薄い • 用語が不明確で訳わからないお – 信頼境界 – バリデーション • そもそもセキュアコーディングとは何だ? Copyright © 2016 HASH Consulting Corp. 3
  4. 4. そもそもセキュアコーディングとは何だ? • 「脆弱性がない」を目指すだけでは、もはやセキュアコーディングと は言えない – セキュアコーディングでなくても、「脆弱性がないこと」は求められる • 「セキュアOS」と比べるとよい – 通常のOSも脆弱性がないことが求められる – セキュアOSは、脆弱性があっても攻撃を受けにくい、攻撃の影響が緩和される ことを目指す • 以下の様なものではないか? – 脆弱性を解消する上で、もっとも確実な方法を採用する – 複数の対策を組み合わせて対策もれを防ぐ(多層防御) – 不測の事態により対策が回避されることを防ぐ Copyright © 2016 HASH Consulting Corp. 4 by @hebikuzure
  5. 5. 代表的なセキュアコーディングの解説例 Copyright © 2016 HASH Consulting Corp. 5
  6. 6. Top 10 Secure Coding Practices (CERT) 1. Validate input. 2. Heed compiler warnings. 3. Architect and design for security policies. 4. Keep it simple. 5. Default deny. 6. Adhere to the principle of least privilege. 7. Sanitize data sent to other systems. 8. Practice defense in depth. 9. Use effective quality assurance techniques. 10. Adopt a secure coding standard. 6 https://www.securecoding.cert.org/confluence/display/seccode/ Top+10+Secure+Coding+Practices
  7. 7. OWASP Top 10 Proactive Controls 2016 1. 早期に、繰り返しセキュリティを検証する 2. クエリーのパラメータ化 3. データのエンコーディング 4. すべての入力値を検証する 5. アイデンティティと認証管理の実装 6. 適切なアクセス制御の実装 7. データの保護 8. ロギングと侵入検知の実装 9. セキュリティフレームワークやライブラリの活用 10. エラー処理と例外処理 7OWASP Top 10 Proactive Controls 2016より引用
  8. 8. CERT C コーディングスタンダード • 00. はじめに • 01. プリプロセッサ (PRE) • 02. 宣言と初期化 (DCL) • 03. 式 (EXP) • 04. 整数 (INT) • 05. 浮動小数点 (FLP) • 06. 配列 (ARR) • 07. 文字と文字列 (STR) • 08. メモリ管理 (MEM) • 09. 入出力 (FIO) • 10. 環境 (ENV) • 11. シグナル (SIG) • 12. エラー処理 (ERR) • 13. Application Programming Interface (API) • 14. 並行性 (CON) • 49. 雑則 (MSC) • 50. POSIX (POS) • AA. 参考情報 • BB. Definitions • CC. 未定義の動作 • DD. 未規定の動作 8https://www.jpcert.or.jp/sc-rules/
  9. 9. Java セキュアコーディングスタンダード CERT/Oracle 版 • はじめに • 00. 入力値検査とデータの無害化 (IDS) • 01. 宣言と初期化 (DCL) • 02. 式 (EXP) • 03. 数値型とその操作 (NUM) • 04. オブジェクト指向 (OBJ) • 05. メソッド (MET) • 06. 例外時の動作 (ERR) • 07. 可視性とアトミック性 (VNA) • 08. ロック (LCK) • 09. スレッド API (THI) • 10. スレッドプール (TPS) • 11. スレッドの安全性に関する雑則 (TSM) • 12. 入出力 (FIO) • 13. シリアライズ (SER) • 14. プラットフォームのセキュリティ (SEC) • 15. 実行環境 (ENV) • 49. 雑則 (MSC) • AA. 参考情報 • BB. Glossary 9https://www.jpcert.or.jp/java-rules/
  10. 10. IDS00-J. 信頼境界を越えて渡される信頼できないデータは無害化する 多くのプログラムは、認証済みでないユーザやネットワーク接続等、信頼できない 情報源からデータを受け取り、それを(改変したり、あるいはそのまま)信頼境界 (trust boundary)を越えて、信頼される側に渡す。多くの場合、データは、一定の シンタックスを持つ文字列であり、プログラム内部のサブシステムによって解析さ れる。不正な形式の入力データには対応できないかもしれないし、インジェクショ ン攻撃が含まれているかもしれないため、そのような入力データは無害化 (sanitize)しなくてはならない。 特にコマンドインタプリタやパーサに渡される文字列データはすべて、解析される 文脈で無害な状態(innocuous)にしなければならない。 コマンドインタプリタやパーサの多くは、独自の無害化メカニズムや検査機構を 備えている。可能であれば、それらの無害化メカニズムを使用するほうが、独自に 無害化メカニズムを実装するよりも好ましい。独自に実装した無害化メカニズムで は、特殊なケースやパーサの複雑な内部構造に配慮しない実装を行ってしまう可能 性がある。それだけでなく、コマンドインタプリタやパーサに新しい機能が追加さ れたとき、無害化メカニズムが適切にメンテナンスされない恐れもある。 10アーカイブ http://web.archive.org/web/20150515043831/ https://www.jpcert.or.jp/java-rules/ids00-j.html
  11. 11. 11 どのような場所で検証?  エントリーポイント  ユーザによる入力  他システムとの連携ポイント  信頼境界  ここを超えるデータを検証 信頼境界 http://download.microsoft.com/download/3/e/e/3ee9501d-df73-41e9-baba-a1b4e41cb1ba/SecurityL100dataissue_6.ppt 先程の現実世界の例と同様に、すべての入 り口、つまりエントリポイントでデータを 検証(チェック)すべきです。 たとえば、SQLインジェクションは悪意の ある、なしにかかわらず、ユーザが入力し たデータを検証せずに、そのままSQL文の 一部として利用してしまった場合に発生し ます。【中略】 一方、すでに検証済みの信頼のおけるデー タはそのまま利用することができます。先 程の例では、高い塀の内側にある場合がそ れです。この壁を信頼境界といいます。
  12. 12. こうですか、わかりません (>_<)/ Copyright © 2016 HASH Consulting Corp. 12 無害化 フィルタ SQL 呼び出し 信頼境界を越えて渡される信頼できないデータは無害化する 信頼境界 無害なデータ信頼できないデータ
  13. 13. こうですか、わかりません (>_<)/ Copyright © 2016 HASH Consulting Corp. 13 無害化 フィルタ SQL 呼び出し 信頼境界を越えて渡される信頼できないデータは無害化する 信頼境界 無害なデータ信頼できないデータ
  14. 14. 14 BOBBY TABLES IS WRONG. WHY? https://www.owasp.org/images/3/33/OWASP_Top_Ten_Proactive_Controls_v2.pptx
  15. 15. 15 '--@owasp.org https://www.owasp.org/images/3/33/OWASP_Top_Ten_Proactive_Controls_v2.pptx
  16. 16. 16https://www.owasp.org/images/3/33/OWASP_Top_Ten_Proactive_Controls_v2.pptx 1. update users set email='$NEW_EMAIL' where id=290494828 2. $NEW_EMAIL = '--@owasp.org 3. update users set email=''--@owasp.org' where id=290494828
  17. 17. IDS00-J. 信頼境界を越えて渡される信頼できないデータは無害化する 多くのプログラムは、認証済みでないユーザやネットワーク接続等、信頼できない情報源か らデータを受け取り、それを(改変したり、あるいはそのまま)信頼境界(trust boundary)を越えて、信頼される側に渡す。多くの場合、データは、一定のシンタックスを 持つ文字列であり、プログラム内部のサブシステムによって解析される。不正な形式の入力 データには対応できないかもしれないし、インジェクション攻撃が含まれているかもしれな いため、そのような入力データは無害化(sanitize)しなくてはならない。 特にコマンドインタプリタやパーサに渡される文字列データはすべて、解析される文脈で無 害な状態(innocuous)にしなければならない。 コマンドインタプリタやパーサの多くは、独自の無害化メカニズムや検査機構を備えてい る。可能であれば、それらの無害化メカニズムを使用するほうが、独自に無害化メカニズム を実装するよりも好ましい。独自に実装した無害化メカニズムでは、特殊なケースやパーサ の複雑な内部構造に配慮しない実装を行ってしまう可能性がある。それだけでなく、コマン ドインタプリタやパーサに新しい機能が追加されたとき、無害化メカニズムが適切にメンテ ナンスされない恐れもある。 17 アーカイブ http://web.archive.org/web/20150515043831/ https://www.jpcert.or.jp/java-rules/ids00-j.html
  18. 18. IDS00-J. 信頼境界を越えて渡される信頼できないデータは無害化する 違反コード 以下の違反コード例は、ユーザ認証を行うJDBCのコードを示している。パスワードはchar型 配列として渡され、データベースへの接続が作成され、パスワードがハッシュ化されている。 残念ながらこのコードはSQLインジェクション攻撃を許してしまう。SQL文 sqlString は無害 化されていない入力値を受け付けており、前述の攻撃シナリオが成立してしまうだろう。 適合コード (PreparedStatement) 幸いJDBCライブラリはSQLコマンドを組み立てるAPIを提供しており、信頼できないデータ を無害化してくれる。java.sql.PreparedStatementクラスは入力文字列を適切にエスケープ処 理するため、適切に利用すればSQLインジェクション攻撃を防ぐことができる。これはコン ポーネントベースで行う無害化の一例である。 この適合コードでは java.sql.Statement の代わりに PreparedStatementを使用するように doPrivilegedAction() メソッドを変更している。また、引数 username の長さを検証しており、 攻撃者が任意に長いユーザ名を送り込むことを防止している。 18 アーカイブ http://web.archive.org/web/20150515043831/ https://www.jpcert.or.jp/java-rules/ids00-j.html
  19. 19. こうだった Copyright © 2016 HASH Consulting Corp. 19 安全な形でSQL 呼び出し 信頼境界を越えて渡される信頼できないデータは無害化する 信頼境界 信頼できないデータ プレースホルダ
  20. 20. そもそも信頼境界関係なくね? Copyright © 2016 HASH Consulting Corp. 20
  21. 21. そう、故に見出しが改定された Copyright © 2016 HASH Consulting Corp. 21
  22. 22. 22https://www.jpcert.or.jp/java-rules/ids00-j.html まさかの「SQLインジェクションを防ぐ」 信頼境界も、信頼できないも、無害化も タイトルから消えた
  23. 23. では、信頼境界は無意味? Copyright © 2016 HASH Consulting Corp. 23
  24. 24. そうでもない Copyright © 2016 HASH Consulting Corp. 24
  25. 25. こういうのはダメ Copyright © 2016 HASH Consulting Corp. 25 SQL呼び出し hiddenパラメータでSQL文を渡している 信頼境界 hiddenパラメータで SQL文を渡している
  26. 26. phpMyAdminの場合 Copyright © 2016 HASH Consulting Corp. 26 SQL呼び出し 信頼境界 ソースコード セッション変数 データベース 設定ファイル … 信頼できる情報源 SQL文 SQL文 SQL文 DB管理者 認証・認可
  27. 27. 「安全なウェブサイトの作り方」に出てくる信頼境界の例 • SQLインジェクション – ウェブアプリケーションに渡されるパラメータにSQL文を直接指定しない。 • OSコマンドインジェクション – Perlのopen関数は、引数として与えるファイルパスに「|」(パイプ)を使うことでOSコマン ドを実行できるため、外部からの入力値を引数として利用する実装は危険です • ディレクトリトラバーサル – 外部からのパラメータでウェブサーバ内のファイル名を直接指定する実装を避ける – ファイルを開く際は、固定のディレクトリを指定し、かつファイル名にディレクトリ名が含ま れないようにする。 • XSS – 入力されたHTMLテキストから構文解析木を作成し、スクリプトを含まない必要な要素のみを 抽出する – 入力されたHTMLテキストから、スクリプトに該当する文字列を排除する Copyright © 2016 HASH Consulting Corp. 27
  28. 28. 「信頼されたデータ」が要求される例 • 信頼境界の中のデータ – プログラムコード – SQL文 – evalの入力 – 設定ファイル名に記載されたファイル名 – 正規表現 – オブジェクト • アプリケーションで「信頼できることを確認」 – ログイン済みユーザ名(認証) – 管理者が入力するSQL文(認可) – CMSに入力するHTML(認可) – 制限されたHTML(フィルタリング) – 外部からのファイル名(basename) Copyright © 2016 HASH Consulting Corp. 28
  29. 29. 信頼に関して… • 安全に使う方法があれば「信頼」を気にしない – SQL文のプレースホルダにバインドする値 – シェルを経由しないコマンド呼び出しのパラメータ – 安全なメール送信APIに渡すメールアドレス • 信頼するしかないデータもある – プログラムコード、SQL文そのもの – evalの入力、正規表現 – オブジェクト • 認証やフィルタリングにより「信頼」できる場合 – basename関数を通したファイル名 – 認証されたユーザ名 – 権限を認可されたSQL文、HTMLテキスト Copyright © 2016 HASH Consulting Corp. 29
  30. 30. phpMyAdmin: CVE-2013-3238 Copyright © 2016 HASH Consulting Corp. 30 case 'replace_prefix_tbl': $current = $selected[$i]; $newtablename = preg_replace("/^" . $from_prefix . "/", $to_prefix, $current); preg_replace("/^/e0/", "phpinfo();", "test"); preg_replace("/^/e", "phpinfo();", "test"); $from_pref = "/e0“; $to_prefix = "phpinfo();”; PHP5.4.3以前では、0以降は無視される
  31. 31. 脆弱性が混入した要因 • preg_replaceに渡す正規表現をエスケープしていなかった – 最低限、/ をエスケープする必要がある • えーっと、preg_quoteって、マルチバイト対応だっけ? – Shift_JIS以外では問題ない? • そもそも、正規表現を外部から(信頼境界を超えて)渡す実装は避け るべき(実際にもその方向で改修された) Copyright © 2016 HASH Consulting Corp. 31 preg_replace(“/^” . $from_prefix . “/”, … ↓ reg_replace("/^" . preg_quote($from_prefix, '/') . "/", …
  32. 32. Joomla2.5.2の権限昇格脆弱性 攻撃の流れ 1. 会員登録時にパスワードを不整合にしておく 2. ユーザ登録時に jforms[groups][]=7 をPOSTパラメータに追加 3. バリデーションでエラー発生 4. 再入力に備えてリクエストのパラメータをすべてセッションに保存 (コントローラ) 5. モデル側で、セッションの中味をすべて取り込み 6. 2.で追加したgroupsが取り込まれる Copyright © 2016 HASH Consulting Corp. 32
  33. 33. Joomla2.5.2の権限昇格脆弱性 components/com_users/controllers/registration.php register()関数 $data = $model->validate($form, $requestData); // Check for validation errors. if ($data === false) { // Save the data in the session. $app->setUserState('com_users.registration.data', $requestData); // Redirect back to the registration screen. $this->setRedirect(JRoute::_('index.php?option=com_users&view=registration', false)); return false; // 中略 // バリデーションが正常の場合 // Flush the data from the session. $app->setUserState('com_users.registration.data', null); Copyright © 2016 HASH Consulting Corp. 33 バリデーションエラーの場合、リクエストデータを まるごとセッション変数に放り込んでいる 権限の情報も含まれている
  34. 34. components/com_users/models/registration.php getData() 関数内 $temp = (array)$app->getUserState('com_users.registration.data', array()); foreach ($temp as $k => $v) { $this->data->$k = $v; // セッションのデータをモデルに放り込んでいる } 【中略】 $this->data->groups = isset($this->data->groups) ? array_unique($this->data->grou ps) : array(); // $this->data->groups = array(); 2.5.3でこのように修正 Copyright © 2016 HASH Consulting Corp. 34 セッション汚染、Trust Boundary Violation と呼ばれる問題
  35. 35. OWASP Top 10 Proactive Controls 2016 1. 早期に、繰り返しセキュリティを検証する 2. クエリーのパラメータ化 3. データのエンコーディング 4. すべての入力値を検証する 5. アイデンティティと認証管理の実装 6. 適切なアクセス制御の実装 7. データの保護 8. ロギングと侵入検知の実装 9. セキュリティフレームワークやライブラリの活用 10. エラー処理と例外処理 35OWASP Top 10 Proactive Controls 2016 より引用 順序に注意
  36. 36. 入力チェックとセキュリティに関する補足 入力チェックの段階では、信頼できない入力値を「無害な状 態に」変換してしまう必要はありません。危険と思われるデー タも「正しいデータ」として受け入れなければならない場合が あります。アプリケーションのセキュリティは、入力値が実際 に使われる箇所で担保されるべきです。たとえば、入力値を HTMLの一部として出力するのであれば、クロスサイトスクリ プティング対策としてHTMLエンコーディングを実装します。 同様に、入力値をSQL文の一部として使うのであれば、クエ リーのパラメータ化を使います。どのような場合であれ、セ キュリティ対策を入力チェックに依存してはいけません。 OWASP Top 10 Proactive Controls 2016 より引用 36
  37. 37. 37 お前は俺か
  38. 38. セキュアコーディングをこう分類したい • 脆弱性を解消する「まさにその場所での対策」 – プレースホルダを用いてSQL文を呼び出す… • 緩和策を実施する – バリデーション – 最小権限 • 前提条件を確認する – 引数チェック・戻り値チェック – 防御的プログラミング • バグの少ない開発に役立つ習慣 – コンパイラのエラーを無視しない – 暗黙の型変換を避ける – … Copyright © 2016 HASH Consulting Corp. 38
  39. 39. バリデーションはプログラムの前提条件 を確実にするために Copyright © 2016 HASH Consulting Corp. 39
  40. 40. Drupageddon(CVE-2014-3704) Copyright © 2016 HASH Consulting Corp. 40
  41. 41. Drupalのログイン処理のSQL文を調べる Copyright © 2012-2014 HASH Consulting Corp. 41 name=admin&pass=xxxxxxxx&form_build_id=form-xQZ7X78LULvs6SyB9MvufbZh5KXjQYRH S05Jl2uD9Kc&form_id=user_login_block&op=Log+in SELECT * FROM users WHERE name = 'admin' AND status = 1 name[]=user1&name[]=user2&pass=xxxxxxxx&form_build_id=form-xQZ7X78LULvs6SyB9 MvufbZh5KXjQYRHS05Jl2uD9Kc&form_id=user_login_block&op=Log+in SELECT * FROM users WHERE name = 'user1', 'user2' AND status = 1 通常時の要求 通常時のSQL文 nameを配列で指定 nameを配列にした場合のSQL文 文字列リテラルが複数生成される
  42. 42. IN句生成の便利な呼び出し方だが… Copyright © 2012-2014 HASH Consulting Corp. 42 <?php db_query("SELECT * FROM {users} where name IN (:name)", array(':name'=>array('user1','user2'))); ?> SELECT * from users where name IN (:name_0, :name_1) array(':name_0'=>'user1', ':name_1'=>'user2')) db_queryにてIN句のバインド値を配列にすると… IN句の値がプレースホルダのリストに展開される バインド値の配列は以下の様に変形される
  43. 43. キー名をつけると Copyright © 2012-2014 HASH Consulting Corp. 43 name[id1]=user1&name[id2]=user2 SELECT * FROM {users} WHERE name = :name_id1, :name_id2 AND status = 1 キー名をつけてみる(id1, id2) プレースホルダにキー名がつく
  44. 44. 空白付きのキー Copyright © 2012-2014 HASH Consulting Corp. 44 array(2) { [":name_1 xxxxx"] => "user1" ← :name_1 ではない [":name_2"] => "user2" } SELECT * FROM {users} WHERE name = :name_1 xxxxx, :name_2 AND status = 1 キー名に空白をつけてみる プレースホルダに空白が含まれる ちぎれたプレースホルダはSQL文の一部 として認識される プレースホルダには、キー :name_1がないので上記のSQL文呼び出しはエラーになる name[1 xxxxx]=user1&name[2]=user2
  45. 45. バインド値のつじつまを合わせる Copyright © 2012-2014 HASH Consulting Corp. 45 array(2) { [":name_2 xxxxx"] => "" [":name_2"] => "user2" } SELECT * FROM {users} WHERE name = :name_2 xxxxx, :name_2 AND statu s = 1 キー名に空白をつけてみる プレースホルダに空白が含まれる プレースホルダ :name_2 が 2箇所現れる プレースホルダ配列は上記SQL文の要求を満たすのでSQL文は呼び出される… が、xxxxxの箇所でSQLの文法違反となる name[2 xxxxx]=&name[2]=user2
  46. 46. SQLインジェクションを試す Copyright © 2012-2014 HASH Consulting Corp. 46 SELECT * FROM users WHERE name = 'user2' ;SELECT sleep(10) -- , 'us er2' AND status = 1 キー名に追加のSQL文を書く 実際に呼び出されるSQL文 name[2 ;SELECT sleep(10) -- ]=&name[2]=user2 SELECT * FROM {users} WHERE name = :name_2 ;SELECT sleep(10) -- , :name_2 AND status = 1 プレースホルダの後ろに追加のSQL文が現れる
  47. 47. 脆弱なソース // includes/database/database.inc protected function expandArguments(&$query, &$args) { $modified = FALSE; // $argsの要素から配列のみ処理対象として foreach foreach (array_filter($args, 'is_array') as $key => $data) { $new_keys = array(); // $dataは配列であるはずなので、foreach 可能。 $i(キー)に注目 foreach ($data as $i => $value) { $new_keys[$key . '_' . $i] = $value; } // $queryを改変 $new_keysのキーをarray_keysでSQL文に混ぜている $query = preg_replace('#' . $key . 'b#', implode(', ', array_keys($new_keys)), $query); unset($args[$key]); $args += $new_keys; $modified = TRUE; } return $modified; } Copyright © 2012-2014 HASH Consulting Corp. 47
  48. 48. 対策版 // includes/database/database.inc protected function expandArguments(&$query, &$args) { $modified = FALSE; // $argsの要素から配列のみ処理対象として foreach foreach (array_filter($args, 'is_array') as $key => $data) { $new_keys = array(); // $dataは配列であるはずなので、foreach 可能。 $i(キー)に注目 //foreach ($data as $i => $value) { foreach (array_values($data) as $i => $value) { // キーを削除 $new_keys[$key . '_' . $i] = $value; } // $queryを改変 $new_keysのキーをarray_keysでSQL文に混ぜている $query = preg_replace('#' . $key . 'b#', implode(', ', array_keys($new_keys)), $query); unset($args[$key]); $args += $new_keys; $modified = TRUE; } return $modified; } Copyright © 2012-2014 HASH Consulting Corp. 48 アドホックな対策に も見えるが、入力値 が実際に使われる箇 所で担保しているこ とが重要
  49. 49. Drupalのログイン画面におけるDoS脆弱性(CVE-2014- 9016) Copyright © 2012-2014 HASH Consulting Corp. 49
  50. 50. 50http://jvndb.jvn.jp/ja/contents/2014/JVNDB-2014-005632.html より引用 想定される影響 第三者により、巧妙に細工されたリクエストを介して、 サービス運用妨害 (CPU 資源およびメモリの消費) 状態にされる可能性があります。
  51. 51. 巧妙に細工されたリクエスト…とは? POST /drupal731/?q=node&destination=node HTTP/1.1 Host: example.jp User-Agent: Mozilla Cookie: has_js=1 Connection: keep-alive Content-Type: application/x-www-form-urlencoded Content-Length: 10114 name=admin&pass=123456789012345678901234567890123456789012345678901234567890123456789012345 678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234 567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890……..…123456789012345 678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 9012345678901234567890123456789012345678901234567890123456789012345678901234567890&form_build_ id=form-Fw_Sa9fPZ5wQBHOURorm7aOILRlK2KXropvxrELFKtc&form_id=user_login_block&op=Log+in Copyright © 2012-2014 HASH Consulting Corp. 51 100万バイトの パスワード
  52. 52. パスワードハッシュ値の計算部分 function _password_crypt($algo, $password, $setting) { // ... // Convert the base 2 logarithm into an integer. $count = 1 << $count_log2; // $count は32768となる // We rely on the hash() function being available in PHP 5.2+. // ソルトとパスワードを連結したもののSHA-512ハッシュを求める $hash = hash($algo, $salt . $password, TRUE); do { // これまでのハッシュ値とパスワードを連結したもののSHA-512ハッシュ $hash = hash($algo, $hash . $password, TRUE); } while (--$count); // 32768回繰り返し $len = strlen($hash); $output = $setting . _password_base64_encode($hash, $len); $expected = 12 + ceil((8 * $len) / 6); return (strlen($output) == $expected) ? substr($output, 0, DRUPAL_HASH_LENGTH) : FALSE; } Copyright © 2012-2014 HASH Consulting Corp. 52
  53. 53. 対策版 function _password_crypt($algo, $password, $setting) { // Prevent DoS attacks by refusing to hash large passwords. if (strlen($password) > 512) { return FALSE; } // 後は同じ… } Copyright © 2012-2014 HASH Consulting Corp. 53 アドホックな対策に も見えるが、入力値 が実際に使われる箇 所で担保しているこ とが重要
  54. 54. 暗黙の型変換に注意 Copyright © 2016 HASH Consulting Corp. 54
  55. 55. MySQL: どうなる: name=‘tana’ + ‘ka’ mysql> SELECT * FROM members WHERE name='tanaka'; +----+--------+-------------------+ | id | name | email | +----+--------+-------------------+ | 8 | tanaka | tanaka@example.jp | +----+--------+-------------------+ mysql> SELECT * FROM members WHERE name='tana'+'ka'; どうなる? Copyright © 2016 HASH Consulting Corp. 55
  56. 56. MySQL: こうなる: name=‘tana’ + ‘ka’ mysql> SELECT * FROM members WHERE name='tanaka'; +----+--------+-------------------+ | id | name | email | +----+--------+-------------------+ | 8 | tanaka | tanaka@example.jp | +----+--------+-------------------+ mysql> SELECT * FROM members WHERE name='tana'+'ka'; +----+-----------+---------------------+ | id | name | email | +----+-----------+---------------------+ | 4 | tokumaru | tokumaru@example.jp | | 5 | sato | sato@example.jp | | 6 | yamada | yamada@example.jp | | 8 | tanaka | tanaka@example.jp | | 9 | suzuki | suzuki@example.jp | +----+-----------+---------------------+ 5 rows in set, 8 warnings (0.00 sec) Copyright © 2016 HASH Consulting Corp. 56 まさかの 全件一致 暗黙の型変 換が原因
  57. 57. MySQLの「暗黙の型変換の罠」 • ‘tana’ + ‘ka’ は ‘tana’ と ‘ka’ の算術加算 • MySQLは、算術加算のオペランドを数値に「暗黙に」型変換する ちなみに浮動小数点数になる) • name = ‘tana’ + ‘ka’ は name=0 と同じ • 列nameが文字列型の場合、name列を数値に変換してから比較する • すなわち、’yamada’ = 0 となる → まさかの ‘yamada’ = ‘tana’ + ‘ka’ Copyright © 2016 HASH Consulting Corp. 57
  58. 58. 再(まとめとして) : セキュアコーディングをこう分類したい • 脆弱性を解消する「まさにその場所での対策」 – プレースホルダを用いてSQL文を呼び出す… • 緩和策を実施する – バリデーション – 最小権限 • 前提条件を確認する – 引数チェック・戻り値チェック – 防御的プログラミング • バグの少ない開発に役立つ習慣 – コンパイラのエラーを無視しない – 暗黙の型変換を避ける – … Copyright © 2016 HASH Consulting Corp. 58

×