インターネットに接続しているコンピュータで MySQL を使用するには、このセクションの内容を十分に理解し、セキュリティ面での誤操作を起こさないように注意してください。
セキュリティに関する説明では、様々な攻撃に対して、MySQL サーバだけでなく、サーバ ホスト全体を完全に守る必要があることを強調しています。この攻撃とは、聴傍受、改ざん、再生、サービス妨害などのことです。ここでは、可用性および耐障害性のすべてについては触れていません。
MySQL では、接続、クエリ、そしてユーザが行なう別のオペレーションに対して、アクセス制御リスト (ACL, Access Control Lists) に基づくセキュリティ保護を行ないます。MySQL クライアントとサーバ間での SSL 暗号化接続をサポートしています。ここで説明するコンセプトの多くは、MySQL だけに該当するものではなく、様々なアプリケーションにも該当します。
MySQL を実行するときには、常に次のガイドラインに従います。
MySQL root
ユーザ以外のだれにも mysql
データベースの user
テーブルへのアクセス権を与えない。
これは特に重要なことです。
MySQL
のアクセス権限システムについて学び、理解する。MySQL
へのアクセスを制御するには、GRANT
および REVOKE
のステートメントを使用します。必要以上の権限をユーザに設定しないこと。すべてのホストに対する権限は決して与えないこと。
チェックリスト
mysql -u root
を試す。パスワードなしでサーバに正常に接続できるようだと問題がある。この場合、すべての権限を持つ
root
ユーザとして、MySQL
サーバに接続できるということである。特に
root
パスワードの設定に関する項目に注意して、MySQL
インストール手順を見直す。項2.10.3. 「最初の MySQL アカウントの確保」
を参照のこと。
SHOW GRANTS
コマンドを使用して、だれが何にアクセスできるかをチェックする。REVOKE
コマンドを使用して不要な権限を削除する。
データベースには、テキスト形式のパスワードを保存しないこと。コンピュータがクラックされたとき、パスワードの完全なリストが奪われて不正使用される結果になる。MD5()
、SHA1()
、または別の一方向ハッシング関数を使用する。
辞書を使用してパスワードを選択しない。特殊プログラムで解読されてしまう。「xfish98」 のようなパスワードも良くない。標準 QWERTY キーボードで 「fish」 を 1 列左でタイプした 「duag98」 などを推奨。また、「Mary had a little lamb」 の頭文字を取って 「Mhall」 とするのも良い。 この方法だと覚えやすく、また部外者が類推することも困難。
ファイアウォールに投資する。これにより、少なくとも 50% の攻撃を防ぐことができる。MySQL をファイアウォール内つまり非武装地帯 (DMZ) に配置する。
チェックリスト
nmap
などのツールを使用して、インターネットから自分のポートをスキャンしてみる。MySQL
はデフォルトでポート 3306
を使用する。このポートは、信頼されていないホストからアクセスできてはいけない。他にも、MySQL
ポートが開いているかどうか確かめる簡単な方法として、リモート
コンピュータから以下のコマンドを実行するという方法がある。ここで、server_host
は MySQL サーバのホスト名、または IP
アドレスである。
shell> telnet server_host
3306
接続できて意味不明な文字が返ればポートが開いている。開いておく正当な理由がない限り、ファイアウォールまたはルータで閉じておく。telnet がハングするか、接続が拒否されれば正常である。つまり、ポートは閉じている。
ユーザが入力するデータを信頼しないこと。Web
フォーム、URL、その他のアプリケーションから特殊文字またはエスケープ文字シーケンスが入力され、不正操作が行われる可能性がある。ユーザが
「; DROP DATABASE mysql;
」
などのような入力をしても、アプリケーションが安全に保たれるようにしなければならない。これは極端な例であるが予防策を講じておかないと、クラッカーによる同様の手段によって、重大なセキュリティリークやデータの紛失が発生する可能性がある。
また、数値データもチェックすること。数値定数をアポストロフィで囲むこと。SELECT
* FROM table WHERE ID=234
ではなく、SELECT * FROM table WHERE
ID='234'
のようにする。(ユーザが 234
という値を入力したときに、SELECT * FROM table
WHERE ID=234
というようなクエリをアプリケーションで生成する場合、そのユーザが
234 OR 1=1
という値を入力して、そのアプリケーションで
SELECT * FROM table WHERE ID=234 OR 1=1
というクエリを生成させることができる。その結果、サーバがテーブルの行をすべて読み出してしまい、サーバの負荷が増える。)
MySQL
は自動的のこの文字列を数値に変換し、非数値記号を削除する。
文字列だけを保護するのは、よくあるミスである。公開データのみのデータベースは保護する必要がないという考えもよくある誤りである。そのようなデータベースにも、サービス妨害タイプの攻撃 ( DoS攻撃) が可能であり、前述の例は、そのようなテクニックを不正使用したケースであり、これによるサーバの脆弱性をつかれ、システム ダウンに繋がる。(正当なユーザに対してサービスを提供できなくなる。)
チェックリスト
すべての Web フォームで
、‘'
’ および
‘"
’を入力してみる。何らかの
MySQL
エラーが発生した場合は、すぐにその問題を調べる。
URL で %22
(‘"
’)、
%23
(‘#
’)、および
%27
(‘'
’)
を追加して URL の動的修正を試みる。
前述の文字を含む URL の動的 データを数値型から文字型に変更する。この類の攻撃があってもアプリケーションに影響しないようにする。
数値フィールドに数値ではなく、文字、スペース、および特殊記号を入力してみる。MySQL に渡すことなくアプリケーションがそれらの値を削除するか、エラーを生成することが必要である。値がチェックされずに MySQL に渡ると非常に危険である。
MySQL に渡す前にデータサイズをチェックする。
管理目的で使用するユーザ名とは別のユーザ名で、アプリケーションをデータベースに接続させる。アプリケーションに、必要以上のアクセス権を設定しないこと。
様々なアプリケーション プログラムのインターフェースは、データ値に特殊文字をエスケープする手段になる。適切に使用しなければ、アプリケーションのユーザによる入力が原因で、意図したものとは異なる効果を与えるステートメントの生成を回避できる。
MySQL C API:
mysql_real_escape_string()
API
コールを使用する。
MySQL++: クエリのストリームには
escape
または
quote
などの修飾子を使用する。
PHP: PHP 4.3.0以降
は、mysql_real_escape_string()
関数を使用する。PHP 4.3.0前の PHP
バージョンでは、mysql_escape_string()
を使用して、PHP 4.0.3
以前は、addslashes()
を使用する。ノート:
mysql_real_escape_string()
関数だけが認識文字セット。そのほかの関数は、無効なマルチ
バイトの文字セットを使用すると、「擦り抜ける
(bypassed) 」。PHP 5
では、mysqli
という拡張モジュールを使用する。これは、改善を施した
MySQL
の認識プロトコルとパスワード、プレースホルダの準備されたステートメント
(prepared statements) をサポートする。
Perl DBI: プレースホルダ、または
quote()
メソッドを使用する。
Ruby DBI: プレースホルダ、または
quote()
メソッドを使用する。
Java JDBC: PreparedStatement
オブジェクトとプレースホルダ
を使用する。
別のプログラミングのインターフェイスでも上記と同様の役割がある可能性がある。
暗号化していないプレーンのデータをインターネット経由で送らない。インターネット経由の情報は、時間と技術があれば誰にでもアクセスでき、第三者によって悪用される可能性がある。MySQL では、バージョン 4.0. 以降、内部 SSL 接続をサポートしている。 SSH ポート転送を使用して、暗号化(および圧縮)された通信トンネルを作成できる。
tcpdump や strings などのユーティリティの使用法を理解すること。ほとんどの場合、以下のようなコマンドで、MySQL データ ストリームが暗号化されているかどうかをチェックできる。
shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings
これは、Linux システムで有効。他のシステムでも、少し修正するだけで使用できる。 警告: データを見ることができなくても、必ずしも実際に暗号化されているとは限らない。高度なセキュリティが必要な場合は、専門家に相談する。