[準備されたステートメントと PDO を使用して PHP での 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
フィールドの値を変数に保存して、資格情報が一致することを確認します。変数に悪意のあるコードが含まれている場合は、メッセージが表示されますCredentials do no match
。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
[ prepared
SQL インジェクションを防ぐために、PHP でパラメータ化されたクエリ ステートメントを使用する]
prepared
パラメータ化されたクエリでステートメントを使用すると、PHP での SQL インジェクションを防ぐことができます。mysqli()
関数オブジェクトを使用してデータベース接続を作成します。?
このアプローチでは、データのプレースホルダーとして疑問符記号を使用します。prepare()
上記の方法として関数を使用します。この関数を使用してbind_param()
、実際のデータをプレースホルダーにバインドします。この方法は、上記の方法と同様の動作メカニズムに従います。
たとえば、データベース接続を確立し、mysqli()
関数オブジェクトを作成して、それを変数に割り当てます$conn
。jeff
変数に名前を割り当てます$firstname
。変数を作成し$sql
、クエリを作成しますSELECT * FROM FROM where where first name = ?;
。変数を使用して$conn
、クエリ変数の関数を呼び出しますprepare()
。?
変数で使用するプレースホルダーを置き換えます$firstname
。関数を使用してexecute()
ステートメントを実行します。get_result()
関数を呼び出し、結果を$result
変数に格納します。条件が失敗した場合は、行にnum_rows
属性があるかどうかを確認し、exit()
関数を使用してメッセージを返しますNo Rows
。このメソッドは while ループ内で呼び出されfetch_assoc()
、変数に格納されます$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
[ SQLインジェクションPDO::ATTR_EMULATE_PREPARES
を防止するプロパティを設定するfalse
]
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);
?>