ホームページ  >  記事  >  バックエンド開発  >  php_PHP チュートリアルで SQL インジェクションを防ぐための最良の解決策

php_PHP チュートリアルで SQL インジェクションを防ぐための最良の解決策

WBOY
WBOYオリジナル
2016-07-21 15:11:45710ブラウズ

ユーザーが 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));

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/326796.html技術記事ユーザーが SQL ステートメントに直接挿入されるクエリを入力すると、アプリケーションは次の例のように SQL インジェクションに対して脆弱になります。 次のようにコードをコピーします: $unsafe_variable =...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。