sql >> Database >  >> RDS >> Mysql

Een configureerbaar verbindingssysteem implementeren, veilig

Je doet zoveel goed dat ik me eigenlijk schuldig voel om erop te wijzen dat je iets verkeerd doet! :)

U kunt alleen voorbereide instructies gebruiken om veldwaarden te parametreren, niet SQL-ID's zoals kolom- of tabelnamen. Daarom kunt u A.x . niet doorgeven , B.z enz. in uw JOIN criteria door middel van voorbereide verklaringsparameters:u moet doe in plaats daarvan wat vreselijk verkeerd aanvoelt en voeg ze direct samen in je SQL-string.

Alles is echter niet verloren. In een vage volgorde van voorkeur kun je:

  1. Geef de gebruiker een optielijst, waaruit u vervolgens de SQL weer samenstelt:

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

    Dan uw formulierbehandelaar:

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

    Deze aanpak heeft het voordeel dat, afgezien van het compromitteren van PHP (in dat geval heb je veel grotere zorgen dan SQL-injectie), willekeurige SQL absoluut niet kan. zijn weg vinden naar uw RDBMS.

  2. Zorg ervoor dat de gebruikersinvoer overeenkomt met een van de verwachte waarden:

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

    Dan uw formulierbehandelaar:

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

    Deze aanpak is gebaseerd op PHP's in_array functie voor de veiligheid (en stelt ook uw onderliggende kolomnamen bloot aan de gebruiker, maar gezien uw toepassing betwijfel ik of dat een probleem is).

  3. Voer wat invoeropschoning uit, zoals:

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

    Hoewel we hier de gebruikersinvoer citeren en elke poging van de gebruiker om aan dat citaat te ontsnappen vervangen, kan deze benadering vol zitten met allerlei fouten en kwetsbaarheden (in PHP's mb_ereg_replace functie of MySQL's behandeling van speciaal vervaardigde strings binnen een identifier tussen aanhalingstekens).

    Het is ver het is beter als het enigszins mogelijk is om een ​​van de bovenstaande methoden te gebruiken om te voorkomen dat door de gebruiker gedefinieerde strings helemaal in iemands SQL worden ingevoegd.



  1. Laravel - meerdere rijen invoegen en ID's ophalen

  2. Postgres - Functie om het snijpunt van 2 ARRAY's te retourneren?

  3. Hoe pgBackRest te gebruiken om een ​​back-up te maken van PostgreSQL en TimescaleDB

  4. Django ManyToMany door met meerdere databases