SQLinjectin

SQLインジェクションとは?【セキュリティ】

ネットワークにおける脆弱性には様々なものがありますが、今回はその中の1つ、SQLインジェクションについて説明していきます。

 

SQLインジェクションとは

SQLインジェクションとは、意図しないSQL文を実行させ、データベースを不正に操作する攻撃方法です。

Webサービスの多くは、PostgreSQLなどのデータベースを利用することが多いかと思いますが、そういったデータベースに対してデータを入れたり取得したり、新しいテーブルを作ったりといった操作を行うための言語がSQLです。

例えば、次のようなSQL文があるとします。

SELECT * FROM users WHERE name = '入力値'

これは、usersというテーブルから、入力したnameに合致する行を取得するという文です。

通常であれば、name = 'bob'のようにしてボブのデータを取得する、といったように利用しますが、ここで攻撃者が悪意のあるコマンドを入力したとしましょう。

例えば'hoge' OR 'hoge' = 'hoge'といった値を入力したとします。

この場合、SQL文は次のようになります。

SELECT * FROM users WHERE name = 'hoge' OR 'hoge' = 'hoge’

この場合、後ろの'hoge' = 'hoge'trueになります。

ここで、ORは論理和を表すコマンドで、両方あるいはどちらか片方が真であれば真を返します。

当然のことながらこの場合trueを返すので、上記のSQL文はnameにある情報をすべて返してしまうことになります。

このようにして、攻撃者はデータベースから情報を抜き取ったり、悪意のある変更を加えることが可能となってしまいます。

 

対策

対策方法としては、入力された値をそのままSQL文に入れるのではなく、事前に入力値チェックを徹底することが効果的です。

名前であれば、英字のみ許可するだとか、パスワードや番号であれば桁数を確かめることで意図しないSQL文を入力されることを防ぐことができます。

また、プリペアドステートメントを利用する方法もあります。

プリペアドステートメントとは、プレースホルダという値を入れておく場所をあらかじめ決めておき、そこに入力データを当てはめる機能です。

PHPで記述すると以下のようになります。

String name = '入力値';
$dbc = pg_connect("dbname=hoge_db");  // データベース接続

// 値を埋め込む前の形のSQL文をコンパイルして構文を確定する
$result = pg_prepare($dbc, "my_query", 'SELECT * FROM users WHERE name = $1');

// $1の場所に入力値を埋め込んで実行
$result = pg_execute($dbc, "my_query", array(name));

こうすることで、入力値は数値や文字列として埋め込まれるため、特殊記号などが含まれていても全て文字列として扱われるため意図しない実行文にはなりません。

 

SQLインジェクションも有名な攻撃手法ですので、データベースを扱う場合は必ず対策しておきましょう!

XSS(クロスサイトスクリプティング)とは?【セキュリティ】