Děláte tolik dobře, že se vlastně cítím provinile, když vám poukazuji na to, že děláte něco špatně! :)
K parametrizaci hodnot polí můžete použít pouze připravené příkazy – nikoli identifikátory SQL, jako jsou názvy sloupců nebo tabulek. Proto nebudete moci předat A.x
, B.z
atd. do vašeho JOIN
kritéria pomocí připravených parametrů výpisu:musíte místo toho udělejte to, co se vám zdá strašně špatné, a přímo je zřetězte do svého řetězce SQL.
Není však vše ztraceno. V určitém vágním pořadí preferencí můžete:
-
Předložte uživateli seznam možností, ze kterého následně znovu sestavíte 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>
Potom váš obslužný program formuláře:
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";
Tento přístup má tu výhodu, že kromě kompromitování PHP (v takovém případě budete mít mnohem větší starosti než SQL injection), libovolné SQL absolutně nemůže najít cestu do vašeho RDBMS.
-
Ujistěte se, že uživatelský vstup odpovídá jedné z očekávaných hodnot:
<select name="join_a"> <option>x</option> <option>y</option> </select> <select name="join_b"> <option>z</option> <option>y</option> </select>
Potom váš obslužný program formuláře:
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]";
Tento přístup se opírá o PHP
in_array
funkce pro bezpečnost (a také zpřístupňuje uživateli vaše základní názvy sloupců, ale vzhledem k vaší aplikaci pochybuji, že je to problém). -
Proveďte určité čištění vstupu, například:
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']) . '`'
Zatímco zde citujeme uživatelský vstup a nahrazujeme jakýkoli pokus uživatele uniknout z tohoto citování, tento přístup může být plný nejrůznějších nedostatků a zranitelností (buď v PHP
mb_ereg_replace
funkce nebo MySQL manipulace se speciálně vytvořenými řetězci v rámci identifikátoru v uvozovkách).Je to daleko je lepší, pokud je to možné, použít jednu z výše uvedených metod, abyste se úplně vyhnuli vkládání uživatelsky definovaných řetězců do svého SQL.