ユーザーが SQL ステートメントに直接挿入されるクエリを入力すると、アプリケーションは次の例のように SQL インジェクションに対して脆弱になります:
コードをコピーします コードは次のとおりです:
$ unsafe_variable = $_POST[ 'user_input'];
mysql_query("INSERT INTO table (column) VALUES ('" . $unsafe_variable . "')");
これは、ユーザーが VALUE のようなものを入力できるためです"); DROP TABLE table; - , make クエリは次のようになります:
コードをコピーします。 コードは次のとおりです:
INSERT INTO table (column) VALUES('VALUE');'
これを防ぐにはどうすればよいでしょうか? 以下、Theo の答えを見てみましょう
プリペアドステートメントとパラメータ化されたクエリを使用します。パラメータを含む SQL ステートメントはデータベース サーバーに送信され、解析されます。攻撃者が悪意を持って SQL を挿入することは不可能です。
これを実現するには基本的に 2 つのオプションがあります:
1. PDO (PHP Data Objects) を使用します
コードをコピーします コードは次のとおりです:
$stmt = $pdo->prepare('SELECT * FROM 従業員 WHERE name = :name ');
$stmt->execute(array(':name' => $name));
foreach ($stmt as $row) {
// $row
で何かをする}
2. mysqliを使用します
コードをコピーします コードは次のとおりです:
$stmt = $dbConnection->prepare('SELECT * FROM 従業員 WHERE name = ?');
$stmt->bind_param('s', $name);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// $row
で何かをする}
PDO (PHP データ オブジェクト)
PDO を使用して MySQL データベースにアクセスする場合、デフォルトでは実際のプリペアド ステートメントは使用されないことに注意してください。この問題を解決するには、準備されたステートメントのエミュレーションを無効にする必要があります。 PDO を使用して接続を作成する例は次のとおりです。
コードをコピーします コードは次のとおりです。
$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1; charset=utf8', 'user', 'pass');
$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
上記の例では、エラーモード ERRMODE は厳密には必須ではありませんが、追加することをお勧めします。このメソッドは、致命的なエラーが発生した場合でもスクリプトを停止しません。そして、開発者にエラー (PDOException がスローされたとき) を捕捉する機会を与えます。
setAttribute() 行は必須であり、エミュレートされたプリペアド ステートメントを無効にし、実際のプリペアド ステートメントを使用するように PDO に指示します。これにより、ステートメントと値が MySQL データベース サーバーに送信される前に PHP によって解析されなくなります (攻撃者が悪意のある SQL を挿入する機会はありません)。
もちろん、コンストラクター オプションで文字セット パラメーターを設定できます。特に、「古い」PHP バージョン (5.3.6) では DSN の文字セット パラメーターが無視されることに注意してください。
説明
渡したSQLプリペアドステートメントがデータベースサーバーによって解析され、コンパイルされるとどうなりますか?文字 (上記の例では、? や :name など) を指定して、データベース エンジンにフィルタリングする内容を伝え、execute を呼び出して、指定したパラメーター値と組み合わせて準備されたステートメントを実行します。
ここで最も重要なことは、パラメータ値が SQL 文字列ではなく、プリコンパイルされたステートメントと結合されることです。SQL インジェクションは、悪意のある文字列を含む SQL スクリプトを不正に作成し、それをデータベースに送信することによって機能します。個別の SQL パラメータを使用すると、リスクが軽減されます。プリペアド ステートメントを使用する場合、送信するパラメータは文字列としてのみ扱われます (ただし、データベース エンジンはパラメータの最適化を行う場合がありますが、上記ではもちろん最終的には数値になる可能性があります)。たとえば、変数 $name に「sarah';DELETE * FROMemployees」が含まれている場合、結果は検索文字列「'sarah';DELETE * FROMemployees」のみとなり、空のサーフェスは得られません。
プリペアド ステートメントを使用するもう 1 つの利点は、同じセッション内で同じステートメントを複数回実行する場合、解析とコンパイルが 1 回だけで済み、速度がある程度向上することです。 ああ、挿入方法を尋ねられたので、ここに例を示します (PDO を使用):
コードをコピーします
コードは次のとおりです:
$preparedStatement = $db->prepare(' INSERT INTO table (column) VALUES (:column)');$preparedStatement->execute(array(':column' => $unsafeValue));
http://www.bkjia.com/PHPjc/326796.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/326796.html技術記事ユーザーが SQL ステートメントに直接挿入されるクエリを入力すると、アプリケーションは次の例のように SQL インジェクションに対して脆弱になります。 次のようにコードをコピーします: $unsafe_variable =...