web-dev-qa-db-ja.com

DBに接続せずにmysql_real_escape_stringの代替

データベースに接続せずにmysql_real_escape_stringとして動作する関数を作成したいので、DBに接続せずにドライテストを行う必要がある場合があります。 mysql_escape_stringは非推奨であるため、望ましくありません。私の発見のいくつか:

http://www.gamedev.net/community/forums/topic.asp?topic_id=448909

http://w3schools.invisionzone.com/index.php?showtopic=20064

86
Viet

DB接続なしで文字列を安全にエスケープすることは不可能です。 mysql_real_escape_string()および準備されたステートメントは、適切な文字セットを使用して文字列をエスケープできるようにデータベースへの接続が必要です。そうでない場合、マルチバイト文字を使用したSQLインジェクション攻撃が依然として可能です。

testingのみの場合、mysql_escape_string()も使用できます。SQLインジェクション攻撃に対して100%保証されているわけではありませんが、DB接続なしでより安全なものを構築することは不可能です。

72
too much php

mysql_real_escape_string 関数リファレンスページによると: "mysql_real_escape_string()は、次の文字をエスケープするMySQLのライブラリ関数mysql_real_escape_stringを呼び出します。\ x00、\ n、\ r、\、 '、"および\ x1a 」

それを念頭に置いて、投稿した2番目のリンクで指定された関数は、必要なことを正確に行う必要があります。

function mres($value)
{
    $search = array("\\",  "\x00", "\n",  "\r",  "'",  '"', "\x1a");
    $replace = array("\\\\","\\0","\\n", "\\r", "\'", '\"', "\\Z");

    return str_replace($search, $replace, $value);
}
60
zombat

私の他の答えに直接反対して、この次の関数は、マルチバイト文字であってもおそらく安全です。

// replace any non-ascii character with its hex code.
function escape($value) {
    $return = '';
    for($i = 0; $i < strlen($value); ++$i) {
        $char = $value[$i];
        $ord = ord($char);
        if($char !== "'" && $char !== "\"" && $char !== '\\' && $ord >= 32 && $ord <= 126)
            $return .= $char;
        else
            $return .= '\\x' . dechex($ord);
    }
    return $return;
}

上記のコードが機能しない理由を私よりも知識のある人が教えてくれることを期待しています...

25
too much php

さらなる研究から、私は見つけた:

http://dev.mysql.com/doc/refman/5.1/en/news-5-1-11.html

セキュリティ修正:

マルチバイトエンコーディング処理でSQLインジェクションセキュリティホールが見つかりました。バグはサーバーにあり、mysql_real_escape_string()C API関数でエスケープされた文字列を誤って解析していました。

この脆弱性は、OSDBコンソーシアムのプロジェクト間セキュリティコラボレーションの一環として、Josh BerkusとTom Laneによって発見および報告されました。 SQLインジェクションの詳細については、次のテキストを参照してください。

討論。 SQLインジェクションのセキュリティホールがマルチバイトエンコーディング処理に見つかりました。 SQLインジェクションセキュリティホールには、ユーザーがデータベースに挿入するデータを指定したときに、サーバーが実行するデータにSQLステートメントを挿入する状況が含まれる場合があります。この脆弱性に関して、文字セットを認識しないエスケープが使用されている場合(PHPのaddlashes()など)、一部のマルチバイト文字セット(SJIS、BIG5、GBKなど)でエスケープをバイパスすることができます。その結果、addslashes()などの関数はSQLインジェクション攻撃を防ぐことができません。サーバー側でこれを修正することは不可能です。最良の解決策は、アプリケーションがmysql_real_escape_string()などの関数によって提供される文字セット対応のエスケープを使用することです。

ただし、MySQLサーバーがmysql_real_escape_string()の出力を解析する方法にバグが検出されました。その結果、文字セット対応関数mysql_real_escape_string()が使用された場合でも、SQLインジェクションが可能になりました。このバグは修正されました。

回避策。 MySQLをmysql_real_escape_string()解析のバグの修正を含むバージョンにアップグレードできないが、MySQL 5.0.1以降を実行する場合は、回避策としてNO_BACKSLASH_ESCAPES SQLモードを使用できます。 (このモードはMySQL 5.0.1で導入されました。)NO_BACKSLASH_ESCAPESは、バックスラッシュが特殊文字と見なされないSQL標準互換モードを有効にします。その結果、クエリは失敗します。

現在の接続にこのモードを設定するには、次のSQLステートメントを入力します。

SET sql_mode='NO_BACKSLASH_ESCAPES';

すべてのクライアントに対してモードをグローバルに設定することもできます。

SET GLOBAL sql_mode='NO_BACKSLASH_ESCAPES';

このSQLモードは、コマンドラインオプション--sql-mode = NO_BACKSLASH_ESCAPESを使用するか、サーバーオプションファイル(my.cnfまたはmy.iniなど)でsql-mode = NO_BACKSLASH_ESCAPESを設定することにより、サーバーの起動時に自動的に有効にすることもできます。 、システムに応じて)。 (バグ#8378、CVE-2006-2753)

Bug#8303も参照してください。

6
Viet