例えば以下のようなフォームがあったとします。
ボタンを押すと Edit1 の内容で like 検索するというものです。
procedure TForm1.Button1Click(Sender: TObject); begin if Query1.Active then Query1.Close; Query1.DatabaseName := 'C:\Program Files\Common Files\CodeGear Shared\Data'; Query1.SQL.Text := 'SELECT * FROM animals.dbf ' + 'WHERE (NAME like "%' + Edit1.Text + '%") AND (AREA = "South America")'; Query1.Open; end;
AREA を "South America" に限定しているので、空文字を検索しても最大で 2 件しか表示されません。
しかしながらこのコードには問題があります。Edit1 に
%") or (NAME <>"
と入力して検索してみると…
AREA が "South America" でないものも列挙されてしまいます。これが SQL インジェクション の簡単な例です。SQL インジェクションを防止するには、パラメータクエリを使います。
※ 他の処理系では "プリペアドステートメント" とか "静的プレースホルダ" と呼ばれています。
procedure TForm1.Button1Click(Sender: TObject); begin if Query1.Active then Query1.Close; Query1.DatabaseName := 'C:\Program Files\Common Files\CodeGear Shared\Data'; Query1.SQL.Text := 'SELECT * FROM animals.dbf ' + 'WHERE (NAME like :_NAME) AND (AREA = "South America")'; Query1.ParamByName('_NAME').AsString := '%' + Edit1.Text + '%'; Query1.Open; end;
このコードでは、
SQL インジェクションは発生しません。
本サイトでは、SQL で Where 句の条件を外部入力するようなサンプルでは ParamByName() でパラメータを渡すコードを書いています。Q&A サイトでも、ParamByName() を使ったコードで回答するように心掛けています。
See Also:
[SQL インジェクション (Wikipedia)]
http://ja.wikipedia.org/wiki/SQL%E3%82%A4%E3%83%B3%E3%82%B8%E3%82%A7%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3
[問い合わせでパラメータを使用する (DocWiki)]
http://docwiki.embarcadero.com/RADStudio/ja/%E5%95%8F%E3%81%84%E5%90%88%E3%82%8F%E3%81%9B%E3%81%A7%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B
[デバッグしやすい SQL の書き方]
http://ht-deko.minim.ne.jp/delphiforum/?vasthtmlaction=viewtopic&t=1163
[SQL のパフォーマンスを低下させないためには?]
http://ht-deko.minim.ne.jp/delphiforum/?vasthtmlaction=viewtopic&t=1164
|