今回はWebアプリの代表的な脆弱性、SQLインジェクションを学ぶわ。仕組みと正しい対策を押さえましょう。
SQLインジェクションって名前は聞くけど、結局どういう攻撃なの?
SQLインジェクションは、入力欄などから不正なSQL文の断片を送り込んで、データベースを操作する攻撃よ。
アプリが利用者の入力をそのままSQL文に組み込んでしまうのが原因ですね。
そのとおり。
たとえばログイン処理で、入力値を文字列連結でSQLに埋め込んでいると危ないの。
どんなふうに悪さされるんですかぁ?
たとえばパスワード欄に ' OR '1'='1 のような文字列を入れられると、条件が常に真になって、認証を回避されてしまうことがあるのよ。
うわっ、パスワード知らなくてもログインできちゃうってこと?
ええ。
さらに悪用されると、データベース内の個人情報を情報漏えいさせられたり、データを改ざん・削除されたりするわ。
では対策はどうすればよいのでしょうか。
入力のチェックだけでよいのですか?
最も確実なのはプレースホルダを使ったバインド機構よ。
SQLの構文と入力値を分けて扱うので、入力値が命令として解釈されなくなるの。
いわゆるプリペアドステートメントですね。
値をパラメータとして安全に渡す仕組みです。
自分で連結する前に、特別な文字を無害にする方法も聞いたことがありますぅ。
それがエスケープ処理ね。
' などSQLで意味を持つ文字を無害な形に変換するの。
ただし漏れが起きやすいので、原則はバインド機構が推奨されるわ。
入力チェックはしなくていいの?
入力値検証も多層防御として大切よ。
加えて、DBのエラーメッセージを利用者に詳しく返さないことも、攻撃者へのヒントを与えない対策になるわ。
アプリがDBに接続する権限を必要最小限にしておくことも被害を抑えますね。
根っこは『入力をSQLの一部にしない』ことなんですねぇ。
確認クイズ
SQLインジェクション対策として最も根本的で有効なものはどれか。
- 利用者に強固なパスワードを設定させる
- プレースホルダを用いたバインド機構でSQL文を組み立てる
- 通信をTLSで暗号化する
- ログイン失敗回数を制限する
こたえを見る
正解: 2. プレースホルダを用いたバインド機構でSQL文を組み立てる
正解はバインド機構(プレースホルダ)。SQLの構文と入力値を分離するため、入力値がSQL命令として解釈されず、注入を根本的に防げる。強固なパスワードやログイン失敗回数制限はパスワード攻撃対策、TLSは通信の盗聴・改ざん対策であり、いずれもSQLインジェクションの本質的対策にはならない。