MySQL-およびSQLインジェクション
Webページからユーザー入力を取得してMySQLデータベースに挿入すると、次のようなセキュリティの問題が発生する可能性があります。 SQL Injection。この章では、これを防ぐ方法と、スクリプトとMySQLステートメントを保護する方法について説明します。
SQLインジェクションは通常、ユーザーに名前などの入力を求めるときに発生し、名前の代わりに、データベースで無意識のうちに実行するMySQLステートメントをユーザーに提供します。
ユーザーから提供されたデータを決して信頼せず、検証後にのみこのデータを処理してください。原則として、これはパターンマッチングによって行われます。次の例では、ユーザー名は英数字とアンダースコア、および8〜20文字の長さに制限されています。必要に応じてこれらのルールを変更してください。
if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)) {
$result = mysql_query("SELECT * FROM users WHERE username = $matches[0]");
} else {
echo "username not accepted";
}
この問題を実証するために、次の抜粋を検討してください。
// supposed input
$name = "Qadir'; DELETE FROM users;";
mysql_query("SELECT * FROM users WHERE name = '{$name}'");
関数呼び出しは、usersテーブルからレコードを取得することになっています。ここで、name列はユーザーが指定した名前と一致します。通常の状況では、$ nameには英数字とおそらくスペースのみが含まれます。しかし、ここでは、まったく新しいクエリをに追加することによって$name、データベースへの呼び出しは災害に変わります。挿入されたDELETEクエリは、ユーザーからすべてのレコードを削除します。
幸い、MySQLを使用している場合、 mysql_query()関数では、1回の関数呼び出しでクエリをスタックしたり複数のクエリを実行したりすることはできません。クエリをスタックしようとすると、呼び出しは失敗します。
ただし、他のPHPデータベース拡張機能( SQLite そして PostgreSQL、スタッククエリを問題なく実行し、1つの文字列で提供されるすべてのクエリを実行し、深刻なセキュリティ問題を引き起こします。
SQLインジェクションの防止
PERLやPHPなどのスクリプト言語では、すべてのエスケープ文字をスマートに処理できます。PHP用のMySQL拡張機能は機能を提供しますmysql_real_escape_string() MySQLに固有の入力文字をエスケープします。
if (get_magic_quotes_gpc()) {
$name = stripslashes($name);
}
$name = mysql_real_escape_string($name);
mysql_query("SELECT * FROM users WHERE name = '{$name}'");
LIKE Quandary
LIKEの問題に対処するには、カスタムエスケープメカニズムでユーザー指定の%文字と_文字をリテラルに変換する必要があります。使用するaddcslashes()、エスケープする文字範囲を指定できる関数。
$sub = addcslashes(mysql_real_escape_string("%something_"), "%_");
// $sub == \%something\_
mysql_query("SELECT * FROM messages WHERE subject LIKE '{$sub}%'");