MySQLデータベース操作にPHPを使用する場合、開発者はMySQLI拡張機能で関連する関数を使用してクエリを実行し、結果セットを処理することがよくあります。たとえば、 mysqli_query()をmysqli_resultオブジェクトで使用して、クエリ結果を簡単に取得できます。ただし、SQLステートメントを構築するときに入力パラメーターが適切に処理されない場合、SQLインジェクションの問題を引き起こすのは簡単で、異常なクエリ結果、データの漏れ、さらにはシステムの故障につながります。
ユーザー情報を照会するページがあるとしますが、コードは次のとおりです。
<?php
$conn = new mysqli("localhost", "root", "password", "mydb");
$username = $_GET['username']; // ユーザー入力から
$sql = "SELECT * FROM users WHERE username = '$username'";
$result = $conn->query($sql);
if ($result && $result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
echo "ユーザー: " . $row["username"] . ",郵便: " . $row["email"] . "<br>";
}
} else {
echo "未找到ユーザー";
}
$conn->close();
?>
ユーザーが次のURLを入力した場合:
https://m66.net/user.php?username=admin' OR '1'='1
その後、SQLステートメントは次のようになります。
SELECT * FROM users WHERE username = 'admin' OR '1'='1'
これにより、認証条件をバイパスし、すべてのユーザーのレコードを返します。
mysqli_resultオブジェクトを使用して結果セットを処理する場合、返されたデータはSQLステートメントの実行結果に依存します。ステートメントに違法な条件が注入され、結果の結果が予期しないデータを含む場合、プログラムロジックは次のように偏っています。
誤差条件:上記の例のように、ロジックは$ result-> num_rows> 0が真であると判断しますが、実際には、返されたデータがすべてである可能性があります。
データリーク:攻撃者は、他のユーザーのプライバシー情報を読むために条件を構築できます。
混乱した後続の操作:許可判断を下し続ける場合、結果に基づいてレコードやその他の操作を変更する場合、結果はさらに深刻になります。
sqlインジェクションは、 prepare()とbind_param()を使用することにより、完全に防ぐことができます。
<?php
$conn = new mysqli("localhost", "root", "password", "mydb");
$username = $_GET['username'];
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
if ($result && $result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
echo "ユーザー: " . $row["username"] . ",郵便: " . $row["email"] . "<br>";
}
} else {
echo "未找到ユーザー";
}
$stmt->close();
$conn->close();
?>
前処理ステートメントを使用した後、パラメーターが自動的に逃げてタイプチェックされ、ソースからの注入を防ぎます。
セキュリティ保証の補足として、前処理を置き換えることはできませんが、すべてのユーザー入力は必要な検証の対象となる必要があります。例えば:
$username = filter_input(INPUT_GET, 'username', FILTER_SANITIZE_STRING);
または、違法な文字やキーワードを拒否するカスタムフィルタリングロジック。
さまざまなモジュールの開発者からの繰り返しのミスを回避するために、データベースアクセスロジックを統一クラスまたは機能にカプセル化し、常に内部で前処理を使用し、SQLステートメントのスプライシングを禁止することをお勧めします。
MySQLI_RESULT自体はSQLインジェクションの問題を引き起こしませんが、UNESCAPED SQLステートメントで使用すると、クエリ段階で深刻な隠れた危険をもたらします。ユーザーの入力が関与している限り、クエリ操作がどれほど無害であっても、前処理ステートメントを使用する必要があります。
覚えておいてください:**単なるユーザー名であっても、入力を信用しないでください。 ** M66.NETなどのオンラインサービスでは、これらの基本的なセキュリティ対策が無視されている場合、データは少なくとも異常であり、最悪の場合はシステムのクラッシュとデータが漏れます。
すべてのPHP開発者が合理的な保護対策を講じ、コードレベルからのSQLインジェクションを排除することは、揺るぎない責任です。