[PR]小規模ECサイトに最適なWAF、SiteGuard Lite
徳丸浩の日記
2007年09月24日 変数に型のない言語におけるSQLインジェクション対策に対する考察(5)
_数値項目に対するSQLインジェクション対策のまとめ
一連の議論では、以下の条件におけるSQLインジェクション対策について議論している。
- SQLインジェクション対策において、バインド機構が利用できない(したくない)
- 変数に型のない言語(Perl、PHP、Rubyなど)を使用している
- 数値型の列の場合
この場合の対策としては、以下の二種類が機能する。
- SQL文組み立ての前に、数値としての妥当性検証を行う
- 数値項目もシングルクォートで囲み(クォートし)、文字列リテラルと同様のエスケープを行う
数値項目もクォートする方法
このうち、後者の積極的な推進者として大垣靖男氏がおられる。例えば、以下のような記事
すべての変数をエスケープする対策
この方法はすべてのデータベースに利用できる対策です。文字列,整数などデータ型に関わらず変数すべてを文字列としてエスケープすることにより,SQLインジェクションを100%防ぐことが可能となります。例えば,PostgreSQLのSQL文を生成する場合,以下のようにすべてのパラメータを文字列して処理・生成します。
$sql = "UPDATE user SET name = '".pg_escape_string($_POST['name'])."', age = '".pg_escape_string($_POST['age'])."' WHERE id = '".pg_escape_string($_SESSION['USERID'])."';";
[なぜPHPアプリにセキュリティホールが多いのか?:第5回 まだまだ残っているSQLインジェクション(2ページ目)より引用]
上記の「"', age = '".pg_escape_string($_POST['age'])."' WHERE id = '"」の部分がそれである。age欄が「24」の場合、SQLの関連部分は以下のようになる。
UPDATE user SET name = 'ほげほげ', age = '24' where 【後略】
一方、age欄が「';DROP TABLE user--」の場合は、
UPDATE user SET name = 'ほげほげ', age = ''';DROP TABLE user--' where 【後略】
このようにこのSQLはageという数値項目に、数値でない文字列をセットしようとしているので、実行時にエラーとなる*1が、SQLインジェクションは回避される。
SQLにおける暗黙の型変換の是非
数値をクォートして文字列にすると、SQL実行時には、数値型の列と文字列リテラルとの間に「暗黙の型変換」が発生する。先の例では、age列が整数型だとして、set ... age = '24' ...という式の実行時に、文字列('24')から、数値(24)への暗黙の型変換が発生する。
一般に、プログラミングの分野では「暗黙の型変換」が有害であると言われる場合があるが、SQLの場合はどうだろうか。たとえば、Oracle Technology Network(OTN)には、以下のようなドキュメントがある。
暗黙的なデータ変換と明示的なデータ変換
次の理由から、暗黙的な変換または自動変換ではなく、明示的な変換を指定することをお薦めします。
- 明示的なデータ型変換ファンクションを使用すると、SQL文がわかりやすくなります。
- 暗黙的なデータ型変換(特に列値のデータ型が定数に変換される場合)は、パフォーマンスに悪影響を及ぼす可能性があります。
- 暗黙的な変換はその変換が行われるコンテキストに依存し、どんな場合でも同様に機能するとはかぎりません。たとえば、日時値からVARCHAR2型へ値を暗黙的に変換すると、NLS_DATE_FORMATパラメータに指定されている値によっては、予期しない年が戻される場合があります。
- 暗黙的な変換のアルゴリズムは、ソフトウェア・リリースやOracle製品の変更によって変更されることがあります。明示的な変換を指定しておくと、その動作は将来的にも確実になります。
[Oracle SQLの基本要素より引用]
このように、暗黙の型変換は、実装依存であるため動作が不確実になることや、性能面の不利などで推奨されていないことがわかる。
興味深いデータがある。ockeghem(徳丸浩)の日記 - 数値リテラルをシングルクォートで囲むことの是非を書いて以来、筆者のブログに「ORA-01722」の検索キーワードで訪れた人が累計74人もおられる。同じキーワードにより、Gooleなどで検索してみると、、同エラーコードに対する対処法の質問や、対処法FAQの説明などがいくつもヒットする。FAQができるくらい「暗黙の型変換」にはまる人が多いことになる。筆者のブログへの来場者も、現実に「ORA-01722」のエラーで困り果てた末にやってきて、がっかりして(なんだ、SQLインジェクションの説明か)立ち去った人が大半ではないだろうか。すなわち、現実に暗黙の型変換は、予期しない問題に遭遇する可能性が高く、書法的に推奨されない。
数値をクォートすると性能が悪化するケース
次に性能面ではどうか。筆者自身は、数値をクォートすることで性能劣化するパターンを見つけられていなかった*2が、最近奥 一穂のお仕事ブログに興味深いデータが示された。
鴨志田さんに教えていただいたのですが、MySQL のクエリは数値をクォートしない方が高速になるらしいです。たとえば以下の例では、160万件の整数から4の倍数を数えていますが、数値をクォートしないほうが約50%も高速になっています。
[Kazuho@Cybozu Labs: MySQL の高速化プチBKより引用]
筆者も手元のノートPCで追試を試みたところ、50%もの差はでなかったが、数値をクォートしない方が約20%高速になるという結果が確認できた*3。
また、SQLインジェクション対策に限らず、SQLにおける暗黙の型変換という広い文脈でとらえると、既に報告の通り、インデックスが利用されなくなるために性能が大幅に低下する場合がある。
ではどうしたらよいか
今まで見てきたように、数値をクォートしてエスケープする方法は、数値項目に対するSQLインジェクション対策としては機能するが、副作用が多い。筆者としてはSQLを組み立てる直前での数値チェックをお勧めしたい。以下のような仕様の関数を作ればよいだろう。
- 入力パラメータを数値として妥当性チェックする
- 妥当の場合は数値をそのまま返す
- 妥当でない場合は例外を発生させる
この関数は、pg_escape_stringなどと同じように使える*4ので、置き換えなどもしやすいであろう。先にあげた「暗黙の型変換」のデメリットが解消されるだけでなく、SQL実行前にエラー(例外)にできるので、アプリケーションの信頼性という点でも少し有利であろう。
なお、このエントリーはSQLインジェクション対策のための数値チェックであるが、アプリケーションの信頼性向上のための「入力値検証」は、上記とは独立に実施されることをおすすめする*5。
自作コンパイラの部屋 > Web Application Security(WAS)に関する話題の目次 - SQLインジェクション > 数値項目に対するSQLインジェクション対策のまとめ
*1 ockeghem(徳丸浩)の日記 - 数値リテラルをシングルクォートで囲むことの是非参照
*2 SQLの「暗黙の型変換」で実行速度が遅くなるのはどのような場合か参照
*3 奥氏の環境はMyISAMだが、筆者の環境はInnoDBというエンジンの違い、奥氏はキー指定をしていないが、徳丸はキー指定をしているなどの違いに依存するものと思われる
*4 数値のクォートは外す必要がある
404方面でも絶賛されていたPHP逆引きレシピを購入した。本書はとても丁寧な仕事で素晴らしいと思ったが、セキュリティに関しては若干残念な思いをしたので、それを書こうと思う。 目次は以下のようになっている。 第1章 準備 第2章 PHPの基本構文 第3章 PHPの基本テ
このエントリでは、SQLにおいて「暗黙の型変換」を使うべきでない理由として、具体的な「ワナ」をいくつか紹介します。 数値項目に対するSQLインジェクション対策のまとめにて説明したように、RDBの数値型の列に対してSQLインジェクション対策をする方法として、以下の三..
- https://www.google.co.jp/ ×638
- http://d.hatena.ne.jp/Kango/20110405/1302013056 ×92
- http://www.tokumaru.org/ ×83
- http://d.hatena.ne.jp/ockeghem/20111109/p1 ×71
- http://d.hatena.ne.jp/ockeghem/20090711/p1 ×47
- http://d.hatena.ne.jp/ockeghem/20070502/1178042280... ×27
- http://labs.cybozu.co.jp/blog/kazuho/archives/2007... ×26
- https://www.google.com/ ×14
- http://d.hatena.ne.jp/ockeghem/touch/20111109/p1 ×11
- http://d.hatena.ne.jp/ockeghem/20081101/p1 ×8
- http://d.hatena.ne.jp/ockeghem/20111203/p1 ×6
- http://bakera.jp/ebi/topic/3585 ×5
- http://d.hatena.ne.jp/ockeghem/20111109 ×4
- http://www.tokumaru.org/was/ ×4
- http://d.hatena.ne.jp/Kango/touch/20110405/1302013... ×4
- https://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&... ×2
- https://www.google.co.uk/ ×2
- https://www.google.co.jp/search?num=100&hl=ja&neww... ×2
- http://www.tokumaru.org/yacc/ ×2
- http://www.askapache.com/ ×2
- http://d.hatena.ne.jp/ockeghem/comment?date=201112... ×2
- https://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&... ×1
- https://www.google.com.sg/ ×1
- https://www.google.com.cu/ ×1
- https://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&... ×1
- https://www.google.com.vn/ ×1
- https://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&... ×1
- https://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&... ×1
- https://search.yahoo.co.jp/ ×1
- http://y-ok.com/musashino/ ×1
- http://www.tokumaru.org/pazzle/sudoku.htm ×1
- http://www.sogou.com/ ×1
- http://www.facebook.com/l.php?u=http://www.tokumar... ×1
- http://t.co/u23HN4UOxD ×1
- http://t.co/bM9usVp8ll ×1
- http://sp-web.search.auone.jp/search?q=sql インジェクショ... ×1
- http://search.smt.docomo.ne.jp/result?search_box=変... ×1
- http://search.mobile.yahoo.co.jp/onesearch?p=ORA-0... ×1
- http://search.mobile.yahoo.co.jp/onesearch/?sbox=S... ×1
- http://search.fenrir-inc.com/?q=pdo quote セキュリティ&h... ×1
- http://search.fenrir-inc.com/?q=SQL 条件式 ora-01722&... ×1
- http://search.fenrir-inc.com/?hl=ja&channel=sleipn... ×1
- http://search.fenrir-inc.com/?hl=ja&channel=sleipn... ×1
- http://d.hatena.ne.jp/sonodam/20110407/p5 ×1
- http://d.hatena.ne.jp/ockeghem/comment?date=201111... ×1
- http://d.hatena.ne.jp/ockeghem/comment/20081101/p1... ×1
- http://d.hatena.ne.jp/ockeghem/comment/20081101 ×1
- http://d.hatena.ne.jp/ockeghem/20111203 ×1
- http://d.hatena.ne.jp/ockeghem/20111109/p1?_ga=1.5... ×1
- http://d.hatena.ne.jp/ockeghem/200811 ×1
- http://api.twitter.com/1/statuses/show/40304710720... ×1
- php sql インジェクション pg_escape_string % 対策 ×4 / set escape パラメータ 型変換 ×3 / Parmeter SQLインジェクション 対策 ×3 / sql where 数値ではない ×2 / sqlインジェクション 数値項目 ×2 / ruby sqlインジェクション対策 ×2 / SQL 数値項目 アップデート ×1 / sqlserver シングルクォート 数値 ×1 / sql 数値 シングルクォート ×1 / sqlインジェクション バインド変数 ×1 / sqlインジェクション対策 数値型 ×1 / sql 数値項目に’ ×1 / ruby sql対策 ×1 / pg_escape_string エスケープ インジェクション ×1 / mysql_escape_string デメリット ×1 / SQL @変数 数値型 ×1 / sqlserver 型変換 チェック ×1 / SQL 変数 数値 ×1 / SQL クォート 対策 Oracle ×1 / SQL文 数値型変換 ×1 / SQLインジェクション 数値型 ×1 / SQLインジェクション 数値のみ ×1 / SQLインジェクション 入力項目に ×1 / Ruby SQLインジェクション対策 ×1 / PHP Oracle SQL 数値 シングルクォート ×1 / バインド変数 型変換 ×1 / 数値パラメータもシングルクオート ×1 / エスケープ sql はまる ×1 / インジェクション回避 パラメーター ×1 / すべてのパラメータを文字列としてエスケープする sql ×1 / 数値項目にシングルクオート ×1 / pg_escape_string ×1
[PR]小規模ECサイトに最適なWAF、SiteGuard Lite
HASHコンサルティング株式会社
最近の記事
- 2011年08月30日
- 1. RSSフィードをリダイレクトします
- 2011年07月01日
- 1.
- 2011年03月29日
- 1. PDO/MySQL(Windows版)の文字エンコーディング指定の不具合原因
- 2011年03月22日
- 1. PHP5.3.6からPDOの文字エンコーディング指定が可能となったがWindows版では不具合(脆弱性)あり
- 2011年01月27日
- 1. CSRF対策のトークンをワンタイムにしたら意図に反して脆弱になった実装例
- 2011年01月04日
- 1. escapeshellcmdの危険な実例
- 2011年01月01日
- 1. PHPのescapeshellcmdの危険性
- 2010年10月03日
- 1. 問題点の概要
- 2010年09月27日
- 1. 文字コードに起因する脆弱性を防ぐ「やや安全な」php.ini設定
- 2010年07月25日
- 1. ツッコミSPAM対策で、ツッコミ抜きのRSSフィードを用意しました
- 2010年07月01日
- 1. ぼくがPDOを採用しなかったわけ(Shift_JISによるSQLインジェクション)
- 2010年04月06日
- 1. PROXY(プロキシ)経由でのDNSリバインディングと対策
- 2010年04月05日
- 1. JavaアプレットのDNSリバインディングはJRE側で対策済みだった
- 2010年03月29日
- 1. DNSリバインディングによる無線LANパスフレーズの読み出しに成功
- 2010年03月25日
- 1. DNSリバインディングによるルータへの侵入実験
- 2010年02月22日
- 1. ケータイtwitter(twtr.jp)においてDNS Rebinding攻撃に対する脆弱性を発見・通報し、即座に修正された
- 2010年02月12日
- 1. かんたんログイン手法の脆弱性に対する責任は誰にあるのか
- 2010年01月18日
- 1. iモードブラウザ2.0のXMLHttpRequestでPOSTデータの扱いが困難になった
- 2009年10月19日
- 1. quoteメソッドの数値データ対応を検証する
- 2009年10月14日
- 1. htmlspecialchars/htmlentitiesはBMP外の文字を正しく扱えない
- 2009年10月09日
- 1. htmlspecialcharsのShift_JISチェック漏れによるXSS回避策
- 2009年09月30日
- 1. htmlspecialcharsは不正な文字エンコーディングをどこまでチェックするか
- 2009年09月24日
- 1. SQLの暗黙の型変換はワナがいっぱい
- 2009年09月18日
- 1. 文字エンコーディングバリデーションは自動化が望ましい
- 2009年09月14日
- 1. 既にあたり前になりつつある文字エンコーディングバリデーション
- 2009年08月05日
- 1. 携帯JavaScriptとXSSの組み合わせによる「かんたんログイン」なりすましの可能性
- 2009年03月28日
- 1. IPAは脆弱性の呼び方を統一して欲しい
- 2009年03月27日
- 2009年03月11日
- 1. U+00A5を用いたXSSの可能性
- 2008年12月22日
- 1. JavaとMySQLの組み合わせでUnicodeのU+00A5を用いたSQLインジェクションの可能性