7

通常、SQL インジェクションを防ぐために、PDO のプリペアド ステートメント、(int) への型キャスト、または PDO::quote() を使用します。このアプリケーションでは、クエリに追加する前に、PHP を使用して日付を変更する必要があります。SQL インジェクションを防ぐために追加の手順を実行する必要がありますか? それとも安全ですか? ありがとう

$date = new DateTime($_GET['suspect_user_provided_date']);
$date->add(new DateInterval('P1D'));
$sql='SELECT * FROM table WHERE date<"'.$date->format('Y-m-d').'"';
4

6 に答える 6

9

DateTime オブジェクトが安全かどうかは問題ではありません。クエリに渡すデータはエスケープする必要があり、提供されたライブラリの安全性に依存しないでください。実装を変更した場合、新しい実装が安全かどうかを気にする必要はありません。必ず逃げるべきです。それ以外の場合は、関数ごとに答えようとします-そして覚えておいてください-SQLに対して安全でしたか? HTML用?CSV用?http /メールヘッダー用? ため...しないでください!クエリを送信するコード行は、DateTime の実装と、それが安全かどうかについて何も知らない必要があります。

于 2013-01-22T16:16:54.650 に答える
2

良い質問です: PHP 日付フォーマッターは SQL インジェクションから安全ですか?

出発点は、あなたの例に従ってフォーマットがハードコードされているかどうかだと思います。日付フォーマット文字列を使用すると、フォーマットされた日付に生の文字を含めることができますが、これには安全でない文字が含まれる可能性があります。そのため、フォーマット文字列に変数を使用している場合、答えは間違いなく「いいえ、安全ではありません」です。

与えられた例のように、ハードコードされた形式を使用している場合、それはより難しい質問ですが、「の出力がDateTime::format目的の形式から逸脱することはありますか?」ということになります。

これに対する答えは「はい」falseです。失敗しても出力できます。これにより SQL が壊れることはありませんが、予期しない結果になる可能性があります。

理論的には、それはそれが得るのと同じくらい悪いはずです。

ただし、防御的に考える必要があります。DateTime クラスには、不適切な形式の日付を出力する原因となる微妙なバグが見つからないことは言うまでもありません。通常、この種のバグはセキュリティ上の問題とは見なされません。それはただの迷惑だろう。特に、通常の使用では再現が難しい場合。しかし、それを SQL に直接渡すことと組み合わせると、簡単にセキュリティの問題になる可能性があります。

レッスンは防御的プログラミングです:すべてをサニタイズします。安全だと確信していても。自分の言語やフレームワードにバグがないと思い込まないでください。防御的プログラミングとは、あらゆるレベルで安全であることを意味し、予期しないバグがプログラムのさらに上位にある場合や制御できない場合、コードが攻撃にさらされることはありません。

于 2013-01-22T16:25:31.533 に答える
2

コンストラクターはDateTime引数を解析し、日付にしようとします。

できない場合はfalseを返します(実際には PHP 5.3 以降では例外がスローされます)。

SQL インジェクションは、インスタンスまたはfalse (例外をスロー)をnew DateTime返しながら、たとえば引用符を使用して SQL クエリ文字列を「だます」ことを試みるため、安全であることを意味します。ただし、とにかくエラーケースを処理できます(PHP 5.3以降)DateTime

try {
  $date = new DateTime($_GET['suspect_user_provided_date']);
}
catch (Exception $e) {
  echo "Error";
  exit;
}

$date->add(new DateInterval('P1D'));
$sql='SELECT * FROM table WHERE date<"'.$date->format('Y-m-d').'"';
于 2013-01-22T16:14:37.203 に答える
1

あなたが投稿した例は安全です。しかし、準備済みステートメントを使用しないのはなぜですか? このような:

     $pdo = new PDO($dsn, $user, $pass, $options = array (
        PDO::ATTR_ERRMODE,  PDO::ERRMODE_EXCEPTION
     ));

     $date = new DateTime($_GET['suspect_user_provided_date']);
     $date->add(new DateInterval('P1D'));

     $sql='
     SELECT
        * 
     FROM table 
     WHERE date < :dt';

     $stmt = $pdo->prepare($sql);
     $params = array (
        'dt' => $date->format('Y-m-d')
     );
     try {
         $res = $pdo->execute($params);
     } catch (PDOException $e) {
         echo $e->getMessage();
     }
于 2013-01-22T16:13:44.297 に答える
1

SQL に関して言えば、何が安全で何が安全でないかを考えないほうがよい場合がよくあります。準備されたステートメントで処理するだけです:

$stmt = $db->prepare('SELECT * FROM table WHERE `date` < :now');
$stmt->execute(array(
    ':now' => $date->format('Y-m-d'),
));
于 2013-01-22T16:17:07.703 に答える
0

日付の出力形式によって異なります。形式を変更して何らかのテキスト (現在のロケールでの月や日の名前など) を出力する場合、引用符が含まれている可能性があるため、安全でない (または少なくとも失敗する) クエリが発生する可能性があります。または、何らかの理由で自分で引用符を付けることができます。そうです、疑うのではなくpdo->quote()、準備されたステートメントを使用してください。

// safe
$date = new DateTime($_GET['suspect_user_provided_date']);
$date->add(new DateInterval('P1D'));
$sql='SELECT * FROM table WHERE date<"'.$date->format('Y-m-d').'"';

// failing
$date = new DateTime($_GET['suspect_user_provided_date']);
$date->add(new DateInterval('P1D'));
$sql='SELECT * FROM table WHERE date<"'.$date->format('\O\"\h\a\i \t\o\d\a\y \i\s Y-m-D').'"';

// not failing, whatever format you are using, using pdo::quote
$date = new DateTime($_GET['suspect_user_provided_date']);
$date->add(new DateInterval('P1D'));
$sql='SELECT * FROM table WHERE date<'.$dbh->quote($date->format('\O\"\h\a\i \t\o\d\a\y \i\s Y-m-D'));

// not failing, whatever format you are using, using prepared statments
$stmt = $dbh->prepare('SELECT * FROM table WHERE date < :date');
$date = new DateTime($_GET['suspect_user_provided_date']);
$date->add(new DateInterval('P1D'));
$stmt->bindValue(':date', $date->format('\O\"\h\a\i \t\o\d\a\y \i\s Y-m-D'), PDO::PARAM_STR);
$stmt->execute();
于 2013-01-22T16:27:23.427 に答える