この記事では、PDO の抗注射原理の分析と PDO を使用する際の注意点について詳しく説明し、参考として皆様に共有します。具体的な分析は次のとおりです:
PDO が合理的かつ正しく使用されている限り、基本的に SQL インジェクションを防止できることは誰もが知っています。この記事は主に次の 2 つの質問に答えます。
mysql_connect の代わりに PDO を使用するのはなぜですか?
PDO がインジェクションに反対するのはなぜですか?
PDO を使用して注射を防ぐ場合、特に注意すべき点は何ですか?
1. PDO の使用を優先する必要があるのはなぜですか?
プリペアドステートメントとストアドプロシージャ
より成熟したデータベースの多くは、プリペアド ステートメントの概念をサポートしています。プリペアド ステートメントは、アプリケーションが実行する SQL のコンパイル済みテンプレートの一種と考えることができ、変数パラメーターを使用してカスタマイズできます。主な利点:
クエリを解析 (または準備) する必要があるのは 1 回だけですが、同じまたは異なるパラメーターを使用して複数回実行できます。クエリが準備されると、データベースはクエリを実行するための計画を分析、コンパイル、最適化します。複雑なクエリの場合、このプロセスには十分な時間がかかるため、異なるパラメーターを使用して同じクエリを何度も繰り返す必要がある場合、アプリケーションは分析、コンパイル、最適化のサイクルを繰り返す必要がなくなります。これは、準備されたステートメントが使用するリソースが少なくなるため、より高速に実行されることを意味します。
プリペアド ステートメントのパラメータを引用符で囲む必要はありません。アプリケーションがプリペアド ステートメントのみを使用する場合、開発者は SQL インジェクションが発生しないことを保証できます (ただし、クエリの他の部分が引用符で囲まれている場合)。エスケープされていない入力で構築されているため、SQL インジェクションは依然として可能です)。
PDO の prepare メソッドを使用しても、主に同じ SQL テンプレートのクエリ パフォーマンスを向上させ、SQL インジェクションを防ぎます
同時に、PHPマニュアルに警告メッセージが表示されます
PHP 5.3.6 より前では、この要素はサイレントに無視されていましたが、次の例に示すように、PDO::MYSQL_ATTR_INIT_COMMAND ドライバー オプションを使用して同じ動作を部分的に複製できます。
警告
以下の例のメソッドは、ISO-8859-1 や UTF-8 など、ASCII と同じ下位 7 ビット表現を共有する文字セットでのみ使用できます。ユーザーは、異なる表現を持つ文字セット (UTF-16 など) を使用します。または Big5) では、PHP 5.3.6 以降のバージョンで提供される charset オプションを使用する必要があります。
これは、PHP 5.3.6 以前のバージョンでは、DSN での文字セット定義がサポートされていないことを意味し、代わりに、一般的に使用される set names gbk コマンドである PDO::MYSQL_ATTR_INIT_COMMAND を使用して初期 SQL を設定する必要があります。
インジェクションを防ぐために依然として addlashes を使用しようとしているプログラムをいくつか見たことがありますが、これが実際にさらなる問題を引き起こすかどうかはわかりません。詳細については、http://www.bkjia.com/article/49205.htm
を参照してください。
データベース クエリを実行する前に、SQL 内の select、union などのキーワードをクリーンアップする方法もあります。このアプローチは明らかに間違った対処方法であり、提出されたテキストに学生組合が含まれている場合、置き換えによって元の内容が改ざんされ、無実の人々が無差別に殺害されることになるため、お勧めできません。
2. PDO が SQL インジェクションを防止できるのはなぜですか?
まず次の PHP コードを見てください:
コードをコピーします
コードは次のとおりです:
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root');
上記の点を理解した後、PDO を使用して SQL インジェクションを防ぐためのいくつかの注意事項をまとめることができます。
1. php を 5.3.6 以降にアップグレードします。実稼働環境では、php 5.3.9 以降にアップグレードすることを強くお勧めします。PHP 5.3.8 には致命的なハッシュ衝突の脆弱性があります。
2. php 5.3.6以降を使用している場合は、PDO
のDSNでcharset属性を指定してください
3. PHP 5.3.6 以前のバージョンを使用している場合は、PDO::ATTR_EMULATE_PREPARES パラメーターを false に設定します (つまり、変数処理は MySQL によって実行されます)。ローカル シミュレーションを使用して prepare することもできます。mysql サーバーの prepare を呼び出すこともできます。 DSN での文字セットの指定は無効であり、セット名
4. PHP 5.3.6 以前のバージョンを使用している場合、Yii フレームワークはデフォルトで ATTR_EMULATE_PREPARES の値を設定しないため、データベース設定ファイルで EmulatePrepare の値を false に指定してください。
そこで質問がありますが、DSN で charset が指定されている場合でも、set names
はい、保存できません。 set names
A. クライアント (PHP プログラム) が送信したエンコーディングを mysql サーバーに伝えます
B. mysql サーバーに、クライアントが必要とする結果のエンコーディングを伝えます
言い換えると、データテーブルが gbk 文字セットを使用し、PHP プログラムが UTF-8 エンコーディングを使用する場合、クエリを実行する前に set names utf8 を実行して、mysql サーバーに正しくエンコードするように指示できます。プログラム。このようにして、クエリを utf-8 エンコーディングで mysql サーバーに送信し、取得される結果も utf-8 エンコーディングになります。これにより、プログラム内の変換エンコードの問題が解消され、文字化けしたコードが生成されることはありません。
では、DSN で文字セットを指定することの役割は何でしょうか? これは、ローカル ドライバーがエスケープするときに指定された文字セットを使用することを PDO に伝えるだけです (mysql サーバーの通信文字セットを設定するわけではありません)。セット名 < ;charset> ディレクティブを使用します。
一部の新しいプロジェクトが PDO を使用せず、従来の mysql_XXX 関数ライブラリを使用する理由が本当にわかりません。 PDO を正しく使用すれば、SQL インジェクションを根本的に排除することができます。各企業の技術リーダーおよび最前線の技術研究開発担当者は、この問題に注意を払い、プロジェクトの進捗と安全性の品質を向上させるために、可能な限り PDO を使用することを強くお勧めします。 。
独自の SQL インジェクション フィルタリング ライブラリを作成しようとしないでください (面倒で、未知の脆弱性が簡単に作成される可能性があります)。
PDO を使用する場合は、SQL インジェクションを防止する必要があります。ユーザーの入力を確認する必要があります。 ! ! !一重引用符のようなものです
PHP にも使用できるメソッドがいくつかあります。すべてを説明することはできません。情報を見てください。通常、チュートリアルではこれについて説明します。