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. ユーザー入力が期待値の1つと一致することを確認してください:

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

      このアプローチは、PHPのin_arrayに依存しています。 安全のために機能します(また、基になる列名をユーザーに公開しますが、アプリケーションを考えると、それが問題になるとは思えません)。

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

      ここではユーザー入力を引用し、その引用から逃れるためのユーザーによる試みを置き換えますが、このアプローチはあらゆる種類の欠陥や脆弱性でいっぱいになる可能性があります(PHPのmb_ereg_replace 関数またはMySQLによる引用符で囲まれた識別子内の特別に細工された文字列の処理)

      遠い 可能であれば、上記の方法のいずれかを使用して、ユーザー定義の文字列をSQLに完全に挿入しないようにすることをお勧めします。



    1. 異なるスキーマから2つのテーブルをクエリする

    2. MySQLでインデックスを作成または削除するために存在する場合、どのように使用できますか?

    3. float LARAVELでメンバー関数addEagerConstraints()を呼び出す

    4. 進化する連絡先情報はデータベースを変更することを意味しますか?