32

アプリケーションでのSQLインジェクションを防ぐために、準備されたステートメントまたは適切な置換/フォーマット規則を使用する必要があることは誰もが知っています.

しかし、MySQL の文字リテラルのリストを見てみると、次の文字が含まれていることに気付きました。

  • \0 ASCII NUL ( 0x00) 文字。
  • \' 一重引用符 ( ') 文字。
  • \" 二重引用符 ( ") 文字。
  • \b バックスペース文字。
  • \n 改行 (改行) 文字。
  • \r キャリッジ リターン文字。
  • \t タブ文字。
  • \Z アスキー 26 ( Ctrl+ Z)。表の後の注を参照してください。
  • \\ バックスラッシュ ( \) 文字。
  • \%%キャラクター 。
  • \__キャラクター 。

ここで、不要なワイルドカードが LIKE ステートメントに挿入されるのを防ぐために、および文字をエスケープ%する必要があります。任意の SQL - これらの他の文字をエスケープしないと、他の方法では存在しない SQL インジェクションの脆弱性に直接つながる可能性がありますか? そのようなエクスプロイトの実際の例はありますか?_'\"

次のようなクエリを作成しているとしましょう。

SELECT * FROM users WHERE username='$user'

エスケープされ$userていない文字リテラルのみが\b(バックスペース)、\0(NUL)、\n(改行)、\r(改行)、\t(タブ)、または\Z( Ctrl+ Z) であり、このクエリに任意の SQL を挿入できる値はありますか?

4

2 に答える 2

8

mysql_real_escape_string() manualの以下の行を考慮してください。

MySQL では、バックスラッシュと、クエリ内の文字列を引用するために使用される引用文字のみをエスケープする必要があります。mysql_real_escape_string()は、他の文字を引用符で囲み、ログ ファイルで読みやすくします。

MySQL での SQL インジェクションは、これらの特殊文字だけでは可能ではありません: \b \0 \n \r \t \Z.

ただし、 String Literals マニュアルには次のように記載されていますが、指定された (または指定されていない) 理由は SQL インジェクションとは関係ありません。

バイナリ データを文字列列 ( BLOB列など) に挿入する場合は、特定の文字をエスケープ シーケンスで表す必要があります。バックスラッシュ (「\」) と、文字列を引用するために使用される引用文字はエスケープする必要があります。特定のクライアント環境では、NUL または Control+Z をエスケープする必要がある場合もあります。mysqlクライアントは、エスケープされていない場合、NUL 文字を含む引用符で囲まれた文字列を切り捨てます。エスケープされていない場合、Windows では END-OF-FILE として Control+Z が使用される場合があります。

さらに、単純なテストでは、天候に関係なく、上記の特殊文字がエスケープされるかどうかに関係なく、MySQL は同じ結果をもたらしました。つまり、MySQL は気にしませんでした:

$query_sql = "SELECT * FROM `user` WHERE user = '$user'";

上記のクエリは、以下に示すように、上記の文字のエスケープされていないバージョンとエスケープされたバージョンに対して同様に機能しました。

$user = chr(8);     // Back Space
$user = chr(0);     // Null char
$user = chr(13);    // Carriage Return
$user = chr(9);     // Horizontal Tab
$user = chr(26);    // Substitute
$user = chr(92) .chr(8);    // Escaped Back Space
$user = chr(92) .chr(0);    // Escaped Null char
$user = chr(92) .chr(13);   // Escaped Carriage Return
$user = chr(92) .chr(9);    // Escaped Horizontal Tab
$user = chr(92) .chr(26);   // Escaped Substitute

単純なテストで使用されるテスト テーブルとデータ:

-- Table Structure

CREATE TABLE IF NOT EXISTS `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user` varchar(10) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

-- Table Data

INSERT INTO `user` ( `user` ) VALUES
( char( '8' ) ),
( char( '0' ) ),
( char( '10' ) ),
( char( '13' ) ),
( char( '9' ) ),
( char( '26' ) );
于 2013-10-26T12:38:28.493 に答える
8

2020 年からの必須の補遺:

文字を扱うことは非効率的で時代遅れであることが証明されました

準備されたステートメントを使用し、エスケープ、「危険な文字」またはそのビジネスのいずれかを忘れる必要があります。

パラメータ化されたクエリを使用することは、SQL インジェクションから保護する唯一の適切な方法と見なされます。これは、以下の元の回答に記載されている理由によるものです。

mysqlで実際にSQLインジェクションを引き起こす可能性のある文字はどれですか

そのようなキャラクターはいません。

SQL インジェクションを引き起こすのは「文字」ではありません。しかし、不適切なフォーマット。状況に応じて、どのキャラクターも「危険」または完全に無害である可能性があります。保護を一部のサブセットに制限することは危険な妄想であり、実際には遅かれ早かれ SQL インジェクションにつながります。

あなたの質問には、あなたを混乱に導いた 2 つの間違った記述があります。

  1. アプリケーションでの sql インジェクションを防ぐために、適切な置換ルールを使用する必要があることは誰もが知っています。

このステートメントは間違っています。差し替えではなく整形。違いは不可欠です。置換だけではインジェクションから保護されませんが、フォーマットは保護されます。クエリの個々の部分ごとに異なるフォーマットが必要であり、他の部分には役に立たないことに注意してください。たとえば、インジェクション保護に不可欠な別の文字、バッククォート (`) があるとします。ただし、文字列リテラルとは関係がないため、リストしませんでした。

  1. インジェクションを防ぐために、' (一重引用符)、\ (バックスラッシュ)、および " (二重引用符) をすべてエスケープする必要があります。

それはひどく間違った発言です。エスケープしても注射は防げません。これらの文字は、文字列をフォーマットするためにエスケープする必要があり、インジェクションとはまったく関係ありません。適切にフォーマットされたクエリ部分が無敵であることは事実ですが。しかし、真実は - 動的なクエリ部分をフォーマットする必要があるのは、それのためだけであり、構文規則に従うためであり、インジェクションのためではありません。また、副作用として、クエリが侵入できなくなります。

これで、最後の発言の理由がわかります。

これらの他のすべての文字が、mysql_real_escape_string を介してエスケープできるほど脆弱である理由は、すぐにはわかりません。

「脆弱性」ではなく、これらの文字を必要とするの
は文字列の書式設定規則です。それらの中には、便宜上だけでエスケープされているものもあれば、読みやすくするためのものもあれば、区切り文字をエスケープするという明白な理由のためにエスケープされているものもあります。それで全部です。

コメントから最近の質問に回答するには:

PHP の mysql_real_escape_string もこれらのリテラルを引用しないため、これに対する回答が本当に必要です。

繰り返しますが、平均的な PHP ユーザーの心の中では、mysql_real_escape_string()恐怖を与えるインジェクションに強く結びついていますが、実際にはそうではありません。「危険な」文字はありません。1つではありません。特別な意味を持ついくつかのサービス文字があります。状況によっては、エスケープする必要があります。

したがって、この関数によってエスケープされる文字と「危険」との間には何の関係もありません。mysql_real_escape_string()その目的は「危険な」キャラクターから逃れることだと考え始めた瞬間、あなたはまさに危険にさらされています。この関数を文字列をエスケープするためだけに使用している (そして無条件に実行している) 限り、安全であると考えることができます (もちろん、それぞれのフォーマット規則を使用して、他のすべてのリテラルもフォーマットすることを忘れない場合)。

「%」文字が、LIKE 句の余分な結果以上のものにつながるかどうかを知りたいです。

いいえ。

于 2013-01-17T05:37:14.467 に答える