1.6K Views
February 27, 16
スライド概要
「オワスプデイ in TOKYO 2016 Spring!!」発表資料
セキュアコーディング方法論再構築の試み HASH コンサルティング株式会社 徳丸 浩
徳丸浩の自己紹介 • 経歴 – 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
セキュアコーディングに対する問題意識 • 原則論 v.s. 各論 – – – – 雑多な「詰め合わせセット」のようなイメージ レイヤーがまちまちだし 原則から各論が導かれていない 優先順位に納得感が薄い • 用語が不明確で訳わからないお – 信頼境界 – バリデーション • そもそもセキュアコーディングとは何だ? Copyright © 2016 HASH Consulting Corp. 3
そもそもセキュアコーディングとは何だ? • 「脆弱性がない」を目指すだけでは、もはやセキュアコーディングと は言えない by @hebikuzure – セキュアコーディングでなくても、「脆弱性がないこと」は求められる • 「セキュアOS」と比べるとよい – 通常のOSも脆弱性がないことが求められる – セキュアOSは、脆弱性があっても攻撃を受けにくい、攻撃の影響が緩和される ことを目指す • 以下の様なものではないか? – 脆弱性を解消する上で、もっとも確実な方法を採用する – 複数の対策を組み合わせて対策もれを防ぐ(多層防御) – 不測の事態により対策が回避されることを防ぐ Copyright © 2016 HASH Consulting Corp. 4
代表的なセキュアコーディングの解説例 Copyright © 2016 HASH Consulting Corp. 5
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. https://www.securecoding.cert.org/confluence/display/seccode/ Top+10+Secure+Coding+Practices 6
OWASP Top 10 Proactive Controls 2016 1. 早期に、繰り返しセキュリティを検証する 2. クエリーのパラメータ化 3. データのエンコーディング 4. すべての入力値を検証する 5. アイデンティティと認証管理の実装 6. 適切なアクセス制御の実装 7. データの保護 8. ロギングと侵入検知の実装 9. セキュリティフレームワークやライブラリの活用 10. エラー処理と例外処理 OWASP Top 10 Proactive Controls 2016より引用 7
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. 未規定の動作 https://www.jpcert.or.jp/sc-rules/ 8
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 https://www.jpcert.or.jp/java-rules/ 9
IDS00-J. 信頼境界を越えて渡される信頼できないデータは無害化する 多くのプログラムは、認証済みでないユーザやネットワーク接続等、信頼できない 情報源からデータを受け取り、それを(改変したり、あるいはそのまま)信頼境界 (trust boundary)を越えて、信頼される側に渡す。多くの場合、データは、一定の シンタックスを持つ文字列であり、プログラム内部のサブシステムによって解析さ れる。不正な形式の入力データには対応できないかもしれないし、インジェクショ ン攻撃が含まれているかもしれないため、そのような入力データは無害化 (sanitize)しなくてはならない。 特にコマンドインタプリタやパーサに渡される文字列データはすべて、解析される 文脈で無害な状態(innocuous)にしなければならない。 コマンドインタプリタやパーサの多くは、独自の無害化メカニズムや検査機構を 備えている。可能であれば、それらの無害化メカニズムを使用するほうが、独自に 無害化メカニズムを実装するよりも好ましい。独自に実装した無害化メカニズムで は、特殊なケースやパーサの複雑な内部構造に配慮しない実装を行ってしまう可能 性がある。それだけでなく、コマンドインタプリタやパーサに新しい機能が追加さ れたとき、無害化メカニズムが適切にメンテナンスされない恐れもある。 アーカイブ http://web.archive.org/web/20150515043831/ https://www.jpcert.or.jp/java-rules/ids00-j.html 10
どのような場所で検証? ⚫ エントリーポイント ⚫ ⚫ ⚫ ユーザによる入力 他システムとの連携ポイント 信頼境界 ⚫ ここを超えるデータを検証 信頼境界 先程の現実世界の例と同様に、すべての入 り口、つまりエントリポイントでデータを 検証(チェック)すべきです。 たとえば、SQLインジェクションは悪意の ある、なしにかかわらず、ユーザが入力し たデータを検証せずに、そのままSQL文の 一部として利用してしまった場合に発生し ます。【中略】 一方、すでに検証済みの信頼のおけるデー タはそのまま利用することができます。先 程の例では、高い塀の内側にある場合がそ れです。この壁を信頼境界といいます。 http://download.microsoft.com/download/3/e/e/3ee9501d-df73-41e9-baba-a1b4e41cb1ba/SecurityL100dataissue_6.ppt 11
こうですか、わかりません (>_<)/ 信頼境界を越えて渡される信頼できないデータは無害化する 信頼境界 信頼できないデータ 無害化 フィルタ 無害なデータ Copyright © 2016 HASH Consulting Corp. SQL 呼び出し 12
こうですか、わかりません (>_<)/ 信頼境界を越えて渡される信頼できないデータは無害化する 信頼境界 信頼できないデータ 無害化 フィルタ 無害なデータ Copyright © 2016 HASH Consulting Corp. SQL 呼び出し 13
BOBBY TABLES IS WRONG. WHY? https://www.owasp.org/images/3/33/OWASP_Top_Ten_Proactive_Controls_v2.pptx 14
'[email protected] https://www.owasp.org/images/3/33/OWASP_Top_Ten_Proactive_Controls_v2.pptx 15
1. update users set email='$NEW_EMAIL' where id=290494828 2. $NEW_EMAIL = '[email protected] 3. update users set email=''[email protected]' where id=290494828 https://www.owasp.org/images/3/33/OWASP_Top_Ten_Proactive_Controls_v2.pptx 16
IDS00-J. 信頼境界を越えて渡される信頼できないデータは無害化する 多くのプログラムは、認証済みでないユーザやネットワーク接続等、信頼できない情報源か らデータを受け取り、それを(改変したり、あるいはそのまま)信頼境界(trust boundary)を越えて、信頼される側に渡す。多くの場合、データは、一定のシンタックスを 持つ文字列であり、プログラム内部のサブシステムによって解析される。不正な形式の入力 データには対応できないかもしれないし、インジェクション攻撃が含まれているかもしれな いため、そのような入力データは無害化(sanitize)しなくてはならない。 特にコマンドインタプリタやパーサに渡される文字列データはすべて、解析される文脈で無 害な状態(innocuous)にしなければならない。 コマンドインタプリタやパーサの多くは、独自の無害化メカニズムや検査機構を備えてい る。可能であれば、それらの無害化メカニズムを使用するほうが、独自に無害化メカニズム を実装するよりも好ましい。独自に実装した無害化メカニズムでは、特殊なケースやパーサ の複雑な内部構造に配慮しない実装を行ってしまう可能性がある。それだけでなく、コマン ドインタプリタやパーサに新しい機能が追加されたとき、無害化メカニズムが適切にメンテ ナンスされない恐れもある。 アーカイブ http://web.archive.org/web/20150515043831/ https://www.jpcert.or.jp/java-rules/ids00-j.html 17
IDS00-J. 信頼境界を越えて渡される信頼できないデータは無害化する 違反コード 以下の違反コード例は、ユーザ認証を行うJDBCのコードを示している。パスワードはchar型 配列として渡され、データベースへの接続が作成され、パスワードがハッシュ化されている。 残念ながらこのコードはSQLインジェクション攻撃を許してしまう。SQL文 sqlString は無害 化されていない入力値を受け付けており、前述の攻撃シナリオが成立してしまうだろう。 適合コード (PreparedStatement) 幸いJDBCライブラリはSQLコマンドを組み立てるAPIを提供しており、信頼できないデータ を無害化してくれる。java.sql.PreparedStatementクラスは入力文字列を適切にエスケープ処 理するため、適切に利用すればSQLインジェクション攻撃を防ぐことができる。これはコン ポーネントベースで行う無害化の一例である。 この適合コードでは java.sql.Statement の代わりに PreparedStatementを使用するように doPrivilegedAction() メソッドを変更している。また、引数 username の長さを検証しており、 攻撃者が任意に長いユーザ名を送り込むことを防止している。 アーカイブ http://web.archive.org/web/20150515043831/ https://www.jpcert.or.jp/java-rules/ids00-j.html 18
こうだった 信頼境界を越えて渡される信頼できないデータは無害化する 信頼境界 プレースホルダ 信頼できないデータ Copyright © 2016 HASH Consulting Corp. 安全な形でSQL 呼び出し 19
そもそも信頼境界関係なくね? Copyright © 2016 HASH Consulting Corp. 20
そう、故に見出しが改定された Copyright © 2016 HASH Consulting Corp. 21
まさかの「SQLインジェクションを防ぐ」 信頼境界も、信頼できないも、無害化も タイトルから消えた https://www.jpcert.or.jp/java-rules/ids00-j.html 22
では、信頼境界は無意味? Copyright © 2016 HASH Consulting Corp. 23
そうでもない Copyright © 2016 HASH Consulting Corp. 24
こういうのはダメ hiddenパラメータでSQL文を渡している 信頼境界 hiddenパラメータで SQL文を渡している SQL呼び出し Copyright © 2016 HASH Consulting Corp. 25
phpMyAdminの場合 DB管理者 信頼境界 認証・認可 SQL呼び出し SQL文 信頼できる情報源 SQL文 SQL文 ソースコード セッション変数 データベース 設定ファイル … Copyright © 2016 HASH Consulting Corp. 26
「安全なウェブサイトの作り方」に出てくる信頼境界の例 • SQLインジェクション – ウェブアプリケーションに渡されるパラメータにSQL文を直接指定しない。 • OSコマンドインジェクション – Perlのopen関数は、引数として与えるファイルパスに「|」(パイプ)を使うことでOSコマン ドを実行できるため、外部からの入力値を引数として利用する実装は危険です • ディレクトリトラバーサル – 外部からのパラメータでウェブサーバ内のファイル名を直接指定する実装を避ける – ファイルを開く際は、固定のディレクトリを指定し、かつファイル名にディレクトリ名が含ま れないようにする。 • XSS – 入力されたHTMLテキストから構文解析木を作成し、スクリプトを含まない必要な要素のみを 抽出する – 入力されたHTMLテキストから、スクリプトに該当する文字列を排除する Copyright © 2016 HASH Consulting Corp. 27
「信頼されたデータ」が要求される例 • 信頼境界の中のデータ – – – – – – プログラムコード SQL文 evalの入力 設定ファイル名に記載されたファイル名 正規表現 オブジェクト • アプリケーションで「信頼できることを確認」 – – – – – ログイン済みユーザ名(認証) 管理者が入力するSQL文(認可) CMSに入力するHTML(認可) 制限されたHTML(フィルタリング) 外部からのファイル名(basename) Copyright © 2016 HASH Consulting Corp. 28
信頼に関して… • 安全に使う方法があれば「信頼」を気にしない – SQL文のプレースホルダにバインドする値 – シェルを経由しないコマンド呼び出しのパラメータ – 安全なメール送信APIに渡すメールアドレス • 信頼するしかないデータもある – プログラムコード、SQL文そのもの – evalの入力、正規表現 – オブジェクト • 認証やフィルタリングにより「信頼」できる場合 – basename関数を通したファイル名 – 認証されたユーザ名 – 権限を認可されたSQL文、HTMLテキスト Copyright © 2016 HASH Consulting Corp. 29
phpMyAdmin: CVE-2013-3238
case 'replace_prefix_tbl':
$current = $selected[$i];
$newtablename = preg_replace("/^" . $from_prefix . "/", $to_prefix, $current);
$from_pref = "/e\0“;
$to_prefix = "phpinfo();”;
preg_replace("/^/e\0/", "phpinfo();", "test");
PHP5.4.3以前では、\0以降は無視される
preg_replace("/^/e", "phpinfo();", "test");
Copyright © 2016 HASH Consulting Corp.
30
脆弱性が混入した要因 • preg_replaceに渡す正規表現をエスケープしていなかった – 最低限、/ をエスケープする必要がある preg_replace(“/^” . $from_prefix . “/”, … ↓ reg_replace("/^" . preg_quote($from_prefix, '/') . "/", … • えーっと、preg_quoteって、マルチバイト対応だっけ? – Shift_JIS以外では問題ない? • そもそも、正規表現を外部から(信頼境界を超えて)渡す実装は避け るべき(実際にもその方向で改修された) Copyright © 2016 HASH Consulting Corp. 31
Joomla2.5.2の権限昇格脆弱性 攻撃の流れ 1. 2. 3. 4. 会員登録時にパスワードを不整合にしておく ユーザ登録時に jforms[groups][]=7 をPOSTパラメータに追加 バリデーションでエラー発生 再入力に備えてリクエストのパラメータをすべてセッションに保存 (コントローラ) 5. モデル側で、セッションの中味をすべて取り込み 6. 2.で追加したgroupsが取り込まれる Copyright © 2016 HASH Consulting Corp. 32
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
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; // セッションのデータをモデルに放り込んでいる
}
【中略】
セッション汚染、Trust Boundary Violation
と呼ばれる問題
$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
OWASP Top 10 Proactive Controls 2016 1. 早期に、繰り返しセキュリティを検証する 2. クエリーのパラメータ化 3. データのエンコーディング 順序に注意 4. すべての入力値を検証する 5. アイデンティティと認証管理の実装 6. 適切なアクセス制御の実装 7. データの保護 8. ロギングと侵入検知の実装 9. セキュリティフレームワークやライブラリの活用 10. エラー処理と例外処理 OWASP Top 10 Proactive Controls 2016 より引用 35
入力チェックとセキュリティに関する補足 入力チェックの段階では、信頼できない入力値を「無害な状 態に」変換してしまう必要はありません。危険と思われるデー タも「正しいデータ」として受け入れなければならない場合が あります。アプリケーションのセキュリティは、入力値が実際 に使われる箇所で担保されるべきです。たとえば、入力値を HTMLの一部として出力するのであれば、クロスサイトスクリ プティング対策としてHTMLエンコーディングを実装します。 同様に、入力値をSQL文の一部として使うのであれば、クエ リーのパラメータ化を使います。どのような場合であれ、セ キュリティ対策を入力チェックに依存してはいけません。 OWASP Top 10 Proactive Controls 2016 より引用 36
お前は俺か 37
セキュアコーディングをこう分類したい • 脆弱性を解消する「まさにその場所での対策」 – プレースホルダを用いてSQL文を呼び出す… • 緩和策を実施する – バリデーション – 最小権限 • 前提条件を確認する – 引数チェック・戻り値チェック – 防御的プログラミング • バグの少ない開発に役立つ習慣 – コンパイラのエラーを無視しない – 暗黙の型変換を避ける – … Copyright © 2016 HASH Consulting Corp. 38
バリデーションはプログラムの前提条件 を確実にするために Copyright © 2016 HASH Consulting Corp. 39
Drupageddon(CVE-2014-3704) Copyright © 2016 HASH Consulting Corp. 40
Drupalのログイン処理のSQL文を調べる 通常時の要求 name=admin&pass=xxxxxxxx&form_build_id=form-xQZ7X78LULvs6SyB9MvufbZh5KXjQYRH S05Jl2uD9Kc&form_id=user_login_block&op=Log+in 通常時のSQL文 SELECT * FROM users WHERE name = 'admin' AND status = 1 nameを配列で指定 name[]=user1&name[]=user2&pass=xxxxxxxx&form_build_id=form-xQZ7X78LULvs6SyB9 MvufbZh5KXjQYRHS05Jl2uD9Kc&form_id=user_login_block&op=Log+in nameを配列にした場合のSQL文 SELECT * FROM users WHERE name = 'user1', 'user2' AND status = 1 文字列リテラルが複数生成される Copyright © 2012-2014 HASH Consulting Corp. 41
IN句生成の便利な呼び出し方だが…
db_queryにてIN句のバインド値を配列にすると…
<?php
db_query("SELECT * FROM {users} where name IN (:name)",
array(':name'=>array('user1','user2')));
?>
IN句の値がプレースホルダのリストに展開される
SELECT * from users where name IN (:name_0, :name_1)
バインド値の配列は以下の様に変形される
array(':name_0'=>'user1', ':name_1'=>'user2'))
Copyright © 2012-2014 HASH Consulting Corp.
42
キー名をつけると キー名をつけてみる(id1, id2) name[id1]=user1&name[id2]=user2 プレースホルダにキー名がつく SELECT * FROM {users} WHERE name = :name_id1, :name_id2 AND status = 1 Copyright © 2012-2014 HASH Consulting Corp. 43
空白付きのキー
キー名に空白をつけてみる
name[1 xxxxx]=user1&name[2]=user2
プレースホルダに空白が含まれる
SELECT * FROM {users} WHERE name = :name_1 xxxxx, :name_2 AND
status = 1
ちぎれたプレースホルダはSQL文の一部
として認識される
プレースホルダには、キー :name_1がないので上記のSQL文呼び出しはエラーになる
array(2) {
[":name_1 xxxxx"] => "user1"
[":name_2"] => "user2"
}
← :name_1 ではない
Copyright © 2012-2014 HASH Consulting Corp.
44
バインド値のつじつまを合わせる
キー名に空白をつけてみる
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の文法違反となる
array(2) {
[":name_2 xxxxx"] => ""
[":name_2"] => "user2"
}
Copyright © 2012-2014 HASH Consulting Corp.
45
SQLインジェクションを試す
キー名に追加のSQL文を書く
name[2 ;SELECT sleep(10) -- ]=&name[2]=user2
プレースホルダの後ろに追加のSQL文が現れる
SELECT * FROM {users} WHERE name = :name_2 ;SELECT sleep(10) -- ,
:name_2 AND status = 1
実際に呼び出されるSQL文
SELECT * FROM users WHERE name = 'user2' ;SELECT sleep(10) -- , 'us
er2' AND status = 1
Copyright © 2012-2014 HASH Consulting Corp.
46
脆弱なソース
// 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
対策版
// 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
Drupalのログイン画面におけるDoS脆弱性(CVE-20149016) Copyright © 2012-2014 HASH Consulting Corp. 49
想定される影響 第三者により、巧妙に細工されたリクエストを介して、 サービス運用妨害 (CPU 資源およびメモリの消費) 状態にされる可能性があります。 http://jvndb.jvn.jp/ja/contents/2014/JVNDB-2014-005632.html より引用 50
巧妙に細工されたリクエスト…とは? 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 100万バイトの パスワード 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
パスワードハッシュ値の計算部分
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
対策版
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
暗黙の型変換に注意 Copyright © 2016 HASH Consulting Corp. 54
MySQL: どうなる: name=‘tana’ + ‘ka’ mysql> SELECT * FROM members WHERE name='tanaka'; +----+--------+-------------------+ | id | name | email | +----+--------+-------------------+ | 8 | tanaka | [email protected] | +----+--------+-------------------+ mysql> SELECT * FROM members WHERE name='tana'+'ka'; どうなる? Copyright © 2016 HASH Consulting Corp. 55
MySQL: こうなる: name=‘tana’ + ‘ka’
mysql> SELECT * FROM members WHERE name='tanaka';
+----+--------+-------------------+
| id | name
| email
|
+----+--------+-------------------+
| 8 | tanaka | [email protected] |
+----+--------+-------------------+
mysql> SELECT * FROM members WHERE name='tana'+'ka';
+----+-----------+---------------------+
| id | name
| email
|
+----+-----------+---------------------+
| 4 | tokumaru | [email protected] |
| 5 | sato
| [email protected]
|
| 6 | yamada
| [email protected]
|
| 8 | tanaka
| [email protected]
|
| 9 | suzuki
| [email protected]
|
+----+-----------+---------------------+
5 rows in set, 8 warnings (0.00 sec)
Copyright © 2016 HASH Consulting Corp.
まさかの
全件一致
暗黙の型変
換が原因
56
MySQLの「暗黙の型変換の罠」 • ‘tana’ + ‘ka’ は ‘tana’ と ‘ka’ の算術加算 • MySQLは、算術加算のオペランドを数値に「暗黙に」型変換する ちなみに浮動小数点数になる) • name = ‘tana’ + ‘ka’ は name=0 と同じ • 列nameが文字列型の場合、name列を数値に変換してから比較する • すなわち、’yamada’ = 0 となる → まさかの ‘yamada’ = ‘tana’ + ‘ka’ Copyright © 2016 HASH Consulting Corp. 57
再(まとめとして) : セキュアコーディングをこう分類したい • 脆弱性を解消する「まさにその場所での対策」 – プレースホルダを用いてSQL文を呼び出す… • 緩和策を実施する – バリデーション – 最小権限 • 前提条件を確認する – 引数チェック・戻り値チェック – 防御的プログラミング • バグの少ない開発に役立つ習慣 – コンパイラのエラーを無視しない – 暗黙の型変換を避ける – … Copyright © 2016 HASH Consulting Corp. 58