最終更新日:2020年8月13日
SQL インジェクションと対策
SQL インジェクションとは
SQL インジェクションとは、Webアプリケーションのリクエストパラメーターに、「不正な SQL 文」を含めてリクエストを送信し、本来の処理とは異なる命令をデータベースに実行させることができる脆弱性のことです。
SQL インジェクションは、Webアプリケーションの脆弱性の中でも深刻なもので、発見されたら早急に対応が必要です。具体的な被害には以下のようなものがあります。
- 個人情報などの重要情報の漏洩
- 不正なログイン
- データベースの改ざん
- OSコマンドの実行
- サーバーの乗っ取り
最近のセキュリティ事故では、パスワードなどの情報漏洩がよく起きています。決して他人事ではなく、内容も深刻なので確実に脆弱性に対応するようにしましょう。
具体的な攻撃の方法ですが、例えばログイン処理の SQL 文 を以下のように文字列連結で生成していたとします。ここでは PHP の文法で記述します。
"SELECT * FROM LOGIN WHERE ID = '" . $id . "' AND PASSWORD = '" . $password . "';"
ここで、id=yamada, password=pass という値が入力されれば、この SQL 文は以下のように組み立てられるので問題は起きません。
"SELECT * FROM LOGIN WHERE ID = 'yamada' AND PASSWORD = 'pass';"
ですが、ここで、id に以下の値を入力したらどうなるでしょう?password は pass のままとします。
' OR 1 = 1 --
このとき SQL は以下のように組み立てられ、WHERE の条件は常に真となってログインが成功してしまいます。--以降はコメントと扱われるため SQL エラーにもなりません。
"SELECT * FROM LOGIN WHERE ID = '' OR 1 = 1 --' AND PASSWORD = 'pass';"
これが SQL インジェクションのメカニズムです。
SQL インジェクションの対策
SQL インジェクションの根本的な対策は明快で、SQL 生成の際にプレースホルダを利用するようにすることです。
- SQL 文はプレースホルダを利用して作成する
プレースホルダとは、SQL 文の中で可変な項目を後から変更可能なパラメーターとして処理する方法です。先ほどの SQL 文は以下のように記述します(実装により記述方法に違いはあり)。
"SELECT * FROM LOGIN WHERE ID = ? AND PASSWORD = ? ;"
プレースホルダでは、この ? の部分を単純な文字列として扱うので、先ほどの不正なパラメーターが入ったとしても問題なく処理することができます。
プレースホルダには、ライブラリでプレースホルダを実現する「動的プレースホルダ」と、データベース側でプレースホルダを実現する「静的プレースホルダ」があります。
脆弱性を完全に排除できるという点で静的プレースホルダの採用が望ましいです。詳しくは IPA から提供されている「安全なSQLの呼び出し方」を参照してください。
余談ですが、プレースホルダは本来 SQL インジェクションのために利用するものではなく、頻繁に利用する SQL 文を事前コンパイルしてキャッシュしておくことでパフォーマンス向上させるものです。それが、SQL インジェクションにも効果があるということですね。
SQL インジェクションの脆弱性の被害を軽減してくれる保険的対策には以下のものがあります。
- エラーメッセージをそのまま表示しない
- データベース権限を適切に割り当てる
特に一点目はエラーメッセージが攻撃者に手がかりを与えてしまうことになるので注意しましょう。
参考
Webアプリケーションセキュリティに関する記事は、以下のページにまとまっています。ぜひご確認ください。
スポンサーリンク
カテゴリー:Webアプリケーションセキュリティ対策
コメントを残す