1. 注射攻撃の種類
攻撃動機にはさまざまな種類があるかもしれませんが、一見したところ、もっと種類があるように見えます。これは、悪意のあるユーザーが複数のクエリを実行する方法を見つけた場合に当てはまります。これについては、この記事の後半で詳しく説明します。
たとえば
スクリプトが SELECT 命令を実行している場合、攻撃者は、以下に示すように、「1=1」などの条件を WHERE 句に挿入することで、テーブル内のすべての行を強制的に表示できます (ここで、注入は部分は太字で示されています):
SELECT * FROM wines WHEREvariation = 'lagrein' OR 1=1;'
前に説明したように、テーブルの一般的な構造が明らかになるため、これ自体が有益な情報になります (実際にはそうではありません)。通常のレコードで可能)、機密情報を含むレコードが表示される可能性があります。
更新された指令は、より差し迫った脅威をもたらす可能性があります。 SET 句に他の属性を配置することにより、攻撃者は、次の例 (挿入された部分が太字で示されている) のように、現在更新中のレコード内の任意のフィールドを変更できます。
UPDATE wines SET type='red ','vintage '='9999' WHERE 多様性 = 'lagrein'
更新命令の WHERE 句に 1=1 などの true 条件を追加することで、この変更範囲をレコードごとに拡張できます。 たとえば、次の例 (注入部分は太字で示されています):
UPDATE wines SET type='red', 'vintage'='9999 WHEREvariation = 'lagrein' OR 1=1;'
おそらく最も危険なディレクティブは DELETE です - 想像するのは難しくありません。注入手法は、これまでに説明したものと同じです。以下の例のように、WHERE 句を変更することで影響を受けるレコードの範囲を拡張します (注入された部分は太字です)。 lagrein' OR 1=1;'
2. 複数のクエリ インジェクション
複数のクエリ インジェクションは、単一のクエリに複数の破壊的な命令が含まれることを許可することで、攻撃者が引き起こす可能性のある潜在的な損害を悪化させます。 MySQL データベースを使用する場合、攻撃者はクエリに予期しないターミネータを挿入することでこれを簡単に達成できます。挿入された引用符 (一重または二重) は予期される変数の終わりを示し、ディレクティブをセミコロンで終了します。ここで、終了した元のコマンドの最後に追加の攻撃コマンドを追加できます。最終的な破壊的なクエリは次のようになります:
コードをコピー コードは次のとおりです:
SELECT * FROM wines WHEREvariation = 'lagrein';
GRANT ALL ON *.* TO 'BadGuy@%' 「ガッチャ」によって識別されました
このインジェクションにより、新しいユーザー BadGuy が作成され、ネットワーク権限 (すべてのテーブルに対するすべての権限) が付与され、この単純な SELECT ステートメントに「不気味な」パスワードが追加されます。前の記事のアドバイスに従い、プロセス ユーザーの権限を厳密に制限した場合、Web サーバー デーモンには取り消した GRANT 権限がなくなっているため、これは機能しません。しかし理論的には、このような攻撃により、BadGuy はデータベースに対してやりたいことを何でもできるようになる可能性があります。
そのようなマルチクエリが MySQL サーバーによって処理されるかどうかについては、結論は一意ではありません。これは、MySQL のバージョンの違いが原因である場合もありますが、ほとんどの場合、複数のクエリの存在方法が原因です。 MySQL の監視プログラムでは、このようなクエリを完全に許可します。一般的に使用される MySQL GUI-phpMyAdmin は、最後のクエリの前に以前のすべてのコンテンツをコピーし、これのみを実行します。
ただし、インジェクションコンテキスト内の複数のクエリのほとんどは、PHP の mysql 拡張機能によって管理されます。幸いなことに、デフォルトでは、クエリ内で複数の命令を実行することはできません。2 つの命令 (上記のインジェクションなど) を実行しようとすると、エラーが設定されず、情報も出力されません。この場合、PHP はデフォルトの動作を「定期的に」実装するだけですが、ほとんどの単純なインジェクション攻撃から実際に保護できます。
PHP5 の新しい mysqli 拡張機能 (http://php.net/mysqli を参照) は、mysql と同様に、本質的に複数のクエリをサポートしませんが、複数のクエリ -If の実装をサポートする mysqli_multi_query() 関数を提供します。あなたは本当にそれをしたいのです。
ただし、PHP5 にバンドルされている埋め込み可能な SQL データベース エンジンである SQLite (http://sqlite.org/ および http://php.net/sqlite を参照) の場合、その使いやすさにより、状況はさらに悲惨です。多数のユーザーの。場合によっては、データベースがバッチ クエリ、特にバッチ INSERT ステートメント処理を最適化でき、非常に効率的であるため、SQLite はデフォルトでこのような複数命令クエリを許可します。ただし、クエリの結果がスクリプトで使用される場合 (たとえば、レコードを取得するために SELECT ステートメントを使用する場合)、sqlite_query() 関数では複数のクエリを実行できません。 3. INVISION Power BOARD SQL インジェクションの脆弱性
Invision Power Board はよく知られたフォーラム システムです。 2005 年 5 月 6 日、ログイン コードに SQL インジェクションの脆弱性が発見されました。これは、GulfTech Security Research の James Bercegay によって発見されました。
このログインクエリは次のとおりです:
$DB->query("SELECT * FROM ibf_members WHERE id=$mid AND passwd='$pid'");
このうち、メンバー ID 変数 $mid とパスワード ID変数 $pid は、次の 2 行のコードを使用して my_cookie() 関数から取得されます:
コードをコピー コードは次のとおりです:
$mid = intval($std->my_getcookie('member_id) '));
$pid = $std->my_getcookie('pass_hash');
コードをコピー コードは次のとおりです:
if ( ! in_array( $name,array('topicsread' , 'forum_read', 'collapseprefs') ) )
{
return $this->
clean_value($_COOKIE[$ibforums->vars['cookie_id'].$name]));
{
return urldecode($_COOKIE[$ibforums->vars['cookie_id'].$name]);
そのような修正の後、キー変数はグローバル clean_value() 関数を「通過」した後に返されますが、他の変数はチェックされません。
SQL インジェクションとは何か、どのように機能するか、そしてこのインジェクションがいかに脆弱であるかについて一般的に理解できたので、それを効果的に防止する方法を見てみましょう。幸いなことに、PHP は豊富なリソースを提供するため、推奨する手法を使用して注意深く徹底的に構築されたアプリケーションによって、スクリプトから SQL がインジェクションされる可能性が基本的に排除されると確信を持って予測できます。これは、ユーザーのデータを「クリーンアップ」することによって実現されます。損害が発生する前に。
4. クエリ内の各値を定義する
クエリ内の各値を必ず定義することをお勧めします。文字列値は、通常 (「二重」引用符ではなく) 「一重引用符」を使用すると予想されるものと同様に、最初に影響を受けます。二重引用符を使用して文字列内で PHP 変数を置換できるようにすると、クエリの入力が容易になりますが、その一方で、将来の PHP コードの量が (確かに最小限にとどまります) 削減されます。仕事。
次に、この問題を説明するために最初に使用した非注入クエリを使用してみましょう:
SELECT * FROM wines WHEREvariation = 'lagrein'
または、PHP ステートメントで次のように表現します:
$query = "SELECT * FROM wines WHERE variety = '$variety'";
技術的には、数値に引用符は必要ありません。ただし、ワインのようなフィールドの値を引用符で囲んでも構わない場合、およびユーザーがフォームに null 値を入力すると、次のようなクエリが表示されます:
SELECT * FROM wines WHEREvintage =
もちろん、このクエリは構文的には無効ですが、次の構文は有効です:
SELECT * FROM wines WHEREvintage = ''
2 番目のクエリは (おそらく) 何も返しませんが、少なくともエラー メッセージは返しません。 。
5. ユーザーによって送信された値のタイプを確認します
前の説明から、これまでのところ、SQL インジェクションの主な原因は予期しないフォームのエントリから来ていることがわかります。ただし、フォームを介して特定の値を送信する機会をユーザーに提供する場合、どの入力を取得するかを決定する際にかなりの利点があるはずです。これにより、ユーザーの入力の有効性を確認することが容易になります。以前の記事でこのような検証の問題について議論しましたので、ここではその時の議論の要点のみを簡単に要約します。数値を期待している場合は、次のいずれかの手法を使用して、取得しているものが実際に数値型であることを確認できます:
· is_int() 関数 (または is_integer() または is_long()) を使用します。
・gettype()関数を使用します。
・intval()関数を使います。
・settype()関数を使用します。
ユーザー入力の長さを確認するには、strlen() 関数を使用できます。希望の時刻または日付が有効かどうかを確認するには、strtotime() 関数を使用できます。これにより、ユーザーのエントリにセミコロン文字が含まれていないことがほぼ確実になります (句読点を法的に含めることができない場合を除く)。以下に示すように、strpos() 関数を使用すると、これを簡単に実現できます。
if( strpos( $variety, ';' ) ) exit ( "$variety is an無効な値です!" );前述したように、ユーザー入力の期待を注意深く分析している限り、多くの問題を簡単に検出できるはずです。
6. クエリから疑わしい文字をすべて除外します
以前の記事で危険な文字を除外する方法について説明しましたが、ここでもう一度この問題を簡単に強調して要約します。
· magic_quotes_gpc ディレクティブまたはそのディレクティブを使用しないでください。 「舞台裏のパートナー」 - addslashes() 関数。この関数はアプリケーション開発に制限されており、追加の手順が必要です。stripslashes() 関数を使用します。
· 比較すると、mysql_real_escape_string() 関数がより一般的に使用されますが、これには独自の欠点もあります。
上記は、SQL インジェクションを防止する内容も含めて、PHP で SQL インジェクションを防止するコードを紹介しています。PHP チュートリアルに興味のある友人に役立つことを願っています。