SQL-インジェクション

Webページを介してユーザー入力を取得し、それをSQLデータベースに挿入すると、セキュリティの問題として知られているセキュリティの問題のために自分自身を大きく開いたままにしておく可能性があります。 SQL Injection。この章では、これを防ぐ方法と、PERLスクリプトなどのサーバーサイドスクリプトでスクリプトとSQLステートメントを保護する方法について説明します。

インジェクションは通常、ユーザーに名前などの入力を求めるときに発生し、名前の代わりに、データベースで無意識のうちに実行するSQLステートメントをユーザーに提供します。ユーザーが提供したデータを決して信頼せず、検証後にのみこのデータを処理してください。原則として、これはによって行われますPattern Matching

以下の例では、 name 英数字とアンダースコア、および8〜20文字の長さに制限されています(必要に応じてこれらのルールを変更してください)。

if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)) {
   $result = mysql_query("SELECT * FROM CUSTOMERS 
      WHERE name = $matches[0]");
} else {
   echo "user name not accepted";
}

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

// supposed input
$name = "Qadir'; DELETE FROM CUSTOMERS;";
mysql_query("SELECT * FROM CUSTOMSRS WHERE name='{$name}'");

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

幸い、MySQLを使用している場合、 mysql_query()関数では、クエリをスタックしたり、1回の関数呼び出しで複数のSQLクエリを実行したりすることはできません。クエリをスタックしようとすると、呼び出しは失敗します。

ただし、他の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 CUSTOMERS WHERE name='{$name}'");

LIKE Quandary

LIKEの問題に対処するには、カスタムエスケープメカニズムでユーザー指定の「%」および「_」文字をリテラルに変換する必要があります。使用するaddcslashes()、エスケープする文字範囲を指定できる関数。

$sub = addcslashes(mysql_real_escape_string("%str"), "%_");
// $sub == \%str\_
mysql_query("SELECT * FROM messages 
   WHERE subject LIKE '{$sub}%'");