SQLインジェクション
Webサイトを作成する場合、データベースを使用することがあります。WordPressなどのCMSを利用してWebサイトを作成する場合も、制作者は意識していなくても裏ではデータベースが使われています。例えば、ブログの記事、コメントの内容、ユーザーの情報などがデータベースに格納されています。
SQLとは、データベースを制御するためのプログラム言語のことで、SQLインジェクションではSQLの命令を悪用して、データベースの情報を不正に盗み見たり改ざんしたりします。
SQLインジェクションによる脅威
SQLインジェクションによって次のような脅威が発生します。
個人情報の漏えい
SQLインジェクションによる攻撃を受けると、データベースに記録されている個人情報や機密情報が漏えいしてしまう恐れがあります。例えば、会員制サイトならば会員のIDやパスワード、住所などが不正に取得されてしまうこともあります。SQLインジェクションによる攻撃では、特定のユーザーだけではなく全ユーザーの情報が流出してしまうこともあり、被害が大きくなってしまいます。
情報の改ざん
SQLインジェクションによる攻撃では、情報の改ざんなどが行われることもあります。Webページの情報や登録されている個人情報などを改ざんや消去したりします。また、サイトを乗っ取りや、マルウェアを仕掛けてページを開いた利用者に感染させるなどのケースもあります。
SQLインジェクションの仕組み
例えば、ユーザーがログインするための認証を行うために、SQLによって次のようなコードを書いたとします。
SELECT * FORM users WHERE id = '$id' AND password = '$pw';
SQLのコードについて簡単に説明すると、「id = ‘$id’」の部分で入力フォームのID欄に入力された値($id)を受け取り、 「password = ‘$pw’」の部分で入力フォームのパスワード欄に入力された値($pw)を受け取っています。そして、データベースの中の「users」というテーブルにこれらと同じ情報があるかどうかを確認します。
正規のユーザー名が「abc」、パスワードが「1234」だったとします。
このとき、「$id = abc」「$pw = 1234」という情報がSQLに渡されたならば、データベースの中の「users」というテーブルに格納されている情報と一致し、この後にログインなどの処理が実行されます。
この情報をSQLのコードに当てはめると次のようになります。
SELECT * FORM users WHERE id = 'abc' AND password = '1234';
しかし、このときに「$id = abc」「$pw = ‘ OR A’ = ‘A」という情報がSQLに渡されるとどうなるでしょうか。SQLのコードに当てはめてみると次のようになります。
SELECT * FORM users WHERE id = 'abc' AND password = '' OR 'A' = 'A';
この例では「$id」には問題ありませんが、パスワードの部分でおかしな状況が発生しています。本来なら「password = ‘$pw(入力されたパスワード)’」となってなければならない部分が、入力された値によって「password = ” OR ‘A’ = ‘A’」となってしまっています。
パスワードの欄は引用符(’)ですぐに閉じられ、その後に「OR ‘A’ = ‘A’」と入力されています。このプログラムを日本語に訳してみると「または、A = A」となります。つまり、OR(または)の後ろは常に「真」となり、コードが実行されてしまいます。
これがSQLインジェクションによる攻撃の基本となります。
SQLインジェクション対策
SQLインジェクションを防ぐためには次のような対策方法があります。
プレースホルダを使う
SQL文の組み立てはプレースホルダを使います。プレースホルダとは、上記の例でいうと「$id」や「$pw」の部分の仮の記号を入れておき、その部分に後から値を割り当てる仕組みです。この仕組みを使うことで、プレースホルダに割り当てられた値は単純な文字列として扱われます。上記の例では「$pw = ‘ OR A’ = ‘A」と入力されていましたが、シングルクォート(’)も文字列として扱われるため、攻撃を防ぐことができます。
エラーメッセージを非表示にする
プログラムがエラーとなったときのエラーコードは画面に表示させないようにします。エラーコードに含まれるメッセージには、データベースのテーブル名やカラム名、実行しようとしているSQL文などが表示されることもあります。これにより、攻撃の糸口となってしまうこともあるため、プログラムやサーバーの設定でエラーコードを表示させないようにします。