P粉2383558602023-09-01 15:03:48
パラメータ化されたクエリを使用するには、Mysqli または PDO を使用する必要があります。 mysqli を使用して例を書き直すには、次のものが必要になります。
リーリー読む必要がある重要な関数は mysqli::prepare
.
また、他の人が提案しているように、PDO< 之类的东西来提升抽象层很有用/更容易/a>.
のようなものを使用することもできます。あなたが質問しているケースは非常に単純ですが、より複雑なケースではより高度な方法が必要になる可能性があることに注意してください。特に:###
には必要なエスケープが含まれていません。この場合、ユーザーの入力をホワイトリストに渡して、「安全な」値のみが許可されるようにする方が良いでしょう。
P粉2835590332023-09-01 11:53:19
どのデータベースを使用する場合でも、SQL インジェクション攻撃を回避する 正しい 方法は、 データを SQL から分離することです これにより、データは依然としてデータのままであり、 >決して SQL パーサーによってコマンドとして解釈されません。適切にフォーマットされたデータ部分を含む SQL ステートメントを作成することは可能ですが、 詳細がまったく理解できない場合は、常に プリペアド ステートメントとパラメーター化されたクエリを使用する必要があります。 は、パラメーターとは別にデータベース サーバーに送信され、データベース サーバーによって解析される SQL ステートメントです。これにより、攻撃者が悪意のある SQL を挿入することは不可能になります。
これを実現するには基本的に 2 つのオプションがあります:
の使用 (MySQL の場合):
PHP 8.2 以降では、
execute_query() を使用して、1 つのメソッドで準備、パラメータのバインド、SQL ステートメントの実行を行うことができます。
リーリー
< code>PHP8.1 まで:
MySQL 以外のデータベースに接続している場合は、2 番目のドライバー固有のオプションを参照できます (たとえば、PostgreSQL の場合は
pg_prepare()) 。 PDO はユニバーサル オプションです。
接続を正しく設定してください< /code>
プリペアド ステートメント はデフォルトでは使用されないことに注意してください。この問題を解決するには、準備されたステートメントのシミュレーションを無効にする必要があります。 PDO を使用して接続を作成する例は次のとおりです。 リーリー 上記の例では、エラー モードは厳密には必要ありませんが、 追加することをお勧めします。このように、PDO は PDOException をスローすることで、すべての MySQL エラーを通知します。
ただし、 forcing は最初の setAttribute()
行で、シミュレートされたプリペアド ステートメントを無効にし、
プリペアド ステートメント ステートメントを使用するように PDO に指示します。これにより、ステートメントと値が MySQL サーバーに送信される前に PHP によって解析されなくなります (攻撃者になる可能性のある者に悪意のある SQL を注入する機会を与えません)。
コンストラクターのオプションで 文字セット
を設定できますが、PHP の「古い」バージョン (5.3.6 より前) は文字セットを黙って無視することに注意することが重要です。パラメーター ###。
mysqli の場合も同じルーチンに従う必要があります:
リーリー
イラスト
に渡す SQL ステートメントは、データベース サーバーによって解析され、コンパイルされます。パラメーター (
?execute を呼び出すと、準備されたステートメントが指定したパラメーター値と結合されます。
ここで重要なのは、パラメーター値が SQL 文字列ではなく、コンパイルされたステートメントと組み合わされるということです。 SQL インジェクションは、データベースに送信する SQL を作成するときに、スクリプトをだまして悪意のある文字列を含めることによって機能します。したがって、実際の SQL をパラメータとは別に送信することで、予期しない結果が生じるリスクを制限できます。
準備されたステートメントを使用するときに送信するパラメーターはすべて文字列として扱われます (ただし、データベース エンジンが最適化を行う可能性があるため、パラメーターは最終的に数値として扱われることもあります)。上記の例では、$name
変数に 'Sarah'; DELETE FROMEmployees
が含まれている場合、結果は単に検索文字列 "'Sarah'; DELETE FROMEmployees"
になります。 空のテーブルが残ることはありません。
プリペアド ステートメントを使用するもう 1 つの利点は、同じセッション内で同じステートメントを複数回実行しても、解析とコンパイルが 1 回だけ行われるため、速度が向上することです。
ああ、挿入方法を尋ねられたので、ここに例を示します (PDO を使用):
リーリープリペアド ステートメントをクエリ パラメーターとともに使用することはできますが、動的クエリ自体の構造はパラメーター化できず、特定のクエリ関数もパラメーター化できません。
これらの特定のシナリオの場合、最適なアプローチは、ホワイトリスト フィルターを使用して、可能な値を制限することです。
リーリー