序文 この記事では、SQL インジェクションを回避するために pdo の前処理メソッドを使用します。詳しい紹介を見てみましょう。 PHP マニュアルの「PDO - 準備されたステートメントとストアド プロシージャ」の項:
上記の 2 つの利点は次のとおりです。 1. まず、MySQL のストアド プロシージャについて説明します。MySQL5 ではストアド プロシージャ機能が導入されました。ストアド プロシージャが作成されると、データベースはすでにそれを解析して最適化していました。次に、ストアド プロシージャが実行されると、そのストアド プロシージャのコピーがメモリ内に保持されるため、次に同じストアド プロシージャが実行されたときに、メモリから直接読み取ることができます。 MySQL ストアド プロシージャの使用については、https://www.jb51.net/article/7032.htm を参照してください。 PDO の場合も、原理は同じですが、PDO は EMULATE_PREPARES (シミュレートされた前処理) をサポートしており、これは PDO ドライバーによってローカルで完了します。同時に、ローカルのシミュレートされた前処理を使用せず、MySQL に完了させることもできます。これら 2 つの状況については、以下で説明します。 2. SQL インジェクションを防ぐために、tcpdump と wireshark を使用してパケットをキャプチャし、分析しました。 仮想マシン上でコードを実行して、リモート MySQL へのリクエストを開始します。 <?php $pdo = 新しい PDO ("mysql:host=10.121.95.81;dbname=thor_cms;charset=utf8", "root","qihoo@360@qihoo"); $st = $pdo->prepare("id =? かつ uid = ?" の場合、share から * を選択します); $id = 6; $uid = 521; $st->bindParam(1, $id); $st->bindParam(2, $uid); $st->execute(); $ret = $st->fetchAll(); print_r($ret); tcpdump を介してパケットをキャプチャしてファイルを生成します。 tcpdump -ieth0 -A -s 3000 ポート 3306 -w ./mysql.dump sz mysql.dump Wireshark 経由でファイルを開きます: 全体のプロセスを見ることができます: 3ウェイハンドシェイク - ログイン要求 - 要求クエリ - 要求終了 リクエスト クエリ パッケージを見ると、次のことがわかります。 はぁ?これも SQL ステートメントを連結しているのではないですか? 実際、これは、mysql_real_escape_string を使用して文字列をエスケープし、それを SQL ステートメントに連結する方法と変わりません。PDO ローカル ドライバーがエスケープを完了するだけです (EMULATE_PREPARES) この場合、SQL インジェクションは依然として可能です。つまり、クエリを操作するために PHP で pdo prepare の mysql_real_escape_string がローカルに呼び出され、ローカルのシングルバイト文字セットが使用され、マルチバイトでエンコードされた変数を渡すと、SQL インジェクションの脆弱性が依然として発生する可能性があります (これは PHP 5.3.6 より前のバージョンの問題の 1 つであり、PHP 5.3.6 以降にアップグレードし、PDO を使用するときに DSN 文字列で文字セットを指定することが推奨される理由です)。 PHP 5.3.6 より前のバージョンでは、次のコードによって SQL インジェクションの問題が発生する可能性があります。 $pdo->query('GBKの名前を設定'); $var = chr(0xbf) . chr(0x27) . " OR 1=1 /*"; $query = "SELECT * FROM info WHERE name = ?"; $stmt = $pdo->prepare($query); $stmt->execute(配列($var)); 正しいエスケープは、MySQL サーバーの文字セットを指定し、変数を MySQL サーバーに送信して文字エスケープを完了することです。 では、PHP のローカル エスケープを無効にして、MySQL サーバーにエスケープを実行させるにはどうすればよいでしょうか? PDO には PDO::ATTR_EMULATE_PREPARES というパラメータがあり、PHP ローカル シミュレート準備を使用するかどうかを示します。このパラメータのデフォルトは true です。これを false に変更してパケットをキャプチャしてみましょう。 コードの最初の行の後に追加します PDO::ATTR_EMULATE_PREPARES 属性を false に設定します。 tcpdump を使用してパケットを再度キャプチャします。Wireshark では次のことがわかります。 PHPはSQL文を送信するために準備-実行メソッドを使用する 今回は変数エスケープ処理はMySQLサーバーによって実行されます。 変数と SQL テンプレートは 2 回送信されるため、SQL インジェクションの問題はありませんが、明らかに送信が 1 回多く発生します。これは、php5.3.6 以降では不要です。 PDO の使用に関する注意事項 1. PHP を 5.3.6 以降にアップグレードします。実稼働環境では、PHP 5.3.9 以降または PHP 5.4 以降にアップグレードすることを強くお勧めします。PHP 5.3.8 には、致命的なハッシュ衝突の脆弱性があります。 2. PHP 5.3.6 以降を使用している場合は、PDO DSN で charset 属性を指定してください。 5.3.6 未満: $dbh = new PDO($dsn,$user,$pass,array(PDO::MYSQL_ATTR_INIT_COMMAND => "set names utf8")); 3. PHP 5.3.6 以前を使用している場合は、PDO::ATTR_EMULATE_PREPARES パラメータを false に設定します (つまり、MySQL サーバーが変数を処理するようにします)。ローカルでシミュレートされた準備を使用する場合でも、MySQL サーバーの準備を呼び出す場合でも、PHP 5.3.6 以降のバージョンではこの問題がすでに処理されています。 4. PHP 5.3.6 以前を使用している場合、Yii フレームワークはデフォルトで ATTR_EMULATE_PREPARES の値を設定しないため、データベース構成ファイルで emulatePrepare の値を false に指定してください。 注記: 1. DSN で文字セットを指定する場合、セット名 <charset> を実行する必要があるのはなぜですか? 実際、セット名 <charset> には 2 つの機能があります。 MySQLサーバーにクライアント(PHPプログラム)が送信したエンコーディングを通知する MySQLサーバーにクライアントが結果に必要とするエンコーディングを通知する つまり、データ テーブルが gbk 文字セットを使用し、PHP プログラムが UTF-8 エンコーディングを使用する場合、クエリを実行する前に set names utf8 を実行して、プログラムでエンコーディングを変換することなく、MySQL サーバーに正しいエンコーディングを使用するように指示することができます。この方法では、UTF-8 エンコーディングで MySQL サーバーにクエリを送信すると、結果も UTF-8 エンコーディングになります。これにより、プログラム内でのエンコード変換の問題がなくなります。文字化けは発生しませんのでご安心ください。 では、DSN で文字セットを指定する目的は何でしょうか? これは、ローカル ドライバーがエスケープ時に指定された文字セットを使用するように PDO に指示するだけです (MySQL サーバー通信の文字セットは設定しません)。MySQL サーバー通信の文字セットを設定するには、set names <charset> コマンドも使用する必要があります。 2. PDO::ATTR_EMULATE_PREPARES 属性を false に設定したことによる殺人事件: http://my.oschina.net/u/437615/blog/369481 要約する 上記はこの記事の全内容です。この記事の内容が皆さんの勉強や仕事に一定の参考学習価値を持つことを願っています。ご質問があれば、メッセージを残してコミュニケーションしてください。123WORDPRESS.COM を応援していただきありがとうございます。 以下もご興味があるかもしれません:
|
コマンドラインでMYSQLに正常にログインでき、NavicatもMySQLに正常に接続できますが、I...
仮想マシンに独自の LAN IP を持たせたいので、テストを容易にするためにブリッジを使用します。 ...
mysql の IN はインデックスを無効にしますか?しませんよ! 結果をご覧ください: mysq...
プログラムサービスがgitlab ci/cdと統合されたk8sを使用してデプロイされている場合、gi...
目次1. NFS-Ganeshaの紹介2. NFS-Ganeshaの設定3. NFS-Ganesha...
序文今日、自作のコンポーネントを使っていたところ、突然、長い間忘れていたバブリングイベントに遭遇しま...
これは私が Vue フレームワークを独学していたときに真似したウェブサイトです。いくつかの都市の天気...
目次1. 需要方法1方法2方法3 2. 実装3. 問題解決質問1: トークンの複数回の更新を防ぐ方法...
Linux での Hadoop インストール チュートリアルはインターネットや書籍に多数ありますが、...
初心者は、いくつかの HTML タグを理解することで HTML を学習できます。この入門書は、初心者...
目次序文1. これを使用してデータ内のデータを読み取るプロセス2. Dep.target はいつ存在...
HTML5 で contentEditable 属性が導入されて以来、div は textarea ...
私はかつて、ウェブサイトを一度も構築したことのない人々が、初心者向けのウェブサイト構築方法に関する私...
1. プロジェクト文書 2. ページレイアウトにHTMLとCSSを使用するHTML部分 <di...
目次初期ビューVue開発環境の構築Vueインスタンスの作成Vue テンプレート構文Vue データバイ...