SQLite-インジェクション

Webページからユーザー入力を取得し、それをSQLiteデータベースに挿入すると、SQLインジェクションと呼ばれるセキュリティ問題が発生する可能性があります。 この章では、これを防ぎ、スクリプトとSQLiteステートメントを保護する方法を学びます。

通常、インジェクションは、ユーザーに名前などの入力を求めるときに発生します。名前の代わりに、ユーザーが知らないうちにデータベースで実行するSQLiteステートメントを提供します。

ユーザーが提供したデータを信頼せず、検証後にのみこのデータを処理します。原則として、これはパターンマッチングによって行われます。 次の例では、ユーザー名は英数字とアンダースコアに制限され、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";
}

問題を実証するために、この抜粋を考慮してください-

$name = "Qadir'; DELETE FROM users;";
@$db->query("SELECT* FROM users WHERE username = '{$name}'");

関数呼び出しは、名前列がユーザーによって指定された名前と一致するユーザーテーブルからレコードを取得することになっています。 通常の状況では、 $ name には英数字と、おそらく文字列iliaなどのスペースのみが含まれます。 ただし、この場合、まったく新しいクエリを$ nameに追加すると、データベースへの呼び出しは災害に変わります。注入されたDELETEクエリは、ユーザーからすべてのレコードを削除します。

単一の関数呼び出しでクエリのスタックや複数のクエリの実行を許可しないデータベースインターフェイスがあります。 クエリをスタックしようとすると、呼び出しは失敗しますが、SQLiteとPostgreSQLはスタッククエリを喜んで実行し、1つの文字列で提供されるすべてのクエリを実行し、深刻なセキュリティ問題を引き起こします。

SQLインジェクションの防止

PERLやPHPなどのスクリプト言語では、すべてのエスケープ文字をスマートに処理できます。 プログラミング言語PHPは、SQLite専用の入力文字をエスケープする関数* string sqlite_escape_string()*を提供します。

if (get_magic_quotes_gpc()) {
   $name = sqlite_escape_string($name);
}
$result = @$db->query("SELECT * FROM users WHERE username = '{$name}'");

エンコードによりデータを安全に挿入できますが、クエリ内の単純なテキスト比較と LIKE 句は、バイナリデータを含む列では使用できなくなります。

注意-* addslashes()*は、SQLiteクエリの文字列を引用するために使用しないでください。データを取得すると、奇妙な結果につながります。