SQLite インジェクション
もしあなたのサイトがユーザーによるWebページ経由の入力を許可し、その入力内容をSQLiteデータベースに挿入する場合、あなたはSQLインジェクションと呼ばれるセキュリティ問題に直面します。この章では、このような状況の発生を防ぎ、スクリプトとSQLite文の安全性を確保する方法を説明します。
インジェクションは通常、ユーザー入力を要求するときに発生します。たとえば、ユーザーに名前の入力を求めたのに、ユーザーがSQLite文を入力した場合、その文が知らないうちにデータベース上で実行されます。
ユーザーが提供するデータを決して信頼せず、検証済みのデータのみを処理してください。このルールはパターンマッチングによって実現されます。次の例では、ユーザー名 username は英数字またはアンダースコアに制限され、長さは8〜20文字でなければなりません。必要に応じてこれらのルールを変更してください。
if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)){
$db = new SQLiteDatabase('filename');
$result = @$db->query("SELECT * FROM users WHERE username=$matches[0]");
}else{
echo "username not accepted";
}
この問題を示すために、次の抜粋を考えてみましょう:To demonstrate the problem, consider this excerpt:
$name = "Qadir'; DELETE FROM users;";
@$db->query("SELECT * FROM users WHERE username='{$name}'");
関数呼び出しは、ユーザーテーブルから name 列がユーザー指定の名前と一致するレコードを取得するためのものです。通常、$name英数字またはスペースのみを含みます。たとえば、文字列 ilia などです。しかし、ここでは $name にまったく新しいクエリが追加されています。これにより、データベースへのこの呼び出しは壊滅的な問題を引き起こします:注入された DELETE クエリが users のすべてのレコードを削除します。
クエリのスタックや単一の関数呼び出しでの複数クエリの実行を許可しないデータベースインターフェースも存在します。スタッククエリを試みると呼び出しは失敗しますが、SQLite と PostgreSQL ではスタッククエリが可能で、つまり1つの文字列内で提供されるすべてのクエリが実行され、深刻なセキュリティ問題を引き起こす可能性があります。
SQL インジェクションの防止
スクリプト言語(PERL や PHP など)では、すべてのエスケープ文字を巧妙に処理できます。プログラミング言語 PHP は文字列関数を提供します。SQLite3::escapeString($string)とsqlite_escape_string()SQLite にとって特別な入力文字をエスケープします。
注意:使用する関数sqlite_escape_string()の PHP バージョン要件は次のとおりです:PHP 5 < 5.4.0。
PHP 5 >= 5.3.0、PHP 7 などのより高いバージョンでは、上記の関数を使用します:
SQLite3::escapeString($string);//$string为要转义的字符串
以下の方法は最新バージョンの PHP ではサポートされていません:
if (get_magic_quotes_gpc())
{
$name = sqlite_escape_string($name);
}
$result = @$db->query("SELECT * FROM users WHERE username='{$name}'");
エンコードによりデータの挿入は安全になりますが、それは単純なテキスト比較になります。クエリ内で、バイナリデータを含む列に対して、LIKE句は使用できません。
addslashes() は SQLite クエリで文字列を引用するために使用すべきではないことに注意してください。データを取得する際に奇妙な結果を引き起こす可能性があります。
その他の拡張