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

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

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

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

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

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

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