ホームページ > バックエンド開発 > PHPチュートリアル > PDO のアンチインジェクション原理の分析と PDO 使用時の注意事項のまとめ、pdo の注意事項_PHP チュートリアル

PDO のアンチインジェクション原理の分析と PDO 使用時の注意事項のまとめ、pdo の注意事項_PHP チュートリアル

WBOY
リリース: 2016-07-13 10:16:26
オリジナル
1077 人が閲覧しました

PDOの抗注射原理の分析とPDO使用時の注意点、pdoの注意事項のまとめ

この記事では、PDO の抗注射原理の分析と PDO を使用する際の注意点について詳しく説明し、参考として皆様に共有します。具体的な分析は次のとおりです:

PDO が合理的かつ正しく使用されている限り、基本的に SQL インジェクションを防止できることは誰もが知っています。この記事は主に次の 2 つの質問に答えます。 mysql_connect の代わりに PDO を使用するのはなぜですか?
PDO がインジェクションに反対するのはなぜですか?
PDO を使用して注射を防ぐ場合、特に注意すべき点は何ですか?


1. PDO の使用を優先する必要があるのはなぜですか?

PHP マニュアルには明確に記載されています:


プリペアドステートメントとストアドプロシージャ より成熟したデータベースの多くは、プリペアド ステートメントの概念をサポートしています。プリペアド ステートメントは、アプリケーションが実行する 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 = 新しい PDO("mysql:host=192.168.0.1;dbname=test;charset=utf8","root");
$st = $pdo->prepare("select * from info where id =? and name = ?");

$id = 21;
$name = '張三';
$st->bindParam(1,$id);
$st->bindParam(2,$name);

$st->execute();
$st->fetchAll();
?>


環境は以下の通りです
PHP 5.4.7
MySQLプロトコルバージョン10
MySQLサーバー5.5.27

PHP と MySQL サーバー間の通信の詳細を徹底的に理解するために、調査用に特別に Wireshark を使用してパケットをキャプチャしました。次に示すように、Wireshak をインストールした後、フィルター条件を tcp.port==3306 に設定しました。


このようにして、不要な干渉を避けるために、mysql 3306 ポートとの通信データのみが表示されます。
Wireshak は wincap ドライバーに基づいており、ローカル ループバック インターフェイスでのリッスンをサポートしていないことに注意することが重要です (PHP を使用してローカル MySQL に接続しても、リッスンすることはできません)。他のマシン (仮想) 上の MySQL に接続してください。ブリッジされたネットワーク上のマシンでもテストを実行できます)。

次に、PHP プログラムを実行します。リスニング結果は次のとおりです。PHP が単に SQL を MySQL Server に直接送信しているだけであることがわかりました。


実際、これは mysql_real_escape_string を通常使用して文字列をエスケープし、SQL ステートメントに結合する場合と何ら変わりません (明らかに、この場合でも SQL インジェクションは可能です)。 PHP でローカルにクエリを操作するために pdo prepare で mysql_real_escape_string を呼び出すと、ローカルのシングルバイト文字セットが使用され、マルチバイトでエンコードされた変数を渡すと、依然として SQL インジェクションの脆弱性が発生する可能性があります (PHP 5.3.6 より前)。この問題のうち、PDO を使用する場合、php 5.3.6 以降にアップグレードし、DSN 文字列
で文字セットを指定することが推奨される理由が説明されています。
PHP 5.3.6 より前のバージョンの場合、次のコードは依然として SQL インジェクションの問題を引き起こす可能性があります:


コードをコピーします コードは次のとおりです:$pdo->query('SET NAMES GBK'); $var = chr(0xbf) .chr(0x27) " OR 1=1 /*"; $query = "SELECT * FROM info WHERE name = ?"; $stmt = $pdo->prepare($query); $stmt->execute(array($var));

その理由は上記の分析と一致しています。

正しいエスケープは、mysql サーバーの文字セットを指定し、変数を MySQL サーバーに送信して文字エスケープを完了することです。
では、PHP のローカル エスケープを禁止し、MySQL Server にエスケープさせるにはどうすればよいでしょうか?
PDO には PDO::ATTR_EMULATE_PREPARES という名前のパラメータがあり、PHP を使用してローカルで準備をシミュレートするかどうかを示します。このパラメータのデフォルト値は不明です。先ほど確認したパケット キャプチャと分析の結果によると、PHP 5.3.6 以降は依然としてデフォルトでローカル変数を使用し、それらを SQL に結合して MySQL サーバーに送信します。この値を false に設定して効果を試してみます。次のコード内:




コードをコピーします

コードは次のとおりです:

$pdo = 新しい PDO("mysql:host=192.168.0.1;dbname=test;","root"); $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);//これが先ほど追加したものです $st = $pdo->prepare("select * from info where id =? and name = ?");
$id = 21;
$name = '張三';

$st->bindParam(1,$id);
$st->bindParam(2,$name);
$st->execute();
$st->fetchAll();
?>


プログラムを実行し、Wireshark を使用してパケットをキャプチャして分析すると、結果は次のようになります。




見ましたか?これが魔法です。今回は、PHP が SQL テンプレートと変数を 2 回に分けて MySQL に送信し、MySQL が変数のエスケープを完了することがわかります。 SQL インジェクションの問題は解決されましたが、DSN で次のように charset 属性を指定する必要があります:

コードをコピーします

コードは次のとおりです:


$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root');



このようにして、SQL インジェクションの問題を根本的に排除できます。これについてよくわからない場合は、zhangxugg@163.com に電子メールを送信して、一緒に話し合うことができます。

3. PDOを使用する際の注意点

上記の点を理解した後、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 には実際には 2 つの関数があります:

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 インジェクション フィルタリング ライブラリを作成しようとしないでください (面倒で、未知の脆弱性が簡単に作成される可能性があります)。

この記事で説明した内容が皆様の PHP プログラミング設計に役立つことを願っています。

PHP はインジェクションを防ぐために前処理された PDO を使用します

前処理に PDO を使用すると、SQL が bgim に挿入されるのを効果的に防ぐことができます


phpのpdoの問題

これは少し範囲が広いですが、セキュリティは SQL だけでできるものではありません。

PDO を使用する場合は、SQL インジェクションを防止する必要があります。ユーザーの入力を確認する必要があります。 ! ! !一重引用符のようなものです
PHP にも使用できるメソッドがいくつかあります。すべてを説明することはできません。情報を見てください。通常、チュートリアルではこれについて説明します。

http://www.bkjia.com/PHPjc/898286.htmlwww.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/898286.html技術記事 PDO アンチインジェクション原理の分析と PDO 使用上の注意点のまとめ PDO アンチインジェクション原理の分析と PDO 使用上の注意点について詳しく説明します...
関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート