SQLインジェクションについてまとめています。
SQLインジェクションとはウェブサイトの脆弱性を突いた攻撃
SQLインジェクションとは、 操作にSQLと呼ばれる言語を用いるタイプのデータベースを使用するアプリケーションに対し、 その入力に本来入力としては使われることが想定されていないSQL文を挿入すること
参考) JPNIC
具体的には、ウェブサイトのユーザ登録画面などの入力フォームに、SQLコードを特殊な方法で入力することで、サーバ上で意図しないSQL文を発行させる不正な攻撃方法です。SQLインジェクションにより、データベース上の情報が抜き取られたり、改ざんされたり、データが削除されてしまうケースがあります。
SQLインジェクションを体験できるウェブページがあります。あえて脆弱性があるままの状態にしてあり、入力フォームに不正なコードを入力することでSQLインジェクションを体験することができます。
フォームに以下のような攻撃用の文字列を入力すると、全データが取得できてしまいます。
aiueo' or 'A'='A
内部的には、以下のようにフォームに指定されたidに応じたデータを返す構成になっています。
SELECT * FROM user WHERE id='aiueo'
しかし、攻撃用の文字列を入力すると、内部的に以下のSQLが実行されてしまうんですね。
SELECT * FROM user WHERE id='aiueo' or 'A'='A'
「or ‘A’=’A’」という条件が付与されることで、WHERE句の条件は「常に真」となり、全データが抽出されてしまいます。
mysql> select * from departments where dept_no='d001'; +---------+-----------+ | dept_no | dept_name | +---------+-----------+ | d001 | Marketing | +---------+-----------+ 1 row in set (0.00 sec) mysql> select * from departments where dept_no='d001' or 'A'='A'; +---------+--------------------+ | dept_no | dept_name | +---------+--------------------+ | d009 | Customer Service | | d005 | Development | | d002 | Finance | | d003 | Human Resources | | d001 | Marketing | | d004 | Production | | d006 | Quality Management | | d008 | Research | | d007 | Sales | +---------+--------------------+ 9 rows in set (0.00 sec)
SQLインジェクションの対策
SQLインジェクションには、WAFの導入やアプリケーションでの入力値のサニタイジングなどの対策が有効です。
【関連記事】
▶【入門】SQLのインジェクション対策とは?概要や使い方を解説!
ここでは、サニタイジングについて解説します。
入力値のサニタイジング
入力値として、「d001」のような文字列が想定されている箇所に、「d001′ union select emp_no, fi rst_name from employees limit 10」という文字列を入力すると想定外のSQLを実行させることができてしまいます。
この場合、データベースにシングルクォートをそのまま渡してしまうと、想定外の動作を起こしてしまいます。このような文字列を無効化するのがサニタイズです。
# 入力値=d001 mysql> select * from departments where dept_no='d001'; +---------+-----------+ | dept_no | dept_name | +---------+-----------+ | d001 | Marketing | +---------+-----------+ 1 row in set (0.00 sec) # 入力値=d001' union select emp_no, first_name from employees limit 10 mysql> select * from departments where dept_no='d001' union select emp_no, fi rst_name from employees limit 10; +---------+-----------+ | dept_no | dept_name | +---------+-----------+ | d001 | Marketing | | 10001 | Georgi | | 10002 | Bezalel | | 10003 | Parto | | 10004 | Chirstian | | 10005 | Kyoichi | | 10006 | Anneke | | 10007 | Tzvetan | | 10008 | Saniya | | 10009 | Sumant | +---------+-----------+ 10 rows in set (0.05 sec)
サニタイジングとは、Webアプリケーションにおけるセキュリティ対策の1つです。 SNSや掲示板から投稿された文字列に含まれる有害な文字・文字列を検知して無害化することをいいます。
参考)ITトレンド
なお、エンジニアへの指示として伝える場合、厳密な意味では「サニタイジング」は曖昧な言葉です。「変なコードが入ってきても大丈夫なようにしておいて」と伝えるようなもの。
具体的な対策としては、以下を施すことになります。
- バリデーション(入力値の検証)
- 表示や入力時のエスケープ処理
- SQLの動的生成を廃止して、バインド機構を使用
参考)「サニタイジングして」は禁句、曖昧過ぎるセキュリティー用語 | 日経クロステック(xTECH)
上記のSQLの場合、バリデーションをおこなって入力値からシングルクォートを排除することで、内部的には以下のSQLが実行されることになります。結果は、空となります。
# 入力値をバリデーションして、シングルクォートを無効化した例 mysql> select * from departments where dept_no='d001 union select emp_no, first_name from employees limit 10'; Empty set (0.00 sec)
エスケープ処理では、SQLとして実行されると誤動作を起こす可能性がある文字をエスケープ文字(バックスラッシュなど)でエスケープします。
# 入力値のシングルクォートをバックスラッシュでエスケープした例 mysql> select * from departments where dept_no='d001\' union select emp_no, first_name from employees limit 10'; Empty set (0.00 sec)
DBMSによっては、PHPやC++などの開発用ライブラリにバインド機構が用意されています。バインド機構は、SQLを動的生成することなく、あらかじめクエリを予約(プリペアドステートメント)し、あとからプレースホルダにバインド値を付与します。
不正文字の排除などは、バインド機構を組み込んだライブラリがおこなってくれるため、アプリケーション側でSQLインジェクションの対応をする負荷はなくなります。ただし、言語によってはバインド機構が用意されていないDBMSもあるので注意が必要です。
まとめ
- SQLインジェクションは、ウェブアプリの入力フォームに特殊コードを入力して、意図しないSQLを内部で実行させる攻撃方法
- SQLインジェクション対策には、WAF導入やサニタイジングが有効
- サニタイジングには、入力値のバリデーションやエスケープ処理、バインド機構でのSQL実行などがあげられる