SQLインジェクション対策はおすみですか?
開発開始時点からのコンサルティングから、公開済みWebサイトの脆弱性検査、
脆弱性発見後の適切な対策まで
トップ 最新 追記
過去の日記

2007-09-05 そろそろ入力値検証に関して一言いっとくか

Webアプリケーション脆弱性対策としての入力値検証について

 Webアプリケーションのセキュリティ対策としての「入力値検証」について色々言われている。セキュアコーディングの基本は入力値検証だといわれたり、さほど重要でないと言われたりしている。本当のところはどうなのだろうか。以下、バイナリデータを扱う場合の多いミドルウェア(Webサーバーなど)と対比しながら、この問題を掘り下げたい。

バイナリデータの場合(≒ミドルウェアの場合)

 バイナリデータでは、入力検証が重要である。少し前にmod_imagefightを取り上げた(画像版サニタイズ言うな(2))ので、ビットマップ画像を例に説明しよう。
 その際に使用したBMP形式の説明を再掲する。
0000:MARK(2) ='BM'
0002:ファイルサイズ(4)             *
0006:予約1(2) =0
0008:予約2(2) =0
000A:ビットマップ開始位置(4)       *(間接的にサイズに関連)
000E:ヘッダサイズ(4) =0x28         *
0012:イメージ横幅(4)               *
0016:イメージ高さ(4)               *
001A:プレーン数(2) =1
001C:ピクセルあたりのビット数(2) 1,4,8,24  *
001E:圧縮形式(4) =0,1
0022:圧縮後のイメージサイズ        *
0026:水平解像度(4)                 *(間接的にサイズに関連)
002A:垂直解像度(4)                 *(間接的にサイズに関連)
002E:使用色数(4)                   *
0032:重要な色数(4)
0036:カラーパレット
ZZZZ:ビットマップ
 ヘッダの中には、サイズに関連する値が多いことに注意されたい。上手上図において、サイズに関連する(可能性のある)ものを「*」により示した。これらの値を検証することは重要である。
 例えば、実際に受け取ったファイルのサイズと、BMPヘッダ中の「ファイルサイズ欄」が矛盾したら処理が継続できない。また、イメージの横幅と高さを鵜呑みにしてメモリを確保していたら、これらに巨大な値を入れるだけで(画像の中身は送らなくても)、アプリケーションは巨大なメモリをアロケートしようと試みるので、簡単にDoS攻撃が成立してしまう。また「ピクセルあたりビット数」が「1,4,8,24」のいずれかになっていることもチェックする必要があるだろう。
 BMPの例に限らず、一般にバイナリデータの形式は、「データ長」に続いて「データ本体」が続く場合が多い。このデータ長に間違ったあるいは巨大なデータが入っていることをチェックしなければ脆弱性の原因となる。「入力データのチェック」が必要となる所以である。
 すなわち、バイナリ形式のデータを扱う上では、

・データの整合性を保証することにより動作を確実にする
・リソース割り当てを適当に制限してDoS耐性を持たせる

などのために、入力の検証は必須なのである。
 また、ここで注目して欲しいことは、BMPの画像イメージの内容まではチェックしないことだ(圧縮されている場合は別)。
 すなわち、入力のチェックといっても、データの中身をチェックするのではなく、いわばデータの構造や枠組みをチェックしていることになる。そりゃそうだろう。TCP/IPでやりとりできるデータに制限があったり(例えば「'」があればエラーになる)、勝手に書き換えられたり(たとえば「;」が「_」に置換される)、勝手に削除される(例えば「<」や「>」があれば削除される)としたら、TCP/IPは使い物にならなくなる。

Webアプリケーションの場合

 Webアプリケーションの場合で考えると、入力データの構造のチェックとしては以下が考えられる。

・HTTPヘッダ(Cookieなど)の形式チェック
・クエリ・ストリングの形式チェック
・POSTデータの形式チェック(application/x-www-form-urlencodedなどの)

 これらは確かに必要だろう。しかし、これらチェックはアプリケーションの役目というよりは、ミドルウェアやライブラリの役目だ。ミドルウェア類からアプリケーションに渡されるデータは、データの中身であって、上記の形式チェックや構文解析は既に終わっている。
 ミドルウェア側の構文解析などがすんでしまえば、入力データがいかなる値であっても、データを受け取った時点で直ちにセキュリティ上問題が起こるわけではない。問題が発生するのは、その値を使う時である(当たり前だ)。
 その例として、クロスサイト・スクリプティング(XSS)やSQLインジェクションなどのインジェクション系脆弱性があり、値を使う時に(出力時に)エスケープなどを行う必要があるのだ。データを使う時にどの文字が問題になるかは、データの使い方(HTML、SQL、・・・)によって変わる。そのため、データを使う直前まで、エスケープなどの処理はできないことになる。

アプリケーションの入力チェックですべきこと


 Webアプリケーションでも入力値のチェックはするべきであるが、それはセキュア・コーディングという意味においてではない。ユーザが間違ったデータを入力した場合にできるだけ早期に誤りを発見して、アプリケーションの信頼性を高めるという、ビジネス要件の意味合いからである。したがって、電話番号とか、価格とか、メールアドレスのように文字種や桁数などが限定される場合には、ぜひその形式になっているかをチェックすべきである。
 しかし、住所欄や掲示板への投稿本文欄など、実質的に文字種を制限できない場合も多い。そのような場合には、入力チェックとしてできることは、せいぜい桁数(文字数)のチェックくらいである。
 すなわち、そもそも入力チェック(文字種チェック)は出来る場合と出来ない場合があり、文字種チェックなどが脆弱性対策に(結果として)役立つ場合もあれば、役立たない場合もある。したがって、Webアプリケーションの場合、入力チェックは根本的な脆弱性対策にはなりえず、「やっておいた方がよい」という保険的な対応にすぎない。

まとめ

 古典的なセキュアコーディングの原則の一つに入力値検証があることから、Webアプリケーションにおいても入力値検証が脆弱性対策の基本であるかのような説明を見かけることが多い。しかしバイナリデータを扱うミドルウェア等の場合、入力データの検証とはデータの枠組みの検査であって、入力データそのものの検査ではない場合が多い。一方、Webアプリケーションにおいて、入力値の検査は入力データそのものの検査を論じる場合が多い。ここにギャップがある。
 (Web)アプリケーションの場合、通常データの枠組みは解析済みであり、データそのものを受け取る。したがって、ミドルウェアなどの場合に比べて入力値検証の重要性は低い。一方、アプリケーションの場合、ビジネス要件に従った入力値検証は重要である。下表にこれらをまとめた。

ミドルウェアアプリケーション
データの枠組みの検査重要重要でない
データそのものの検査不要な場合が多い重要(*1)
(*1) セキュリティの要請ではなく業務要件として

 このように整理すると分かりやすい(上記は大まかな議論であって、もちろん例外はありえる)。
 従来混乱しがちだった「Webアプリケーションのセキュリティ対策における入力値検証」の意味を考える出発点として、新しい視点を提案するものである。

本日のツッコミ(全12件) [ツッコミを入れる]

Before...

別の通りすがり [カラム名なら「"」で括るのが正しいですよ。 カラム名に予約語があったら困るので当然そういう文法が言語に用意されている..]

masa__ [別の通りすがりさん > カラム名なら「"」で括るのが正しいですよ。 恥ずかしながら知りませんでした、ありがとうござい..]

masa__ [フレームを発生させてしまい申し訳ありません。 カラム名のクォートについて調査した結果だけ報告して最後とさせて頂きます..]


2007-09-09 入力値検証について(2)

アプリケーションの先頭で行う入力値検証は業務要件により行うべし

 前回のエントリ徳丸浩の日記 - そろそろ入力値検証に関して一言いっとくか - Webアプリケーション脆弱性対策としての入力値検証についての内容をもう少し突っ込んでみたい。
 このエントリは、幸いにも何人かの人たちの建設的なコメントをいただくことができた。それにより、私自身の考えを整理し、深めることができたように思う。

T.Teradaの日記 - 2007-09-08
"週"記(2007-09-07)

 今回は、入力値検証の中でも、特にアプリケーションの先頭で行う入力値検証として何をすべきかということに焦点を絞って議論を進めたいと思う。
 その前に、まずHTTPの復習から。

HTTPリクエストは申請書にたとえると理解しやすい

 この日記の読者の多くは先刻ご存知だと思うが、HTTPは非常にシンプルなプロトコルである。WebサーバはHTTPリクエストを受付け、HTTPレスポンスを返す。それを延々と繰り返す。HTTPリクエストには、ファイル名に加えて種々のパラメータをセットできる。このパラメータ類を「Webアプリケーションの入力」とここでは呼ぶことにしよう。具体的には、クエリ・ストリング、POSTパラメータ、Cookieなどである。

 HTTPリクエストを発行する際には、通常はHTMLフォーム上で規定された形式に従うが、現実にはどのようなパラメータをどのようにセットすることも呼び出し側の勝手である。ここで、HTTPリクエストを申請書にたとえてみると、申請書の形式は一応HTMLフォームで規定されている。しかし、申請書記入者は、指定の申請書形式に従わずに、項目を勝手に追加したり、申請書指定の形式(文字種や文字数など)を無視して自由に項目を記述することができる。

アプリケーションが申請書を受け付けるかどうかは早期に決定したい

 役所や銀行などで、申請書類を提出すると、まず窓口で、申請書が所定の書式に沿っているかをチェックされ、一箇所でも間違いがあると、つき返される。一方、書式に間違えがなければ、受理され、バックオフィスで処理されることになる。窓口での書式確認は、形式ばっているようにも見えるが、申請書の間違いにバックオフィス側で初めて気がついて、申請書が行ったり来たりする無駄を考えれば、一応の合理性がある。
 これと似たことはアプリケーションにもある。HTTPリクエストに記載されたパラメータ類は、アプリケーションの期待する形式になっているかどうかは保証されていない。仮に、アプリケーションの処理が相当進んでから、たとえば必須項目が足りずに処理が継続できなければ、今までの処理をロールバックして「なかったこと」にしなければならない。場合によっていは、ロールバックができずに、オペレータの手作業により、リカバリーしなければならないケースもあるだろう。現実には、上記は相当低レベルな話であり、アプリケーションは以下のような入力値チェックを「処理に先立って」実施することになる。

・必須項目が揃っているか
・各項目は指定の書式(型、文字数など)に従っているか
・形式が決まっている場合のチェック(電話番号、メールアドレスなど)

 これらのチェックが通れば、申請書は受理され、処理にまわることになる。さて、ここからが本題である。

 申請書に相当するHTTPリクエストが受理される要件は、セキュリティ上の都合ではないはずである。例えば、以下のような会話はどうか。

役人:えーっと、中村さん、住所欄に「'」は使えませんよ。書き直してください。
中村:そう言われても、アパート名がこうなんだからどうしようもないでしょ。
役人:とにかく駄目なものは駄目です。別の文字にしてください(*1)。

(*1)うわ、サニタイズ言うな

 すなわち、申請書が受理されるかどうかの条件は、原則として全て業務要件によって決まるはずである。通常、現実の申請書には、書式が詳しく説明してあり、その条件を満たしているにも関わらず返却されたら、申請者は相当ムカツクはずである。

ケーススタディ

 さて、T.Teradaの日記には以下のコメントがあるが、

徳丸さんの日記は、ユーザがテキストボックスなどで自由に値を入力できる住所などのデータを主に対象としたものだと思う。

 私は、ラジオボタン、チェックボックス、セレクトボックスなどの場合でも、業務要件として入力チェックをすべきだと思う。これは申請書のたとえで言えばこういうことである。
 たとえば、申請書の「性別欄」には、「女」や「男」と文字で記述する場合もあるが、多いのは男の場合は「1」、女の場合は「2}と番号が記載してあって、番号に丸をつけるか、番号を記入欄に記載する。申請書にはその方法が指定されている。ヤカマシい役所であれば、「『男』と書かずに、1に丸をつけてください」と言われるかもしれない。
 Webアプリケーションの場合で言えば、性別欄がラジオボタンになっていて、その値が男の場合は「M」、女の場合は「F」だとする。性別欄が「M」か「F」のいずれかでなければ処理を継続できないわけだから、この値チェックは業務要件として必要である。

 一方、先のエントリで問題になった、任意列でソートできるテーブルの場合はどうか。
 この場合、ユーザの入力は、ソート対象となる列指定である。列の指定方法はアプリケーションの実装として決めればよいわけで、列番号(1,2,3...)でも良いし、表の各項目の論理名であってもよいし、対応するDBの物理的な列名を採用することもできる(前回議論の対象になった方法はコレ)。私自身の好みでいえば、DBの列名を外部にさらすのは色々な意味で抵抗があるので、たとえば列番号を指定してもらって、アプリケーションの内部で列名に変換するようなロジックにするだろう。
 いずれにせよ、「申請書」に書くべき内容はソート対象の列指定であるが、その書式はアプリケーションの要求として決まっているものであって、一種の業務要件としてチェックすべきだということである。列番号を指定するのであれば、整数であることや数値の範囲のチェックが必要であろうし、列の論理名あるいは物理名を指定するのであれば、名前のチェック(文字種ではなく、列名として存在するか)が必要である。これらはいずれもSQLインジェクション対策としては、そこまでやる必要はない。あくまで、アプリケーションを正常に動作させるために必要な条件である。

「システム起源のデータ」をどうするか

 T.Teradaの日記には、Webアプリケーションには「システム起源のデータ」というものがあって、この場合は入力値検証をすべきであると指摘されている。現実のWebアプリケーションに「システム起源のデータ」が存在することを私も認めるものであるが、しかし、HTTPリクエストが必ずしもアプリケーションに制約されないという条件下では、「システム起源のデータ」をHTTPにより受け渡しすることは非常に危険だ。私は「システム起源のデータ」も(広い意味で)ユーザからの入力に限定すべきであると考える。先に述べたソート対象列の指定のその一例である。そして、ユーザからの入力であれば業務要件としてのチェックが可能であるが、そうでないもの(セッションIDなど)は、極力少なくするべきであると思う。この点についてはまた稿をあらためて説明したい。


まとめ

 アプリケーションの先頭で行う「入力値検証」は、従来セキュアコーディングの文脈で語られることの多かったが、現実には業務要件として行うべきものである。そして、業務要件として受付可能なリクエストは、特別なことがない限り処理されるべきであり、逆に処理できないものは業務要件として、入力に制限が掛っているべきである。例えば、メールアドレスに改行が混ざってはいけないというのも、申請書(伝票)の書式として要求できるものであり、現実問題、改行の入ったメールアドレスには(セキュリティ以前に)処理できない。
 さて、業務要件としての入力値検証を実施すれば、結果としてクロスサイト・スクリプティング(XSS)対策やSQLインジェクション対策にもなっているケースは多いが、これらインジェクション系脆弱性対策と、アプリケーションの先頭での入力値検証は別物として考えた方がよいと思う。アプリケーションにはバグはつきものであり、入力値検証が正しく実装されていない場合もある。また、アプリケーションの脆弱性検査や保守をする際に、入力値検査で「検査済み」の項目と、それ以外の項目(入力値でないものも含む)を明確に区別することが難しいことによる。入力値検証が業務要件チェックとして行われている以上、脆弱性対策はそれら値を使う時(出力時)にすべきものとした方が、考え方がシンプルになり、アプリケーションの開発ライフサイクルのトータルで考えれば結局は安上がりになると考える。

本日のリンク元 | 1 | TrackBack(0)

2007-09-15 [JavaScript]ラベルつきbreak文

ループやswitch以外のブロックを脱出するbreak

JavaScriptでは、breakにラベルを指定できて、通常は多重ループを抜ける場合に用いられるような説明がなされていると思う。しかし、ラベル付のbreakは、ループやswitch以外の文を終わらせることもできる(Javaもそう)。
 例えば以下のようなプログラム。

document.writeln("A");
L1: {
    document.writeln("B");
    L2: {
        document.writeln("C");
        break L1;   // L1の文を終わらせるので、D、Eは実行されない
        document.writeln("D");
    }
    document.writeln("E");
}
document.writeln("F");
【実行結果】
A
B
C
F

多重ループを一気に脱出する場合は、それなりに用途を思いつくが、ただの文ブロックを抜けるとなると、限りなくgotoを使っているような感覚を覚える。文ブロック以外に、try/catch/finallyやwith文、if/elseなどでも同様である。

あえて文ブロックをbreakで抜ける用途を強引に考えてみた。ループで配列をサーチするような場合に、対象が見つかった場合と見つからなかった場合で処理を分けたい。以下のように書いてみた。

function search(a, x) {
    L1: {
        for (var i = 0; i < a.length; i++) {
            if (a[i] == x) {
                // 見つかった場合の処理
                alert('見つかった:a[' + i + '] == ' + x);
                break L1;
            }
        }
        // 見つからなかった場合の処理
        alert('見つからなかった:' + x);
    }
    // 共通の後始末(あれば)
}
search([1, 2, 5, 6, 8], 5);    // 見つかる場合の呼び出し例
search([1, 2, 5, 6, 8], 7);    // 見つからない場合の呼び出し例

うわっ、これは駄目だ。こんなへたくそなプログラムは人様には見せられない・・・
 まぁ、こういう場合は、returnを使うんでしょうね。ただ、上記の例にはないが、「共通の後始末」が必要な場合は、ちょっとだけ上記のような書き方をする動機づけになる。try/finallyを使えばすむ話ではあるが。

JavaScript 第5版

追記(2007/09/16 13:20)

「へたくそな」例は僕だったらこう書くでしょうね。

function searchIndex(a, x) {
    for (var i = 0; i < a.length; i++)
        if (a[i] == x)
            return i;
    return -1;
}
function search(a, x) {
    var index = searchIndex(a, x);
    if (index >= 0) {
        // 見つかった場合の処理
        alert('見つかった:a[' + index + '] == ' + x);
    } else {
        // 見つからなかった場合の処理
        alert('見つからなかった:' + x);
    }
    // 共通の後始末(あれば)
}
search([1, 2, 5, 6, 8], 5);    // 見つかる場合の呼び出し例
search([1, 2, 5, 6, 8], 7);    // 見つからない場合の呼び出し例

あまり気の利いたプログラムではないと僕自身思いますが、こういう単純素朴な形なるように一生懸命考えるのが最近の好みです。そして、僕自身は多重ループからの脱出であっても、ラベルつきのbreakは使わないと思います。上記の例は、JavaScriptのトリビア的なネタということで。



自作コンパイラの部屋 > オブジェクト指向プログラム言語としてのJavaScript > ループやswitch以外のブロックを脱出するbreak

本日のツッコミ(全3件) [ツッコミを入れる]

おごちゃん [「深い階層の途中まで抜ける」ってのは、たまに必要になることがあるけれど、たいていは「どこかで設計ミスしてる」ことが多..]

徳丸浩 [おごちゃん、おひさしぶり〜。見ていてくれたんですね。僕も、おごちゃんのブログは見てますよ。 日経mix(懐かしい)で..]

おごちゃん [どもども^^; 最近は... つーか、MIX以後は「言語の仕様なんてどーでもいーじゃん」とか思ってプログラム書いて..]


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 数値のクォートは外す必要がある

*5 アプリケーションの先頭で行う入力値検証は業務要件により行うべし参照

本日のリンク元 | 1 | TrackBack(0)

SQLインジェクション対策はおすみですか?
開発開始時点からのコンサルティングから、公開済みWebサイトの脆弱性検査、
脆弱性発見後の適切な対策まで
トップ 最新 追記