Mysql
 sql >> база данни >  >> RDS >> Mysql

Внедряване на конфигурируема система за присъединяване, безопасно

Правите толкова много правилно, че всъщност се чувствам виновен, като посоча, че правите нещо нередно! :)

Можете да използвате само подготвени изрази, за да параметризирате стойности на полета, а не SQL идентификатори като имена на колони или таблици. Следователно няма да можете да преминете A.x , B.z и т.н. във вашия JOIN критерии чрез подготвени параметри на израза:трябва вместо това направете това, което се чувствате ужасно погрешно и ги свържете директно във вашия SQL низ.

Не всичко обаче е загубено. В някакъв неясен ред на предпочитание можете:

  1. Представете на потребителя списък с опции, от който впоследствие сглобявате отново 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>
    

    След това вашият манипулатор на формуляри:

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

    Този подход има предимството, че освен компрометирането на PHP (в този случай ще имате много по-големи притеснения от SQL инжектирането), произволният SQL абсолютно не може намери своя път във вашата RDBMS.

  2. Уверете се, че въведеното от потребителя отговаря на една от очакваните стойности:

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

    След това вашият манипулатор на формуляри:

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

    Този подход разчита на in_array на PHP функция за безопасност (и също така излага на потребителя имената на основните ви колони, но предвид приложението ви се съмнявам, че това е проблем).

  3. Извършете известно почистване на входа, като например:

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

    Докато тук цитираме въведеното от потребителя и заменяме всеки опит на потребителя да избяга от това цитиране, този подход може да бъде пълен с всякакви недостатъци и уязвимости (в mb_ereg_replace на PHP) функция или обработката на MySQL на специално изработени низове в идентификатор в кавички).

    Това е далече по-добре, ако изобщо е възможно, да използвате един от горните методи, за да избегнете вмъкването на дефинирани от потребителя низове в 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. Не мога да стартирам пакетна актуализация поради mysql2 gem

  2. Точното значение на клаузата за външния ключ на MySQL „при ограничение за изтриване“.

  3. Продължете да попълвате HTML формуляр след затваряне и повторно отваряне

  4. RAW SQL заявка със Zend Framework

  5. Справяне с времената и след полунощ