SQLインジェクション対策は万全ですか?

By uchida - 09/04/22 - このエントリをはてなブックマークに追加このエントリをYahoo!ブックマークに追加このエントリをdel.icio.usに追加このエントリをFC2ブックマークに追加

SQLインジェクションとは

SQLインジェクションとはサイトが想定していないSQL文を第3者に実行されてしまう脆弱性のことです。
データの漏洩や改ざんをされる恐れがあるので非常に危険です。
近年、この虚弱性について認知されるようになりましたが、被害の報告は絶えません。
 
なぜSQLインジェクションの虚弱性を組み込んでしまうのでしょうか?
原因として以下のことが考えられます。
 
・ 未対策のコードを使い回している。
・ 開発者のセキュリティに関する知識不足
・ ソースコード監督者の不在
 
近年、世界的に大規模な被害を受けているといわれています。
これから作るサイトはもちろんのこと、過去に作成したものまでしっかり対応しなくてはいけません。
他の案件からソースを再利用する時などはツイツイ忘れがちに成りやすいですので注意しましょう。
SQLインジェクション対策はセキュリティ対策の中でも比較的簡単に対策をすることができますので、これを機にすべてのソースを見直してみましょう。
 

SQLインジェクションの仕組み

SQLインジェクションはアプリケーションが入力値を適切にエスケープしないままSQL中に展開することで発生します。
会員情報を取得するために以下のSQLを実行するとします。
 

SELECT * FROM user WHERE name = '(入力値)';

 
この入力値に「’ OR ‘h’ = ‘h」と入力するとどうなるでしょう。
 

SELECT * FROM user WHERE name = '' OR 'h' = 'h';

 
nameが空もしくは「h」が「h」の条件に含まれるレコードを取得するとなり、nameというカラムの条件は意味を持たなくなりますので、すべての会員情報を取得してしまいます。
この対策として、「’」を 「”」にエスケープすることにより回避することができます。しかし、バイナリデータや文字エンコードなどにより、この単純なエスケープを逃れてハッキングされる恐れがあります。
多くのプログラム言語には、ただしくエスケープする関数が用意されていますので、そちらを使用するようにしてください。
 

対策はどうすれば良いか

本稿はPHPを例にあげ、SQLインジェクション対策について解説します。
 
まず、PHPにはpg_escape_stringという関数が用意されています。
過去にSQLインジェクションを回避する関数が用意されているものもありますが、それらは不完全ですのでpg_escape_stringを使用してください。
 
入力値をこの関数を使ってエスケープするのですが、全てのパラメータに行ってください。
なぜかというと、どこから値が入力されるか分からないからです。ですので全てに対策することで、悩むこともなくなりますので、安全で工数も最終的に削減できます。
 
次に全てのパラメータを文字列として扱うようにしてください。SQLを「;」で終了できなくするためです。
 

SELECT * FROM user WHERE key = (入力値);

 
これに「0; DELETE FROM user; 」と入力するとどうなるでしょう。
 

SELECT * FROM user WHERE key = 0 ; DELETE FROM user; 

 
となり、全ての会員情報が削除されてしまいます。
ですので、数値型であったとしても必ず文字列として扱いましょう。
 

SQLクエリを全て再確認する

既にSQLインジェクションの脅威は世の中に浸透しています。それでも被害の報告が耐えないのは対策漏れがあることです。
一つの対策は簡単でも全てのソースコードをチェックするのは大変です。
しかし、こればかりは黙視することがもっとも確実です。
 
SQLを実行する「exec()」や「fetchAll()」の関数をgrepで洗い出し、社内にある虚弱性のある全てのコードを廃絶しましょう。
 

参考

Webサイトのセキュリティ診断:傾向分析レポート2008
減らないSQLインジェクション脆弱性