1

パラメータ化されたクエリに関するいくつかの基本的な質問があります

次のコードを検討してください。

$id = (int)$_GET['id'];
mysql_query("UPDATE table SET field=1 WHERE id=".$id);

パラメータ化されたクエリを使用して同じことを行う

$sql = "UPDATE table SET field=1 WHERE id=?";
$q = $db->prepare($sql); 
$q->execute(array($_GET['id']));

私の質問は次のとおりです。

  1. 最初のコード ((int)キャストを含む) が安全でない状況はありますか?
  2. コードの 2 番目の部分は問題ありません$_GET['id']か、それとも int にキャストする必要がありますか?
  3. 2 番目のコードに既知の脆弱性はありますか? つまり、2 番目のクエリを使用している場合、SQL 攻撃を行う方法はありますか?
4

2 に答える 2

3
  1. 最初のコード (つまり (int) キャスト) が安全でない状況はありますか?

    私は PHP の専門家ではありませんが、あるべきではないと思います。PHP には、ここで悪用される可能性のある (既知または未発見の) バグがないというわけではありません。

  2. コードの 2 番目の部分は問題ありませんか、それとも $_GET['id'] を int にキャストする必要がありますか?

    同様に、コードの 2 番目の部分はまったく問題ありません。データ型が文字列であっても、MySQL はそれがパラメーターであるため SQL に対して評価しないことを認識し、したがってリテラル値としてのみ扱われます。ただし、キャストを実行してもはありません(これにより、MySQL のパラメーター処理の欠陥を回避できます)。両方を実行することをお勧めします。

    編集- @Tomalak は、キャストが誤ったデータをもたらす可能性があることについて非常に良い点を指摘しており、最初にis_numeric();などのサニティ チェックで入力を検証することを提案しています。私は心から同意します。

  3. 2 番目のコードに既知の脆弱性はありますか? つまり、2 番目のクエリを使用している場合、SQL 攻撃を行う方法はありますか?

    私の知る限りではありません。

于 2012-05-01T07:49:51.643 に答える
2
  1. (int)0変換が失敗すると生成されます。これにより、間違ったレコードが更新される可能性があります。その上、それはずさんで、後でクエリがより複雑になったときに適切な型キャストを「忘れる」ためのオープンな招待状です。現在の形式では
    安全ですが(間違ったレコードの更新に対してではなく、SQL インジェクションに対して)、私はまだお勧めしません。クエリがより複雑になると、とにかく準備済みステートメントを使用することになります。そのため、一貫性のためにも、最初から正しく実行してください。

  2. それもずさんです。パラメータは文字列として DB に転送され、DB はそれをキャストしようとします。これは (SQL インジェクションに対して) 安全ですが、無効なデータを渡したときに DB サーバーがどのように反応するかを正確に把握していない限り、事前に値をサニタイズ (is_numeric()およびキャスト) する必要があります。

  3. いいえ(PDO にバグがない限り)。

経験則として:

  • チェックされていないデータをデータベースに渡して、正しいことが起こることを期待しないでください。
  • 故意に無効なデータを渡したり、他のシステムが特定の方法で反応することを信頼したりしないでください。健全性チェックとエラー処理を自分で行います。
  • 「ああ、それは変換されますが、とにかく0ID付きのレコードがない0ので大丈夫です」としないでください。あなたの思考プロセスの一部です。
于 2012-05-01T07:51:32.000 に答える