web-dev-qa-db-ja.com

自作の準備済みステートメントとreal_escape_stringを使用したSQLiの可能性

現在の割り当ては、PHP WebAppでSQLインジェクションの可能性を見つけることです。ソースコードを見ていると、スクリプトが準備されたステートメントを処理する方法が奇妙であることに気付きました。

$query = db::prepare("SELECT password FROM vault where id=%s", $_POST['id']);
$res = db::commit($query);

prepare関数の興味深い部分は次のようになります。

    // escape
    foreach ($args as &$value){
        $value = static::$db->real_escape_string($value);
    }

    // prepare
    $query = str_replace("%s", "'%s'", $query);
    $query = vsprintf($query, $args);
    return $query;

これを回避する方法を探していると、明らかにreal_escape_string関数が原因で、単一引用符がエスケープされていることに気づきました。ここを見回すと、 %sを一重引用符で囲むと先制的に非常に疑わしいと思われるという次の投稿 が見つかりました。しかし、私はまだこれを悪用する方法、またはそれが悪用可能かどうかを見つける方法をまだ見つけていません。

そのようなユーザー入力をエスケープして処理するために何か問題がある場合、誰かが私に言うことができますか?元のmysqli/PDOの準備済みステートメント関数を使用する方が良い考えですが、これが私のコードではないので、ここで正確に何が間違っているのか、なぜこのようにしてはいけないのかを見つけるのは素晴らしいことです。

3
Nirusu

そのようなユーザー入力をエスケープして処理するために何か問題がある場合はどうなりますか?

明確にするために、エスケープper seが意図的に使用されている限り、任意の「ユーザー入力」ではなく、具体的にはSQLクエリの文字列リテラルで使用されるデータをエスケープすることに問題はありません。率直に言って、SQLクエリのデータが引用符で囲まれているの両方がエスケープされている限り、害はありません。

問題のコードは特殊なケースです。バルクエスケープが使用されますが(これは原則として大きな赤いフラグです)、この場合、引数のスワッピングやその他の豪華な機能なしで、基本的なprintfプレースホルダー(つまり%s, %d, %fなど)のみが使用されている限り、安全であると見なされます。もの。その結果、すべての入力変数は次のいずれかになります

  • %sプレースホルダーが使用されている場合は引用符で囲まれます(したがって、上記のルールを満たすために引用符で囲まれてエスケープされます)。
  • または、他のプレースホルダーが使用されている場合は、数値としてフォーマットされます。

注射の可能性は見当たらない。

ここでの唯一のセキュリティ上の懸念は mysqli :: set_charset() を使用して接続エンコーディングを設定し、固有の古いエンコーディングが使用されている場合の仮想の脆弱性を回避することです。

1

セキュリティに直接関連しない問題が発生する可能性があります。 _$value_は、real_escape_string()がマジックを実行する前に文字列に変換する必要があるため、あらゆる種類のローカライズの問題が発生する可能性があります。データベースで受け入れられない小数点または日付形式の代わりに_,_について考えてください。すべてのパラメータを文字列として処理することはお勧めできません。

0
martinstoeckli