SQLで引用符を逃がします
-
27-10-2019 - |
質問
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")");
データベースのデータを確認すると、$値と同じように見えますので "It's Time"
そしてそうではありません "It\'s Time"
. 。これは正常ですか?これは引用の前にスラッシュを追加すべきではありませんか?
解決
それは正しい動作であり、機能します!引用符は、データベースではなく、クエリで逃げられます。 'SQLクエリは、データベース内の「」に変換する必要があります。
文字列をエスケープするので、SQLクエリは台無しにされず、SQLクエリがコントロール文字として解釈することなくデータベースに引用符を入力できます。
あなたの逃げられたクエリは次のとおりです。
mysql_query("INSERT INTO table (column, column2) VALUES ('It\'s time', "0")");
データベースデータは「It's Time」でなければなりません。
それが逃げられなければ、それは次のとおりです。
mysql_query("INSERT INTO table (column, column2) VALUES ('It's time', "0")");
「S Time」に関するエラーが吐き出されます(次の引用文字までのみ解釈され、「IT」のみが表示されるためです。)と「It's Time!」単なる不快な文字列ですが、キャラクターから逃げないと、多くの攻撃がそれに由来する可能性があります。
他のヒント
簡潔な答え
正解です。
長い答え
これは正しいですが、あなたの質問は、ここで何が起こっているのかについて深みのある理解の欠如を示しています。これがあなたの質問です:
INSERT INTO table (column, column2) VALUES ('{$escaped_value}', "0")
逃げられないと、ユーザーが次のデータを入力した場合に何が起こるか見てみましょう。
Eve'
文字列をMySQLに渡すだけで、挿入はPHPの文字列処理によって行われることを忘れないでください。これは、この例では、mysql_queryに送信されたクエリは次のとおりです。
INSERT INTO table (column, column2) VALUES ('Eve'', "0")
これは構文エラーであり、ページがエラーが発生します。さて、私のようなユーザーが(つまり、あなたの日を悲惨にすることを目指していることを意味します。次のデータがユーザーによって提供された場合はどうなりますか?
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")
それは大丈夫です!ユーザーが入力したデータは、入力したデータベースに保存されます。引用がないわけではなく、余分なバックスラッシュではなく、入力したように。 これは重要. 。他の方法でデータを保存すると、後でエスケープまたはダブルエスケープを行うと問題が発生します。さらに、余分なスラッシュなどを追加するなど、多くの場合、何らかの形でユーザーにさらされることが多く、物事が適切に逃げられていない可能性があるという巨大な警告サインです。あなたは間違ったことをしないようにしたい、そしてあなたは特に間違ったことをしてそれについて宣伝することを避けたいと思っているので、それは私を次のセクションに連れて行きます:
データを逃れるための代替案
- 魔法の引用。あなたが指摘したように、非推奨(そして正当な理由で)、避けてください。
- データを逃がさないでください。このオプションに対してアドバイスします。
- 入力から悪い文字を剥がします。ほぼすべての状況で迷惑なので、技術的に簡単に保存できるものではなく、ユーザーが入力するものを保存する必要があります。
- 悪い文字を入力から禁止します。時には受け入れられることがあります(クレジットカード番号のフィールドは見積もりを処理する必要はありません)、時には迷惑な、時には大規模な警告サイン(たとえばパスワードフィールドにある場合)
準備されたステートメント。文字列内の変数の「充填」はPHPによって行われ、MySQLはクエリ文字列を取得しているだけであるため、逃げる必要があると言いました。準備されたステートメントは、もう少しインテリジェントであることでこの作業をオフロードし、準備されたステートメントを使用すると、このようなものになります(警告:pseudocode):
$ statement = $ db-> prepare( '挿入テーブル(列、列2)値( "%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 .')');
私は最初にこのアイデアを素晴らしい記事で見ました 間違ったコードを間違えるように見せます Joel Spolskyによる。
結論
今、あなたが今注入されないサイトを作る準備ができていると感じてください。あなたが選んだ方法で幸運を祈ります。そして、データベースに当たる前に、すべてのユーザー入力を常にエスケープすることを楽しんでください! ;)
mysql_real_escape_string()は通常、防止するのに十分です SQLインジェクション.
また、ユーザーから取得している数値を(intval()を使用して)フィルタリングする必要があります。