ホームページ  >  記事  >  バックエンド開発  >  PHP_PHP チュートリアルでの SQL インジェクションを防ぐ実装コード

PHP_PHP チュートリアルでの SQL インジェクションを防ぐ実装コード

WBOY
WBOYオリジナル
2016-07-21 15:31:52886ブラウズ

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 条件を追加すると、次の例のように、この変更範囲を各レコードに拡張できます (whereインジェクション部分は太字で示されています):
UPDATE wines SET type='red', 'vintage'='9999 WHEREvariation = 'lagrein' OR 1=1;'

最も危険な指示 おそらく削除 - 難しいことではありません想像する。注入手法は、これまでに説明したものと同じです。以下の例のように、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');

ここで、my_cookie() 関数は次のステートメントを使用して Cookie から要求された変数を取得します。 [$ibforums->vars[' cookie_id'].$name]);

[注] この Cookie から返される値はまったく処理されません。 $mid はクエリで使用される前に整数にキャストされますが、$pid は変更されません。したがって、前述した種類のインジェクション攻撃に対して脆弱です。
そのため、次の方法で my_cookie() 関数を変更すると、この脆弱性が公開されます:


コードをコピー コードは次のとおりです:
if ( ! in_array( $name,array('topicsread' , 'forum_read', 'collapseprefs') ) )
{
return $this->
clean_value($_COOKIE[$ibforums->vars['cookie_id'].$name])); else
{
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 WHEREvariety = '$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() 関数を使用して簡単に実現できます。前述したように、ユーザー入力の期待を慎重に分析している限り、多くの問題を簡単に検出できるはずです。

6. クエリから疑わしい文字をすべて除外します

以前の記事で危険な文字を除外する方法について説明しましたが、ここでもう一度簡単に強調して要約します。この質問:
· magic_quotes_gpc は使用しないでください。ディレクティブまたはその「舞台裏のパートナー」 - addslashes() 関数 この関数はアプリケーション開発に制限されており、stripslashes() 関数を使用するという追加の手順が必要です。
· 比較すると、mysql_real_escape_string() 関数がより一般的に使用されますが、これには独自の欠点もあります。

http://www.bkjia.com/PHPjc/322927.html
www.bkjia.com

tru​​ehttp://www.bkjia.com/PHPjc/322927.html技術記事 1. インジェクション攻撃の種類 攻撃の動機にはさまざまな種類があると思われますが、一見すると、さらに種類があるように見えます。それは非常に現実的です - 悪意のあるユーザーが...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。