Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Bezpieczne wdrożenie konfigurowalnego systemu łączenia

Robisz tak dobrze, że naprawdę czuję się winny, gdy mówię, że robisz coś złego! :)

Do parametryzacji wartości pól można używać tylko przygotowanych instrukcji — nie można używać identyfikatorów SQL, takich jak nazwy kolumn lub tabel. Dlatego nie będziesz w stanie przekazać A.x , B.z itp. do swojego JOIN kryteria za pomocą przygotowanych parametrów zestawienia:musisz zamiast tego zrób to, co wydaje się strasznie złe i bezpośrednio połącz je w łańcuch SQL.

Jednak, nie wszystko stracone. W pewnej niejasnej kolejności preferencji możesz:

  1. Zaprezentuj użytkownikowi listę opcji, z której następnie ponownie asemblujesz 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>
    

    Następnie Twój moduł obsługi formularza:

    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";
    

    Takie podejście ma tę zaletę, że poza narażaniem PHP (w takim przypadku będziesz miał znacznie większe obawy niż wstrzyknięcie SQL), arbitralny SQL absolutnie nie może znaleźć drogę do RDBMS.

  2. Upewnij się, że dane wprowadzone przez użytkownika odpowiadają jednej z oczekiwanych wartości:

    <select name="join_a">
      <option>x</option>
      <option>y</option>
    </select>
    <select name="join_b">
      <option>z</option>
      <option>y</option>
    </select>
    

    Następnie Twój moduł obsługi formularza:

    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]";
    

    To podejście opiera się na in_array PHP funkcja dla bezpieczeństwa (a także ujawnia użytkownikowi nazwy podstawowych kolumn, ale biorąc pod uwagę twoją aplikację, wątpię, czy jest to problem).

  3. Wykonaj pewne czyszczenie danych wejściowych, na przykład:

    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']) . '`'
    

    Chociaż tutaj cytujemy dane wprowadzone przez użytkownika i zastępujemy wszelkie próby ucieczki od tego cytowania, to podejście może być pełne wszelkiego rodzaju wad i luk (w każdym mb_ereg_replace PHP funkcji lub obsługi przez MySQL specjalnie spreparowanych ciągów znaków w identyfikatorze w cudzysłowie).

    Jest daleko lepiej, jeśli to w ogóle możliwe, użyć jednej z powyższych metod, aby całkowicie uniknąć wstawiania ciągów zdefiniowanych przez użytkownika do własnego SQL.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dodawanie danych do bazy danych MySQL z formularza HTML

  2. Tabela eksportu mysql na podstawie określonego warunku

  3. Bardziej wydajne, aby mieć więcej kolumn lub więcej wierszy?

  4. Jak mogę ograniczyć użytkownika MySQL do określonych tabel?

  5. MySQL - Złożoność:SELECT COUNT(*) FROM MyTable;