FlawOpen

flawopen.com/SQL Injection di PHP/mysqli vs PDO

MySQLi vs PDO: prepared statement yang aman

Halaman referensi
Jawaban singkat

Prepared statement menjaga instruksi SQL tetap dan mengirim nilai input terpisah, seperti mengisi kotak berlabel. PDO dan MySQLi sama-sama bisa melakukannya. Keamanan berasal dari binding nilai yang benar, bukan nama library.

Kueri yang sama disiapkan dengan kedua API

TIDAK AMAN — SQL dengan data permintaan
$userId = $_GET['id'];
$sql = "SELECT id, email FROM users WHERE id = " . $userId;

// Both calls execute the already-built SQL string:
$rows = $mysqli->query($sql);
$rows = $pdo->query($sql);
AMAN — ikat nilai di kedua API
// PDO
$stmt = $pdo->prepare(
    "SELECT id, email FROM users WHERE id = :id"
);
$stmt->execute(["id" => $userId]);

// MySQLi
$stmt = $mysqli->prepare(
    "SELECT id, email FROM users WHERE id = ?"
);
$stmt->bind_param("i", $userId);
$stmt->execute();

Portabilitas database adalah perbedaan utama PDO

Portabilitas database adalah perbedaan utama PDO

PDO menyediakan antarmuka umum untuk beberapa driver; MySQLi berfokus pada MySQL dan MariaDB. PDO tidak otomatis membuat SQL portabel: dialek, perilaku driver, dan fitur tetap berbeda.

Gaya placeholder berbeda

PDO dapat memakai placeholder bernama seperti :id atau posisi ?, bergantung driver; jangan mencampurnya dalam satu statement. MySQLi memakai ?. Keduanya mengikat nilai, bukan nama tabel/kolom, kata kunci, atau arah urutan.

Mode persiapan PDO bergantung pada driver

Driver PDO dapat memakai prepare native atau emulasi. Pada MySQL, PDO::ATTR_EMULATE_PREPARES mengatur emulasi jika didukung; driver dapat mengemulasi atau fallback saat prepare native tak tersedia/gagal. Ikuti dokumentasi driver. Pengaturan ini tidak mengamankan SQL interpolasi: pertahankan teks tetap dan ikat nilai dalam mode apa pun.

Aturan mencegah SQL Injection pada kedua library

Gunakan prepare() dan ikat setiap nilai tak tepercaya. Pertahankan sintaks SQL; pilih identifier dinamis dari peta server yang ketat atau varian kueri terbatas. Prepared statement tidak mengotorisasi akses baris: batasi kueri ke pengguna terautentikasi bila perlu. Pada LIKE, binding mencegah injeksi sintaks SQL, tetapi % dan _ tetap wildcard kecuali di-escape untuk pencarian literal.

Memilih PDO atau MySQLi

Pertanyaan umum

Apakah placeholder bernama PDO lebih aman daripada tanda ? MySQLi?

Tidak. Keduanya mengikat nilai dengan aman bila kueri dipersiapkan dan nilainya diikat. Nama placeholder dapat lebih mudah dibaca, tetapi tidak mengikat identifier atau menggantikan otorisasi.

Haruskah emulasi prepare PDO selalu dinonaktifkan?

Tidak sebagai aturan umum. Dukungan dan fallback driver berbeda. Periksa dokumentasi dan kebutuhan aplikasi. Dalam mode apa pun, pertahankan struktur SQL dan kirim nilai sebagai parameter.

Bisakah prepared statement mengikat nama tabel atau kolom?

Tidak. Parameter mewakili nilai, bukan identifier atau kata kunci SQL. Petakan pilihan klien ke kumpulan fragmen tepercaya yang terbatas di server.

Referensi

Lihat juga SQL Injection (CWE-89): cara kerja dan cara mencegahnya di setiap bahasa — flawopen.com Apakah NHibernate aman dari SQL Injection? Injeksi NoSQL MongoDB: filter kueri aman Apakah format string berbahaya untuk ID numerik? Apa itu kueri terparameterisasi? Apakah Prisma $queryRaw aman dari SQL Injection? Apakah interpolasi string di Rails where() aman?