PHP での SQL インジェクションの防止
- PHP でプリペアドステートメントと PDO を使用しての SQL インジェクションを防止する
-
PHP でパラメータ化されたクエリで
Prepared
ステートメントを使用しての SQL インジェクションを防止する -
PDO::ATTR_EMULATE_PREPARES
属性をfalse
に設定して、SQL インジェクションを防止する
プリペアドステートメントと PHP データオブジェクト(PDO)を使用して、PHP での SQL インジェクションを防止する方法を紹介します。この方法では、PDO を使用してデータベース通信を確立します。このメソッドは、データとクエリを別々にデータベースサーバーに送信します。これにより、データとサーバーが混在するのを防ぎます。
プリペアドステートメントとパラメータ化されたクエリを使用して、PHP で SQL インジェクションを防止する方法を紹介します。この方法では、mysqli
を使用してデータベース通信を確立します。この方法は、最初の方法と同様の動作メカニズムを備えています。対照的な点は、SQL インジェクションを防ぐために使用する mysqli
関数のみです。
プリペアドステートメントのエミュレーションを false
に設定することにより、PHP で PDO を使用しながら SQL インジェクションから安全にする方法の例を示します。
PHP でプリペアドステートメントと PDO を使用しての SQL インジェクションを防止する
プリペアドステートメントを PDO と一緒に使用して、PHP での SQL インジェクションを防ぐことができます。SQL インジェクションは、データベースへの送信中にクエリとデータが混在している場合に発生します。このメソッドでは、SQL ステートメントでデータの正確な値を指定しません。代わりにプレースホルダーを使用します。このため、パラメーター化された SQL ステートメントは最初の要求としてサーバーに送信されます。これを実現するために、prepare()
関数を使用します。2 番目のリクエストのパラメータの正確な値をデータベースサーバーにバインドします。この目的のために bindValue()
関数を使用します。このようにして、最初のリクエストでプログラムを送信し、2 番目のリクエストでデータを送信します。SQL コードと一緒にデータを要求すると、ユーザーはプログラムを変更して悪意のあるコードを書き込むことができます。したがって、悪意のある SQL コードがサーバーに挿入されるのを防ぎます。
たとえば、テーブル users
には次のフィールドとデータが含まれています。
+----+-----------+----------+------------+
| id | firstname | lastname | dob |
+----+-----------+----------+------------+
| 1 | bruce | rose | 1998-02-13 |
| 2 | jeff | james | 2000-03-30 |
+----+-----------+----------+------------+
変数 $firstname
を作成し、bruce
という名前を割り当てます。変数 $sql
を作成して、SELECT * FROM users WHERE firstname =:fname;
というクエリを記述する。
firstname
のデータの正確な値を書き込まないでください。代わりに、パラメータ:fname
を使用してください。$pdo
変数を使用して、クエリ変数で prepare()
関数を呼び出します。:fname
の値を変数 $firstname
に置き換えます。execute()
関数を使用してステートメントを実行します。クレデンシャルがデータベースと一致する場合は、fetch()
関数で結果を確認してください。表示されている場合は、選択した行の id
、firstname
、および lastname
を表示します。
以下の例は、プリペアドステートメントの使用法を示しています。firstname
フィールドの値を変数に格納して、資格情報が一致するかどうかを確認します。代わりに変数に悪意のあるコードが含まれている場合は、資格情報が一致しません
というメッセージが表示されます。これは、prepared()
関数がパラメーター化されたクエリのみを受け取り、正確なデータを許可しないためです。$pdo
変数には、データベース接続のオブジェクトが含まれています。
サンプルコード:
# php 7.*
<?php
$firstname = "bruce";
$sql = "SELECT * FROM users WHERE firstname =:fname ;";
$stmt = $pdo->prepare($sql);
$stmt->bindValue(":fname", $firstname);
$stmt->execute();
if(!$result = $stmt->fetch(PDO::FETCH_OBJ)){
echo "Credentials do no match";
} else {
echo"Id: ".$result->id. " Name: ".$result->firstname." ".$result->lastname;
}
?>
出力:
Id: 1 Name: bruce rose
PHP でパラメータ化されたクエリで Prepared
ステートメントを使用しての SQL インジェクションを防止する
PHP での SQL インジェクションを防ぐために、プリペアドステートメントをパラメータ化されたクエリと一緒に使用できます。mysqli()
関数のオブジェクトを使用して、データベース接続を作成します。この方法では、疑問符記号 ?
を使用します。データのプレースホルダーとして。上記のメソッドとして prepare()
関数を使用します。プレースホルダー内の実際のデータをバインドするために、bind_param()
関数を使用します。この方法は、上記の方法と同様の動作メカニズムに従います。
たとえば、mysqli()
関数のオブジェクトを作成するデータベース接続を確立し、それを変数 $conn
に割り当てます。jeff
という名前で変数 $firstname
に割り当てます。変数 $sql
を作成し、クエリ SELECT * FROM users WHERE first name =?;
を記述します。$conn
変数を使用して、クエリ変数で prepare()
関数を呼び出します。プレースホルダー?
を置き換えます変数 $firstname
を使用します。execute()
関数を使用してステートメントを実行します。get_result()
関数を呼び出して、結果を $result
変数に格納します。num_rows
プロパティで行が存在するかどうかを確認し、条件が失敗した場合は exit()
関数でメッセージ No Rows
を返します。fetch_assoc()
メソッドを呼び出し、while
ループの $row
変数に格納します。選択した行の id
、firstname
、および lastname
を表示します。
サンプルコード:
#php 7.x
<?php
$conn = new mysqli($host, $user, $pwd, $dbName);
$firstname = "jeff";
$sql = "SELECT * FROM users WHERE firstname = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $firstname);
$stmt->execute();
$result = $stmt->get_result();
if($result->num_rows === 0) exit('No rows');
while($row = $result->fetch_assoc()) {
echo"Id: ".$row['id']. " Name: ".$row['firstname']." ".$row['lastname'];
}
出力:
Id: 2 Name: jeff james
PDO::ATTR_EMULATE_PREPARES
属性を false
に設定して、SQL インジェクションを防止する
PDO 属性を正しく設定しないと、PDO でプリペアドステートメントを使用しても SQL インジェクションを防ぐのに十分でない場合があります。インジェクションを防ぐために、PDO::ATTR_EMULATE_PREPARES
属性を false
に設定する必要があります。属性を true
に設定すると、PDO は準備されたステートメントを使用せずにエミュレートするだけです。したがって、システムは SQL インジェクションに対して脆弱になります。
たとえば、変数 $pdo
でデータベースへの PDO 接続を作成します。変数を使用して、setAttribute()
関数を呼び出します。属性 PDO::ATTR_EMULATE_PREPARES
を false に設定します。
コード例:
#php 7.x
<?php
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
?>
Subodh is a proactive software engineer, specialized in fintech industry and a writer who loves to express his software development learnings and set of skills through blogs and articles.
LinkedIn