7

php.netによると 、非推奨になっているため、 mysql_real_escape_string()を使用し、魔法の引用符をオフにする必要があります。

それで、それをオフにしてmysql_real_escape_string()を使用しましたが、次のコードのように使用するだけで十分ですか?

$value = "It's Time!";
$escaped_value = mysql_real_escape_string($value);

mysql_query("INSERT INTO table (column, column2) VALUES ('{$escaped_value}', "0")");

データベース内のデータを確認すると、$ valueの場合と同じように見えますが、そう"It's Time"ではありません"It\'s Time"。これは正常ですか?これは引用符の前にスラッシュを追加するべきではありませんか?

4

3 に答える 3

10

これは正しい動作であり、機能します。引用符は、データベースではなく、クエリでエスケープされます。SQLクエリの\'は、データベース内で'に変換する必要があります。

文字列をエスケープするので、SQLクエリが混乱することはなく、SQLクエリが文字列を制御文字として解釈せずにデータベースに引用符を入力できます。

エスケープされたクエリは次のようになります。

mysql_query("INSERT INTO table (column, column2) VALUES ('It\'s time', "0")");

データベースデータは「時間です」である必要があります。

エスケープされなかった場合は、次のようになります。

mysql_query("INSERT INTO table (column, column2) VALUES ('It's time', "0")");

「stime」に関するエラーを吐き出します(次の引用文字までしか解釈されず、「It」しか表示されないためです)。そして「It'stime!」単なる不快な文字列ですが、キャラクターをエスケープしないと、そこから多くの攻撃が発生する可能性があります。

于 2011-02-01T13:39:31.523 に答える
10

短い答え

正解です。

長い答え

これは正しいですが、あなたの質問は、ここで何が起こっているのかについての理解の深さが不足していることを示しています。クエリは次のとおりです。

INSERT INTO table (column, column2) VALUES ('{$escaped_value}', "0")

エスケープしないと、ユーザーが次のデータを入力するとどうなるか見てみましょう。

Eve'

文字列をMySQLに渡すだけで、挿入はPHPの文字列処理によって行われることに注意してください。これは、この場合、mysql_queryに送信されるクエリは次のとおりであることを意味します。

INSERT INTO table (column, column2) VALUES ('Eve'', "0")

これは構文エラーであり、ページエラーが発生します。さて、私のようなユーザー(つまり、あなたの一日を悲惨なものにすることに熱心な野郎)がこれらの1つを見つけたとき、私たちは遊ぶ時間だと知っています。次のデータがユーザーによって提供された場合はどうなりますか?

Eve', "0"); DROP TABLE table--

クエリは次のように拡張されます。

INSERT INTO table (column, column2) VALUES ('Eve', "0"); DROP TABLE table--', "0")

これは構文エラーではありませんが、問題があります...現在、意図していなかったクエリを実行しています。(認識できない場合、「-」はSQLのコメントを示します。つまり、「この時点以降はすべて無視します」)。

現在、これはこの正確なインスタンスでは発生しません(mysql_queryは複数のクエリをサポートしていません)が、これは防止しようとしている種類の攻撃です-SQLインジェクションとして知られる攻撃のクラスです。mysql_real_escape_stringを使用するとどうなるか見てみましょう!

入力されたデータは次のようになります。

Eve\', \"0\"); DROP TABLE table--

つまり、クエリ文字列は次のようになります。

INSERT INTO table (column, column2) VALUES ('Eve\', \"0\"); DROP TABLE table--}', "0")

どちらでもいいです!ユーザーが入力したデータは、ユーザーが入力したときにデータベースに保存されます。引用符なしではなく、余分な円記号を付けずに、入力時に追加します。これは重要です。他の方法でデータを保存すると、後でエスケープ解除またはダブルエスケープなどの問題が発生します。さらに、余分なスラッシュなどを追加すると、何らかの形でユーザーに公開されることがよくあります。これは、物事が適切に回避されていない可能性があることを示す巨大な警告サインです。あなたは間違ったことをしたくありません、そしてあなたは特に間違ったことをしたりそれについて宣伝したりすることを避けたいです、それは私を次のセクションに連れて行きます:

データをエスケープする代わりの方法

  1. 魔法の引用。あなたが指摘したように、非推奨になりました(そして正当な理由で)、避けてください。

  2. データをエスケープしないでください。私はこのオプションに反対することをお勧めします。

  3. 入力から不正な文字を削除します。ほぼすべての状況で煩わしいので、技術的に簡単に保存できるものではなく、ユーザーが入力したものを保存する必要があります。

  4. 不正な文字の入力を禁止します。受け入れられる場合もあれば(クレジットカード番号フィールドで引用符を処理する必要がない場合)、煩わしい場合もあり、大規模な警告サインが表示される場合もあります(たとえば、パスワードフィールドの場合)。

  5. プリペアドステートメント。文字列への変数の「入力」はPHPによって行われ、MySQLはクエリ文字列を取得しているだけなので、エスケープする必要があると言いました。プリペアドステートメントは、もう少しインテリジェントになることでこの作業をオフロードします。プリペアドステートメントを使用すると、次のようになります(警告:擬似コード)。

    $ statement = $ db-> prepare('INSERT INTO table(column、column2)VALUES( "%1"、 "%2")'); $ result = $ statement-> execute($ value1、$ value2);

SQLエスケープメソッドに関する素晴らしいスタックオーバーフローの質問があり、そこでの答えはより深く掘り下げられているので、それを読むことをお勧めします。

個人的には、これは私が好きなオプションです。変数をエスケープして、この方法でデータベースに挿入することを忘れないでください。値が適切にマーシャリングされているか、データベースの近くにないため、途中のオプションはありません。つまり、すべてのクエリがプリペアドステートメントを通過し、次のような文字列の連結がないことを強制するとします。

$db->prepare('INSERT INTO table VALUES('.$value.')'))

終わらせる。私の意見では、これは、どの変数がサニタイズされ、どの変数がサニタイズされていないかを追跡するよりも簡単です。文字列がユーザーから届いたらすぐにエスケープするのが好きな人もいますが、データベース以外の場所、つまりHTMLやmemcacheなどに戻ることができれば、それは非常に厄介です。自分で行う場合は、たとえば、ハンガリアン記法を提案します。

$uValue = $_POST['value'];
$sValue = escape($uValue);
$db->query('INSERT INTO table VALUES(' . $sValue .')');

このアイデアは、JoelSpolskyによる優れた記事MakingWrong CodeLookWrongで最初に見まし

結論

うまくいけば、今すぐ注射防止サイトを作成する準備ができていると感じます。どちらの方法を選択しても幸運を祈ります。データベースにアクセスする前に、すべてのユーザー入力を常にエスケープするようにしてください。;)

于 2011-02-01T14:01:08.197 に答える
0

mysql_real_escape_string()は通常、SQLインジェクションを防ぐのに十分です。

また、(intval()を使用して)ユーザーから取得する数値をフィルタリングする必要があります。

于 2011-02-01T13:40:18.433 に答える