-4

このコードは SQL インジェクションの影響を非常に受けやすいと言われています。安全になるように変更するにはどうすればよいですか? 準備済みステートメントを使用するのが最善であることは知っていますが、それを壊さない方法は見つかりませんでした。

<?php

$con = new mysqli("localhost", "", "", "");
// Check connection
if (mysqli_connect_errno()) {
    echo "Failed to connect to MySQL: " . mysqli_connect_error();
}

$existsQuery = "select count(*) as count from entry where emailaddress like '" . $_POST[emailaddress] . "'";
$existsResult = mysqli_query($con, $existsQuery);

if ($existsResult->fetch_object()->count > 0) {
    header('Location: index2.php?email=exists');
} else {
    $sql = "INSERT INTO entry (firstname, lastname, emailaddress, favoritesong) VALUES ('$_POST[firstname]','$_POST[lastname]','$_POST[emailaddress]','$_POST[favoritesong]')";

    if (!mysqli_query($con, $sql)) {
        die('Error: ' . mysqli_error($con));
    }
    echo "1 record added";
}

mysqli_close($con);
?>
4

2 に答える 2

3

SQL インジェクションを回避するための重要な点は、文字列連結を使用してクエリを作成しないことです。

したがって、このようなクエリを作成する代わりに...

$sql = "select count(*) from entry where emailaddress like '" . $_POST[emailaddress] . "'";
$sth = $pdo->prepare($sql);
$sth->execute();

...代わりにバインディングを使用します。バインディングでは、? プレースホルダーは電子メールアドレスに置き換えられますが、データベースは入力を引用する方法とエスケープする方法を知っています...

$sql = 'select count(*) from entry where emailaddress like ?';
$sth = $pdo->prepare($sql);
$sth->bindParam(1, $_POST[emailaddress], PDO::PARAM_STR);
$sth->execute();

このパラメーター化されたクエリは、PDO と SQLi で機能します。SQL インジェクションがどのように機能するかのデモンストレーションをここで見ることができます。次の矢印をクリックして、間違ったユーザー入力を入力してください。

考慮すべきことがもう 1 つあります。バインディングは SQL インジェクションから一定の保護を提供しますが、これによってユーザー入力の検証が妨げられることはありません。あなたの例では、これは、入力が本当に電子メールアドレスであるかどうかを確認することを意味します。そうでない場合は、ユーザー入力を拒否するだけです。

于 2013-05-03T13:12:48.390 に答える
0

SQL に渡されるすべての変数、特にすべての $_POST と $_GET をエスケープする必要があります。

私見では、PDO を使用できます (引用の例: http://php.net/manual/en/pdo.quote.php )。

それが役立つことを願っています。

于 2013-05-03T12:47:17.263 に答える