Anda melakukan banyak hal dengan benar sehingga saya benar-benar merasa bersalah menunjukkan bahwa Anda melakukan sesuatu yang salah! :)
Anda hanya dapat menggunakan pernyataan yang disiapkan untuk membuat parameter nilai bidang—bukan pengidentifikasi SQL seperti nama kolom atau tabel. Oleh karena itu, Anda tidak akan dapat melewati A.x
, B.z
dll. ke dalam JOIN
kriteria melalui parameter pernyataan yang disiapkan:Anda harus alih-alih lakukan apa yang terasa sangat salah dan langsung gabungkan ke dalam string SQL Anda.
Namun, semua tidak hilang. Dalam beberapa urutan preferensi yang tidak jelas, Anda dapat:
-
Sajikan pengguna dengan daftar opsi, dari mana Anda kemudian menyusun kembali SQL:
<select name="join_a"> <option value="1">x</option> <option value="2">y</option> </select> <select name="join_b"> <option value="1">z</option> <option value="2">y</option> </select>
Kemudian penangan formulir Anda:
switch ($_POST['join_a']) { case 1: $acol = 'x'; break; case 2: $acol = 'y'; break; default: die('Invalid input'); } switch ($_POST['join_b']) { case 1: $bcol = 'z'; break; case 2: $bcol = 'y'; break; default: die('Invalid input'); } $sql .= "FROM A JOIN B ON A.$acol = B.$bcol";
Pendekatan ini memiliki keuntungan bahwa, selain mengorbankan PHP (dalam hal ini Anda akan memiliki masalah yang jauh lebih besar daripada injeksi SQL), SQL arbitrer sama sekali tidak bisa temukan jalannya ke RDBMS Anda.
-
Pastikan input pengguna cocok dengan salah satu nilai yang diharapkan:
<select name="join_a"> <option>x</option> <option>y</option> </select> <select name="join_b"> <option>z</option> <option>y</option> </select>
Kemudian penangan formulir Anda:
if (!in_array($_POST['join_a'], ['x', 'y']) or !in_array($_POST['join_b'], ['z', 'y'])) die('Invalid input'); $sql .= "FROM A JOIN B ON A.$_POST[join_a] = B.$_POST[join_b]";
Pendekatan ini bergantung pada
in_array
PHP berfungsi untuk keamanan (dan juga memperlihatkan kepada pengguna nama kolom dasar Anda, tetapi mengingat aplikasi Anda, saya ragu itu menjadi perhatian). -
Lakukan beberapa pembersihan input, seperti:
mb_regex_encoding($charset); // charset of database connection $sql .= 'FROM A JOIN B ON A.`' . mb_ereg_replace('`', '``', $_POST['join_a']) . '`' . ' = B.`' . mb_ereg_replace('`', '``', $_POST['join_b']) . '`'
Sementara kami di sini mengutip input pengguna dan mengganti upaya apa pun oleh pengguna untuk melarikan diri dari kutipan itu, pendekatan ini bisa penuh dengan segala macam kekurangan dan kerentanan (baik dalam
mb_ereg_replace
PHP fungsi atau penanganan MySQL terhadap string yang dibuat khusus dalam pengenal yang dikutip).Itu jauh lebih baik jika memungkinkan untuk menggunakan salah satu metode di atas untuk menghindari penyisipan string yang ditentukan pengguna ke dalam SQL seseorang sama sekali.