Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Sicheres Implementieren eines konfigurierbaren Verbindungssystems

Du machst so viel richtig, dass ich mich tatsächlich schuldig fühle, darauf hinzuweisen, dass du etwas falsch machst! :)

Sie können nur vorbereitete Anweisungen verwenden, um Feldwerte zu parametrisieren – keine SQL-Bezeichner wie Spalten- oder Tabellennamen. Daher können Sie A.x nicht weitergeben , B.z etc. in Ihr JOIN Kriterien durch vorbereitete Anweisungsparameter:Sie müssen tun Sie stattdessen das, was sich schrecklich falsch anfühlt, und verketten Sie sie direkt in Ihren SQL-String.

Es ist jedoch nicht alles verloren. In einer vagen Präferenzreihenfolge können Sie:

  1. Präsentieren Sie dem Benutzer eine Optionsliste, aus der Sie anschließend das SQL:

    wieder zusammensetzen
    <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>
    

    Dann Ihr Formular-Handler:

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

    Dieser Ansatz hat den Vorteil, dass, abgesehen von der Kompromittierung von PHP (in diesem Fall haben Sie weitaus größere Bedenken als die SQL-Injektion), beliebiges SQL absolut nicht kann den Weg in Ihr RDBMS finden.

  2. Stellen Sie sicher, dass die Benutzereingabe mit einem der erwarteten Werte übereinstimmt:

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

    Dann Ihr Formular-Handler:

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

    Dieser Ansatz basiert auf in_array von PHP Funktion aus Sicherheitsgründen (und zeigt dem Benutzer auch Ihre zugrunde liegenden Spaltennamen an, aber angesichts Ihrer Anwendung bezweifle ich, dass dies ein Problem darstellt).

  3. Führen Sie eine Eingabebereinigung durch, wie zum Beispiel:

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

    Während wir hier die Benutzereingabe zitieren und jeden Versuch des Benutzers ersetzen, diesem Zitieren zu entgehen, könnte dieser Ansatz voll von allen möglichen Fehlern und Schwachstellen sein (in PHPs mb_ereg_replace Funktion oder MySQLs Umgang mit speziell gestalteten Zeichenfolgen innerhalb eines Bezeichners in Anführungszeichen).

    Es ist weit es ist besser, wenn überhaupt möglich, eine der oben genannten Methoden zu verwenden, um das Einfügen von benutzerdefinierten Zeichenfolgen in das eigene SQL insgesamt zu vermeiden.