次の例のように、データベース選択のユーザー入力を無害化するためにintvalのみを使用しても安全ですか?
$id = intval($_GET['id']);
$query = "SELECT * FROM table WHERE id='$id'";
intval
は整数を生成することが保証されています(0
それが「失敗する」場合)、整数はMySQLクエリで使用しても安全です。この答え https://stackoverflow.com/a/3208089/458614 on SOは同意します:
はい、intval()は安全です。 (明らかに)整数の形式ではSQLキーワード(または引用符など)を入れることができないため、パラメーターが整数に変換されるときにSQLインジェクションを実行する方法はまったくありません。
SQL以外の用途でも同じことが言えると思います。
経験則として、入力がコード自体以外からのものである場合、提供されたデータは「汚染されている」と見なされます。値が期待どおりであり、SQLステートメント(注入)を台無しにしないことを確認する必要があります。
PDOを使用/利用せず、ステートメントでマーカーを使用する理由を質問しますが、これらは自動的に処理されます。
しかし、私はこのようなことをすることを選択します(三項演算子を使用して):
$id = (is_numeric($id) && $id > 0) ? $id : false;
if ($id !== false) {
... code goes here ...
}
$id
が現実的な整数である可能性が2倍になります。
次の例のように、データベース選択のためのユーザー入力を無害化するためにintvalのみを使用しても安全ですか?
短い答え:いいえ。
OK、intval()は常にSQLを壊さない整数値を提供します。
問題は、返される値が整数であるのに、有効 1であるかどうかです。 保証 intvalによって返される値(たとえば0)がneverがrealデータレコードに対応することはできますか?それ以上のチェックを行わないコードでは、誤って0のキーでレコードを作成し、[すべて]が無効な数値を入力しているため、多くのユーザーが同じレコードにアクセスする可能性があります。良くない。
「IDは数値でなければなりません」のような丁寧なエラーメッセージが必要な場合にのみ使用できます。
Intは、考えられるあらゆる状況に対して定義上安全ですが、CLIコマンドのパラメーターとして使用する場合は、先頭のハイフンがパラメーターの代わりにフラグとして解釈される可能性があるため、負でないことを確認してください。ストレージサイズに制限がある場合は、オーバーフローが発生する可能性があるため、境界に注意してください。
ただし、これを頻繁に行う場合は、ユーザー入力の検証メソッドを多数作成する傾向があります。何かのようなもの:
_public function getValidInt(
string $name,
int $minValue=PHP_INT_MIN,
int $maxValue=PHP_INT_MAX,
int $defaultValue=0
) {
assert($minValue < $maxValue, 'Min bound must be less than max.');
if (!array_key_exists($name, $_GET)) {
return $defaultValue;
}
$userValue = (int)$_GET[$name];
// Could instead return $defaultValue if it's out of bounds.
return min($maxValue, max($minValue, $userValue));
}
_
これにより、指定されていない場合に、汚染されていない境界チェックされた値を有効なデフォルト値で取得するのが非常に簡単になります。
文字列の場合、これは次のようになります。
_public function getValidString(
string $name,
string $validationRegex='.*',
int $minLength=0,
int $maxLength=PHP_INT_MAX,
int $defaultValue=''
)
_
...など。
プロジェクトの早い段階でそのようなものを追加することは、すべてのユーザー入力について検討することを意味し、プロジェクトの終わりに近づくにつれ、「すべてのユーザー入力を検証する」という巨大な技術的借金タスクを蓄積しません。すべてがすでに正しいでしょう。文字列はホワイトリストに登録され、intは境界チェックされます。
入力のエスケープと拘束は、データベースでの使用、HTMLとしての表示などのためにエスケープしない個別の懸念として理想的に扱う必要があります。文字列から悪意のあるHTMLタグを削除することは、入力時に行う必要があります(画面に名前を表示していない場合でも、データベースに保存されている<span onclick="alert('whee')">Fred</span>
という名前のユーザーはいないはずです。HTMLまたはMySQLまたはコマンドラインに変数をスローする前にエスケープすると、最後の最後の確認になりますonlyのチェックではなく、変数を確実に保存します。
最初に、$ idが有効な数値かどうかを確認し(is_numericを使用)、最後に$ idを型(int)にキャストします。