sql >> Databáze >  >> RDS >> Mysql

Bezpečná implementace konfigurovatelného spojovacího systému

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:

  1. 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.

  2. 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).

  3. 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.



  1. Monitorování změn tabulky v Oracle

  2. InnoDB:nalezeny duplicitní indexy – je to velmi špatné?

  3. Nainstalujte PHP s Postgresql na MAC pomocí homebrew

  4. Mysql Sloupec Průměrný čas?