MySQL にアクセスするアプリケーションは、ユーザーによって入力されるあらゆるデータを信頼しないようにしてください。ユーザーは Web フォーム、URL、または構築されたあらゆるアプリケーションに特殊文字またはエスケープ文字のシーケンスを入力することによってコードを欺くことを試すことができます。 ユーザーが ; DROP DATABASE mysql;
のような入力を行なっても、アプリケーションがセキュアな状態に保たれるようにしてください。 これは極端な例ですが、同様の技術を使用するハッカーに備えていない場合、結果として大規模なセキュリティーリークおよびデータ損失が発生することがあります。
よくある過ちは、文字列データ値のみ保護することです。 数値データも忘れずに検査してください。 ユーザーが 234
という値を入力したとき、アプリケーションが SELECT * FROM table WHERE ID=234
のようなクエリーを生成する場合、ユーザーは 234 OR 1=1
という値を入力して、SELECT * FROM table WHERE ID=234 OR 1=1
というクエリーをアプリケーションに生成させることができます。 その結果、サーバーはテーブル内のすべての行を取得します。 これはすべての行を公開し、サーバーに過剰な負荷がかかります。 この種類の攻撃から保護するためのもっとも簡単な方法は、数値定数を囲む単一引用符を使用して、SELECT * FROM table WHERE ID='234'
とする方法です。 ユーザーが余分の情報を入力すると、その情報はすべて文字列の一部となります。 数値コンテキストでは、MySQL は自動的にこの文字列を数値に変換し、あとに続く数値以外のすべての文字を取り除きます。
データベースに格納されているデータが公開されているもののみであれば、保護は不要だと思われることもあります。 これは正しくありません。 データベース内のどの行も表示が許可されている場合であっても、サービス妨害攻撃 (前のパラグラフの技術に基づいた、サーバーにリソースを浪費させるものなど) から保護するべきです。 そうしない場合、サーバーは正当なユーザーに対して応答不能になります。
チェックリスト:
厳密な SQL モードを有効にして、サーバーが受け入れるデータ値の制限を厳しくするようサーバーに指示します。 セクション5.1.11「サーバー SQL モード」を参照してください。
すべての Web フォームに一重引用符および二重引用符 (
'
および"
) を入力してみてください。 何らかの種類の MySQL エラーが出る場合、すぐに問題を調査してください。%22
("
)、%23
(#
) および%27
('
) を追加して、動的 URL の変更を試みます。前の例で示した文字を使用して、動的 URL のデータ型を数値型から文字型に変更してみます。 これらの攻撃や類似の攻撃に対してアプリケーションが安全であるようにしてください。
数値フィールドに、数値でなく文字、スペース、および特殊記号を入力してみます。 アプリケーションはこれらを MySQL に渡す前にこれらを削除するか、またはエラーを生成します。 検査済みでない値を MySQL に渡すことは非常に危険です。
データを MySQL に渡す前にデータのサイズを検査してください。
アプリケーションがデータベースに接続するときは、管理目的で使用するものとは異なるユーザー名を使用するようにしてください。 アプリケーションに不要なアクセス権限を付与しないでください。
多くのアプリケーションプログラミングインタフェースには、データ値の特殊文字をエスケープする手段が備わっています。 適切に使用すれば、これにより、意図とは異なる効果を持つステートメントをアプリケーションに生成させる値を、アプリケーションユーザーが入力できないようにすることができます。
MySQL C API:
mysql_real_escape_string_quote()
API コールを使用します。MySQL++: クエリーストリームに対して
escape
およびquote
修飾子を使用してください。-
PHP:
mysqli
またはpdo_mysql
拡張子を使用し、古いext/mysql
拡張子を使用しないでください。 推奨される API は、プレースホルダを持つプリペアドステートメントのほかに、改善された MySQL 認証プロトコルおよびパスワードをサポートします。 Choosing an APIも参照してください。古い
ext/mysql
拡張機能を使用する必要がある場合、エスケープにはmysql_escape_string()
またはaddslashes()
ではなくmysql_real_escape_string_quote()
関数を使用します。これは、mysql_real_escape_string_quote()
のみが文字セット対応であるためです。マルチバイト文字セットを使用している場合は、他の関数を「「バイパス」」にできます (無効)。 Perl DBI: プレースホルダまたは
quote()
メソッドを使用してください。Ruby DBI: プレースホルダまたは
quote()
メソッドを使用してください。Java JDBC:
PreparedStatement
オブジェクトおよびプレースホルダを使用してください。
ほかのプログラミングインタフェースも似たような機能を持っている場合があります。