リテラルとSQLインジェクション(安全なSQLの呼び出し方)

安全な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呼び出しを実現するには、パラメータを正しくリテラルとして展開することが必要。

具体的には以下を実施する。
・ 文字列 リテラルに対しては、エスケープすべき文字をエスケープすること
・ 数値リ テラルに対しては、数値以外の文字を混入させないこと

参考

安全なSQLの呼び出し方

コメント

タイトルとURLをコピーしました