Walaupun dokumentasi PDO mencadangkan bahawa penyediaan kenyataan menghapuskan keperluan untuk petikan parameter manual, jawapannya adalah bernuansa "ya ." PDO meniru penyataan yang disediakan untuk MySQL secara lalai, dan emulasi ini kadangkala boleh mewujudkan kelemahan yang boleh dieksploitasi.
Kerentanan berpotensi timbul apabila pengekodan sambungan melibatkan set aksara terdedah tertentu (cth., gbk , cp932) dan syarat berikut ialah met:
Dalam kes sedemikian, penyerang boleh membuat muatan yang mengandungi aksara multibait tidak sah dan mengeksploitasi percanggahan antara set aksara yang dijangkakan pada klien dan set aksara sebenar sambungan. Ini membolehkan mereka menyuntik aksara yang tidak disebut ke dalam rentetan pertanyaan yang dijana, yang membawa kepada potensi suntikan SQL.
Pencegahan:
Mitigasi:
Coretan kod berikut menggambarkan amalan selamat:
// PDO without emulated prepares $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $stmt = $pdo->prepare('SELECT * FROM test WHERE name = ? LIMIT 1'); $stmt->execute(array("xbf' OR 1=1 /*")); // PDO with DSN charset parameter $pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=gbk', $user, $password); $stmt = $pdo->prepare('SELECT * FROM test WHERE name = ? LIMIT 1'); $stmt->execute(array("xbf' OR 1=1 /*")); // MySQLi (always uses true prepared statements) $mysqli->query('SET NAMES gbk'); $stmt = $mysqli->prepare('SELECT * FROM test WHERE name = ? LIMIT 1'); $param = "xbf' OR 1=1 /*"; $stmt->bind_param('s', $param); $stmt->execute();
PDO kenyataan yang disediakan boleh menghalang suntikan SQL dengan berkesan apabila digunakan dengan betul dan bersama-sama dengan amalan selamat. Adalah penting untuk mengelakkan pengekodan yang terdedah, melumpuhkan persediaan yang dicontohi atau mendayakan mod NO_BACKSLASH_ESCAPES untuk mengurangkan kemungkinan kelemahan.
Atas ialah kandungan terperinci Adakah Penyata Disediakan PDO Benar-benar Selamat daripada Serangan Suntikan SQL?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!