ホームページ  >  記事  >  バックエンド開発  >  PHPにおけるSQLインジェクション防止の詳細説明、phpsqlインジェクションの詳細説明_PHPチュートリアル

PHPにおけるSQLインジェクション防止の詳細説明、phpsqlインジェクションの詳細説明_PHPチュートリアル

WBOY
WBOYオリジナル
2016-07-13 10:10:51982ブラウズ

PHPでSQLインジェクションを防ぐ方法の詳細説明、phpsqlインジェクションの詳細説明

問題の説明:
ユーザーが入力したデータが処理されずに SQL クエリ ステートメントに挿入された場合、次の例のように、アプリケーションは SQL インジェクション攻撃の対象となる可能性が高くなります。

コードをコピーします コードは次のとおりです:
$unsafe_variable = $_POST['user_input']
mysql_query("INSERT INTO `table` (`column`) VALUES ('" . $unsafe_variable . "')");

ユーザーの入力は次のようになるためです:

コードをコピーします コードは次のとおりです:
値'); DROP TABLE テーブル;--

すると、SQLクエリは次のようになります:

コードをコピーします コードは次のとおりです:
INSERT INTO `テーブル` (`列`) VALUES('値') テーブル;--')

SQLインジェクションを防ぐためにはどのような効果的な方法を採用すべきでしょうか?

ベストアンサー(テオさんから):

準備されたステートメントとパラメーター化されたクエリを使用します。準備されたステートメントとパラメータはそれぞれ解析のためにデータベース サーバーに送信され、パラメータは通常の文字として扱われます。このアプローチにより、攻撃者による悪意のある SQL の挿入が防止されます。 このメソッドを実装するには 2 つのオプションがあります:

1. PDOを使用します:

コードをコピーします コードは次のとおりです:
$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

デフォルトで PDO を使用しても、MySQL データベースは実際のプリペアド ステートメントを実行しないことに注意してください (理由については以下を参照)。この問題を解決するには、準備されたステートメントの PDO エミュレーションを無効にする必要があります。 PDO を正しく使用してデータベース接続を作成する例は次のとおりです:

コードをコピーします コードは次のとおりです:
$dbConnection = 新しい 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);

上記の例では、エラー報告モード(ATTR_ERRMODE)は必要ありませんが、追加することをお勧めします。このようにして、致命的なエラー (Fatal Error) が発生した場合でも、スクリプトの実行は停止されませんが、プログラマは PDOExceptions をキャッチしてエラーを適切に処理できるようになります。 ただし、最初の setAttribute() 呼び出しが必要です。これにより、PDO によるプリペアド ステートメントのシミュレーションが無効になり、実際のプリペアド ステートメントが使用されます。つまり、MySQL がプリペアド ステートメントを実行します。これにより、ステートメントとパラメータが MySQL に送信される前に PHP によって処理されていないことが保証され、攻撃者による悪意のある SQL の挿入が防止されます。理由を理解するには、このブログ記事「PDO の抗注射原理の分析と PDO 使用時の注意事項」を参照してください。 PHP の古いバージョン (5.3.6 未満) では、PDO のコンストラクターの DSN に charset を設定できないことに注意してください。「charset パラメータをサイレントに無視する」を参照してください。

分析

前処理と解析のために SQL ステートメントをデータベース サーバーに送信するとどうなりますか?プレースホルダ (上記の例のように ? または :name) を指定して、データベース エンジンにフィルタリングする場所を伝えます。 execute を呼び出すと、準備されたステートメントは指定したパラメーター値と結合されます。 重要な点はここです。パラメータ値は SQL 文字列ではなく、解析された SQL ステートメントと結合されます。 SQL インジェクションは、SQL ステートメントの作成時に悪意のある文字列を含むスクリプトによってトリガーされます。したがって、SQL ステートメントとパラメーターを分離することで、SQL インジェクションのリスクを回避できます。送信するパラメータ値は通常の文字列として扱われ、データベース サーバーによって解析されません。上記の例に戻ると、$name 変数の値が 'Sarah'; DELETE FROM 従業員の場合、実際のクエリは、name フィールドの値が 'Sarah' である従業員内のレコードを検索することになります。 プリペアド ステートメントを使用するもう 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/932482.html技術記事 PHP で SQL インジェクションを防ぐ方法の詳細な説明、phpsql インジェクションの詳細な説明 問題の説明: ユーザーが入力したデータが処理されずに SQL クエリ ステートメントに挿入されると、アプリケーションはおそらく...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。