-7

私は長い間MySQLインジェクションに悩まされており、この問題を一斉に解消する方法を考えていました。多くの人がこれが役立つことを願って、私は以下の何かを思いついた。

私が考えることができる唯一の欠点は、部分的な検索です。Jo=>like%%ステートメントを使用して"John"を返します。

これがphpソリューションです:

<?php
function safeQ(){
   $search= array('delete','select');//and every keyword...
   $replace= array(base64_encode('delete'),base64_encode('select'));
   foreach($_REQUEST as $k=>$v){
      str_replace($search, $replace, $v);
   }
}
safeQ();

function html($str){
   $search= array(base64_encode('delete'),base64_encode('select'));
   $replace= array('delete','select');//and every keyword...
   str_replace($search, $replace, $str);
}

//example 1
...
...
$result = mysql_fetch_array($query);
echo html($result[0]['field_name']);

//example 2
$select = 'SELECT * FROM $_GET['query'] '; 

//example 3
$insert = 'INSERT INTO .... value( $_GET['query'] )'; 


?>

私はあなたがまだ他のタイプのインジェクションを使ってインジェクションできることを知っています1=1...しかしこれはあなたの問題の半分を解決できると思うので正しいmysqlクエリが実行されます。

だから私の質問は、誰かがこれに関する欠点を見つけることができるなら、ここにコメントしてください。

これが非常に有用な解決策であり、大きな欠点が見つからないと思う場合、または一緒に悪い考えであると思う場合にのみ、答えを与えてください...

4

4 に答える 4

11

これはすでに PHP で正しく実装されています。

ただし、 SQL インジェクションに関する PHP マニュアル エントリを読むことから始める必要があります。


実際の質問に答えるために、アプローチの主な欠点は次のとおりです。

  1. うまくいきません
  2. 明確にするために、それは機能せず、SQL インジェクションに対して無防備なままになります。
  3. また、MySQL キーワードと競合するデータを入力することもできなくなります。

車輪を再発明する場合は、既存の車輪を検討することをお勧めします。

于 2010-05-07T10:01:00.483 に答える
6

車輪の再発明と間違った方法 (TM) による再発明。

  • まず第一に、パラメータ化されたクエリがあります ( MySQLi拡張機能の PHP で利用可能)。それがオプションでない場合は、mysql_real_escape_stringがあります。これが主な問題です。独自に実装することを決定する前に、すでに利用可能なオプションを確認してください。
  • 次に、SQL で PHP 関数を呼び出そうとしています。'SELECT * FROM ' . safeQ($_GET['query'])
  • 3 番目に、すべてのインデックス作成を破り、「悪意のある言葉」を含むデータを検索し、パフォーマンスの問題とクレイジーな回避策に挨拶します。

編集:コメントで与えている例に対処するには:

$v="1; DROP tbl;\";DROP tbl" // oh look, an SQL injection attempt!
$s = 'SELECT * FROM tbl WHERE ID='.$v; // SQL injection, no doubt

// if ID is an integer field, make it an integer. Simple, secure, and fast.
$s = 'SELECT * FROM tbl WHERE ID='.(int)$v; 
// $s == 'SELECT * FROM tbl WHERE ID=1' // see PHP manual for explanation of type casting

// if ID is a string field, escape it. Simple, secure, and still plenty fast.
$s = 'SELECT * FROM tbl WHERE ID="'.mysql_real_escape_string($v) . '"';
// $s == 'SELECT * FROM tbl WHERE ID="1; DROP tbl;\";DROP tbl"'; 
// See? No injection, as the quote is *escaped*
于 2010-05-07T10:12:56.950 に答える
2

それは悪い考えです。

言語、プラットフォーム、ランタイム、エンジン、ライブラリなど、あらゆる言語、プラットフォーム、ランタイム、エンジン、ライブラリに、SQL インジェクションに対する適切で正しく機能するソリューションが既に存在します。

パラメータと呼びます。

値をリテラル定数として SQL に配置する代わりに、パラメーター プレースホルダーを追加してから、クエリと共にパラメーター値を指定します。SQL に戻すための書式設定のトリックも使用しません。

SQLまたはその一部を見て、それが正しいかどうかを判断しようとすることで問題を「修正」しようとする他のすべてのソリューションは標準以下であり、それらのほとんどには他のバグや目に見えない問題があります.知りませんし、本当に持ちたくありません。

したがって、ブッシュの周りを叩くのをやめ、最初から正しい方法でそれを行ってください. パラメータの使用に切り替えます。

PHP で MySQL と対話するには、複数の方法がありますが、mysqli ライブラリを使用します。

$stmt = $db->prepare('SELECT * FROM products WHERE id = ?');
$stmt->bind_param('i', $id);
$stmt->execute();
.. bind for results
$stmt->fetch();

ここで $id 変数に安全でないコードが含まれていると、SQL 実行がクラッシュします。id が整数の場合、他の整数としか比較できず、文字列の場合は、指定した文字列と比較されるためです。文字列を SQL の一部として実行しようとしないでください。

さて、コメントはポイントを引き出します。動的な順序付け (つまり、ユーザーが選択した順序付け) または動的フィルタリング (つまり、適用するフィルターはユーザーによって選択される) を提供するため、SQL を変更する必要がある場合があります。 .

この場合の解決策は簡単です。ユーザー提供のテキストを取得して SQL に配置しないでください。代わりに、SQL に追加する定数をコードにハードコーディングし、ユーザーの選択に応じて、どの定数をどの順序でどこに追加するかをコードに指示します。

于 2010-05-07T10:25:47.337 に答える
1

ほら、あなたは間違った観点からそれについて考えています。
多くの人がそうしますが。SQL インジェクションによると、2 つの大きな誤解があります。

  1. 「SQL インジェクション」と呼ばれる特殊な攻撃があります。
  2. それを防ぐには、入力データを特別な方法で脅かす必要があります。

どちらも間違っています。

SQL 構文に従う場合、「SQL インジェクション」などはありません。

図に行きます。

SQL 構文規則に従えば (インジェクションがあってもそれに従わなければなりません!)、副作用としては安全です。

SQL クエリに入力される文字列データは、次の 2 つの規則に従って処理する必要があります
。1. 文字列内のすべての特殊文字をエスケープする必要があります。
2. 文字列は引用符で囲む必要があります。

非テキストデータにも問題があります。大したことではありません。
しかし、複雑すぎると感じた場合は、いつでも準備済みのステートメントを使用できます。これは常に安全であり、考える必要がありません。

ただし、クエリのデータ以外の部分にはまだ問題があります。それは確かに最も危険な部分です。そして、唯一の問題は「SQL インジェクション」と呼ばれる権利があります。
これを回避するには、クエリのすべての動的な非データ部分をスクリプトにハードコーディングする必要があります。それが唯一可能な方法です。

于 2010-05-07T10:15:14.350 に答える