「安全なSQLの呼び出し方」は、「安全なウェブサイトの作り方」で取り合げた9種類の脆弱性のうち、特に SQLインジェクションについて説明したものである。
この記事は「安全なSQLの呼び出し方」を読んで、自分なりに解釈したものになる。
セキュリティについて勉強したい人は「安全なSQLの呼び出し方」を読むほうがいい。
「安全なSQLの呼び出し方」では、SQLインジェクションの具体的な対策も盛り込まれている。
前回のSQLインジェクション(安全なウェブサイトの作り方)で、プレースホルダ(orエスケープ処理)が有効だと学んだので、その具体策となるだろう。
今回は、SQLインジェクションが発生する原理と関係が深い、リテラルについて学ぶ。
1.リテラルとSQLインジェクション
リテラルって何?って人はちょっと待って。 ちゃんと下のほうに説明あるから。 SQLインジェクションって何?って人はここをご覧ください。
SQL文の構造
SQL文の構造のおさらい。 例えば、この SQL文における要素について考えてみる。
SELECT a,b,c FROM atable WHERE name=’YAMADA’ and age>=20
この SQL文を構成する要素は以下。
キーワード:SELECT FROM WHERE AND
演算子:= >= ,
識別子:a b c atable name age
リテラル:’YAMADA’ 20
リテラルとは
リテラルとは、ソースコード中に直接記述した数値や文字列のこと。
定数ともとれるが、constなどの定数と区別するため、リテラルと呼ぶべき。
上記の例だと、リテラルは「’YAMADA’」「20」であった。
この「’YAMADA’」のことを文字列リテラルと呼び、「20」を数値リテラルと呼ぶ。
他にも論理値リテラル、日時リテラルなどがある。
数値リテラルの例。
20
-170
3.14159
6.0221415E+23
文字列リテラルの例。
‘情報処理推進機構’
‘052312’
‘O”Reilly’
日時リテラルの例。
DATE ‘2009-11-04′
TIME ’13:59:26’
それぞれ見ていこう。
文字列リテラルのエスケープ(日時リテラルも)
文字列リテラルや日時リテラルは全体をシングルクォートで囲んで記述します。これをクォートするといいます。
クォートするって言うのか、初めて知った。
ただし、クォートする文字列内にシングルクォートが現れる場合は、文字としてのクォートかリテラルの終端としてのクォートなのかを区別しないとならない。
文字としてクォートが現れる場合は、そのシングルクォートの前にシングルクォートを記述したらいい。
クォートの例。
‘O’Reilly’ ×
‘O”Reilly’ 〇
数値リテラル
数値リテラルはクォートしないため、文字列リテラルのエスケープに相当する処理はありません。
つまり、シングルクォートで囲まなくていいってこと。
数値リテラルは、数値または符号(プラス、マイナス)で始まり、数字以外の文字が出現したその直前までの文字ということになる。
SQLインジェクションの原因
SQLをアプリケーションから利用する場合、SQL文のリテラル部分をパラメータ化することが一般的です。パラメータ化された部分を実際の値に展開するとき、リテラルとして文法的に正しく文を生成しないと、パラメータに与えられた値がリテラルの外にはみ出した状態になり、リテラルの後ろに続く文として解釈されることになります。
むずかしい・・・
とりあえず、例を見ていく。
文字列リテラルに対するSQLインジェクション
以下のような文字列があったとする。
$q = “SELECT * FROM atable WHERE id=’$id'”;
ここで $id に以下の値を与える。
‘;DELETE FROM atable–
パラメータを展開した後の SQL文は以下となる。
SELECT * FROM atable WHERE id=”;DELETE FROM atable–‘
SELECT文の後ろにDELETE文が追加され、データベースの内容がすべて削除されてしまう。
「–」以降はコメントとして無視される。
このように、SQL文の文字列リテラルをパラメータ化しているときに、そこに別のSQL文の断片を含ませることで、元のSQL文の意味を変更できる場合がある。
これがSQLインジェクションの脆弱性と呼ばれている。
数値リテラルに対するSQLインジェクション
数値リテラルについては、PerlやPHPなど、変数に型のない言語を使用している場合に注意が必要です。アプリケーション開発者は変数に数値が入っているつもりでも、数値以外の文字が入力された場合、変数に型のない言語では、それを文字列として扱ってしまいます。
型宣言のないPHPなどは、数値のみが入っているつもりでも、DELETEなどのSQL文が入ってるかもしれないから注意と。
SQLインジェクションの原理は上と一緒。
安全なSQL呼び出しの要件
このように、安全なSQL呼び出しを実現するには、パラメータを正しくリテラルとして展開することが必要。
具体的には以下を実施する。
・ 文字列 リテラルに対しては、エスケープすべき文字をエスケープすること
・ 数値リ テラルに対しては、数値以外の文字を混入させないこと
コメント