Mysql-sql-injection

提供:Dev Guides
移動先:案内検索

MySQL-およびSQLインジェクション

Webページからユーザー入力を取得し、それをMySQLデータベースに挿入すると、* SQLインジェクション*として知られるセキュリティ問題が発生する可能性があります。 この章では、これを防ぎ、スクリプトと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()*関数は、単一の関数呼び出しでのクエリのスタックまたは複数のクエリの実行を許可しません。 クエリをスタックしようとすると、呼び出しは失敗します。

ただし、 SQLitePostgreSQL などの他のPHPデータベース拡張機能は、スタッククエリを喜んで実行し、1つの文字列で提供されるすべてのクエリを実行し、深刻なセキュリティ問題を引き起こします。

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

PERLやPHPなどのスクリプト言語では、すべてのエスケープ文字をスマートに処理できます。 PHPのMySQL拡張機能は、MySQLに特殊な入力文字をエスケープする関数* mysql_real_escape_string()*を提供します。

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}%'");