ホームページ  >  記事  >  类库下载  >  PHPでSQLインジェクションを防ぐ方法

PHPでSQLインジェクションを防ぐ方法

高洛峰
高洛峰オリジナル
2016-10-14 10:12:581224ブラウズ

【1.サーバー側の設定】

セキュリティ、PHP コード作成は 1 つの側面であり、PHP 構成は非常に重要です。

PHP を手動でインストールしました。PHP のデフォルト設定ファイルは /usr/local/apache2/conf/php.ini にあります。最も重要なことは、PHP をより安全に実行できるように php.ini の内容を設定することです。 PHP全体のセキュリティ設定は主にphpshellとSQLインジェクションによる攻撃を防ぐためのものです。ゆっくり説明していきます。まず、編集ツールを使用して /etc/local/apache2/conf/php.ini を開きます。他の方法でインストールした場合は、設定ファイルがこのディレクトリにない可能性があります。

(1) PHP のセーフ モードをオンにする

PHP のセーフ モードは、system()、

などの PHP の一部の関数を制御できる非常に重要な組み込みのセキュリティ メカニズムであり、同時に多くのファイル操作に対するアクセス許可を付与します。関数を制御し、/etc/passwd などの特定のキー ファイルを許可しません

しかし、デフォルトの php.ini はセーフ モードを開きません。セーフ モードをオンにします:

safe_mode = on

(2) ユーザー グループ セキュリティ

safe_mode がオンで、safe_mode_gid がオフの場合、php スクリプトはファイルにアクセスでき、同じ

グループ内のユーザーもファイルにアクセスできます。

次のように設定することをお勧めします:

safe_mode_gid = off

これが設定されていない場合、例えば、

操作する必要がある場合に、サーバー Web サイトのディレクトリ内のファイルを操作できない可能性があります。ファイル。

(3) セーフ モードでプログラムを実行するためのホーム ディレクトリ

セーフ モードがオンになっているが、特定のプログラムを実行したい場合は、プログラムを実行するためのホーム ディレクトリを指定できます:

safe_mode_exec_dir = D:/usr/bin

通常、プログラムを実行する必要はないため、システム プログラム ディレクトリを実行しないことをお勧めします。

次に、実行する必要があるプログラムをコピーします (例:

safe_mode_exec_dir)。 = D:/tmp/cmd

ただし、プログラムは実行しないことをお勧めします。その場合は、Web ページのディレクトリを指定できます:

safe_mode_exec_dir = D:/usr/www

(4) ファイルをセーフ モードでインクルードします

特定のファイルをセーフ モードのパブリック ファイルに含めたい場合は、オプションを変更します:

safe_mode_include_dir = D:/usr/www/include/

実際、通常、php スクリプトに含まれるファイルはプログラムに記述されています。これは特定のニーズに応じて設定できます。

(5) PHP スクリプトがアクセスできるディレクトリを制御します

open_basedir オプションを使用して、指定されたディレクトリにのみアクセスするように PHP スクリプトを制御します。これにより、PHP スクリプトがアクセスすべきでないファイルにアクセスするのを防ぐことができ、phpshell の害を制限できます。

open_basedir = D:/usr/www

(6) 危険な機能をオフにする

セーフモードがオンになっている場合は、機能を禁止します。必須ではありませんが、安全のために考慮する必要があります。たとえば、

コマンドを実行できる system() などの php 関数、または

phpinfo() や php 情報を表示できるその他の関数を実行したくない場合は、それらを無効にすることができます:

disable_functions = system ,passthru,exec,shell_exec,popen,phpinfo

ファイルやディレクトリの操作を禁止したい場合は、多くのファイル操作を無効にすることができます

disable_functions = chdir,chroot,dir,getcwd,opendir,readdir,scandir,fopen ,unlink ,delete,copy,mkdir, rmdir,rename,file,file_get_contents,fputs,fwrite,chgrp,chmod,chown

上記は一般的に使用されるファイル処理関数の一部です。また、上記の実行コマンド関数を組み合わせることもできます。この関数を組み合わせると、

はほとんどの phpshell に耐えることができます。

(7) http ヘッダーの PHP バージョン情報の漏洩をオフにする

ハッカーがサーバー内の PHP バージョン情報を取得するのを防ぐために、http ヘッダーの情報の漏洩をオフにすることができます:

Expose_php = Off

たとえば、ハッカーが Telnet www.12345.com 80 を使用すると、PHP 情報を見ることができなくなります。

(8) グローバル変数の登録をオフにする

POST または GET を使用して送信された変数を含む、PHP で送信された変数は、グローバル変数として自動的に登録され、直接アクセスできます

これはサーバーにとって非常に安全ではありません。グローバル変数として登録させることはできないので、グローバル変数の登録オプションをオフにします:

register_globals = Off

もちろん、このように設定されている場合は、取得時に合理的な方法を使用する必要があります。 GET var によって送信された変数を取得するなど、対応する変数を取得するには $_GET['var'] を使用する必要があります。PHP プログラマはこれに注意する必要があります。

(9) SQL インジェクションを防ぐために、magic_quotes_gpc をオンにします

SQL インジェクションは、Web サイトのバックエンドに侵入したり、サーバー全体がダウンしたりする可能性があるため、注意してください。 php.ini には次の設定があります:

magic_quotes_gpc = Off

これがオンになっている場合、ユーザーが送信した SQL クエリが自動的に変換されます (例: ' を ' に変換します)。 、SQL インジェクションを防止することが重要な役割を果たします。したがって、次のように設定することをお勧めします:

magic_quotes_gpc = On

(10) エラー メッセージ制御

一般に、PHP はデータベースに接続されていない場合、またはその他の状況下でエラーを表示します。一般に、エラー メッセージには PHP スクリプトの現在のパス情報やクエリの SQL ステートメントが含まれます。この種の情報は安全ではありません。ハッカーに提供される場合は、サーバーでエラー プロンプトを無効にすることが一般的に推奨されます:

display_errors = Off

エラー メッセージを表示したい場合は、上記の情報のみを表示するなど、表示エラーのレベルを必ず設定してください。警告:

error_reporting = E_WARNING & E_ERROR

もちろん、エラー プロンプトをオフにすることをお勧めします。

(11) エラーログ

サーバー動作の原因を見つけやすくするために、display_errors をオフにしてエラー情報を記録することをお勧めします:

log_errors = On

同時に、エラーログが保存されているディレクトリApache ログも一緒にルート化することをお勧めします:

error_log = D:/usr/local/apache2/logs/php_error.log

注: このファイルは、Apache ユーザーとグループに許可する必要があります。書き込み権限を持っています。

権限を減らして実行する MYSQL

mysqlstart のような新しいユーザーを作成します

net user mysqlstart funkmicrosoft /add

net localgroup users mysqlstart /del

どのグループにも属していません

MYSQL が d:mysql にインストールされている場合, 次に、mysqlstart にフル コントロール権限を与えます

次に、システム サービスで MYSQL サービス プロパティを設定し、ログイン プロパティでこのユーザー mysqlstart を選択し、パスワードを入力して確認します。

MYSQL サービスを再起動すると、MYSQL は低い特権で実行されます。

Apache が Windos プラットフォーム上に構築されている場合、Apache はデフォルトでシステム権限で実行されるため、非常に不快に感じます。次に、Apache の権限を下げてみましょう。

net user apache funcmicrosoft /add

net localgroup users apache /del

ok どのグループにも属さないユーザー apche を作成しました。

コンピューターマネージャーを開き、サービスを選択し、Apacheサービスのプロパティをクリックし、ログオンを選択し、このアカウントを選択し、上で作成したアカウントとパスワードを入力します。

Apacheサービスを再起動します。OK、Apacheが実行されます低い権限で降りました。

実際、Apache ユーザーが実行したいことのみを実行できるように各フォルダーの権限を設定し、ディレクトリごとに個別の読み取り/書き込みユーザーを作成することもできます。

これは、現在の多くの仮想ホスティングプロバイダーの間で一般的な構成方法でもありますが、この方法をこれを防ぐために使用すると過剰になります。


【2. PHP コードの記述】

国内の PHP プログラマーの多くは SQL インジェクションを防ぐために依然として addlashes に依存していますが、SQL インジェクションを防ぐために中国語チェックを強化することが依然として推奨されています。 addslashes の問題は、ハッカーが 0xbf27 を使用して一重引用符を置き換えることができるのに対し、addslashes は 0xbf27 を 0xbf5c27 に変更するだけで、有効なマルチバイト文字になる 0xbf5c は依然として一重引用符とみなされ、そのため addslashes は正常にインターセプトできないことです。

もちろん、addslashes は役に立たないわけではありません。マルチバイト文字の場合は、mysql_real_escape_string を使用します。
さらに、php マニュアルの get_magic_quotes_gpc の例:

if (!get_magic_quotes_gpc()) {

$lastname = addlashes($_POST['lastname']);
} else {
$lastname = $_POST[' lastname'];
}

magic_quotes_gpc がすでに開いているときに $_POST['lastname'] を確認するのが最善です。
2 つの関数 mysql_real_escape_string と mysql_escape_string の違いについて話しましょう:
mysql_real_escape_string は (PHP 4 >= 4.3.0、PHP 5) の場合にのみ使用できます。それ以外の場合は、mysql_escape_string のみを使用できます。この 2 つの違いは、mysql_real_escape_string は接続の現在の文字セットを考慮するのに対し、mysql_escape_string は考慮しないことです。

要約すると:

* addedlashes() は強制的な追加です。
* mysql_real_escape_string() は文字セットを決定しますが、PHP バージョンの要件があります。
* mysql_escape_string は接続の現在の文字セットを考慮しません。
------------------------------------------------- --------------------------------------
PHPでコーディングする際に考慮すると基本的なセキュリティの問題について、まず第一に:
1. 変数を初期化します
なぜこれを言うのですか?次のコードを見てみましょう:
PHP コード

 <?php     
    if ($admin)     
    {     
    echo &#39;登陆成功!&#39;;     
    include(&#39;admin.php&#39;);     
    }     
    else     
    {     
    echo &#39;你不是管理员,无法进行管理!&#39;;     
    }     
    ?>

さて、上記のコードが正常に実行されており、問題がないことを確認しましょう。次に、それに不正なパラメータを送信してみましょう。たとえば、私たちのページが http://daybook.diandian.com/login.php である場合、次のように送信します: http://daybook.diandian.com/login.php?admin=1、はは、考えてみてください。あなたが直接管理者であるか、直接管理します。
もちろん、私たちはそのような単純な間違いをしないかもしれません。また、非常に秘密の間違いによってこの問題が発生する可能性もあります。たとえば、phpwind フォーラムには管理者権限がないため、直接取得できる抜け穴があります。 $skin 変数。初期化は後で一連の問題を引き起こします。では、上記の問題を回避するにはどうすればよいでしょうか?まず、php.ini から始めて、php.ini で register_global =off を設定します。これは、登録されているすべての変数がグローバルであるわけではないことを意味するため、これを回避できます。ただし、私たちはサーバー管理者ではないので、コードからしか改善できません。では、上記のコードをどのように改善すればよいでしょうか。これを次のように書き換えます:
PHP コード

 <?php     
    $admin = 0; // 初始化变量     
    if ($_POST[&#39;admin_user&#39;] && $_POST[&#39;admin_pass&#39;])     
    {     
    // 判断提交的管理员用户名和密码是不是对的相应的处理代码     
    // ...     
    $admin = 1;     
    }     
    else     
    {     
    $admin = 0;     
    }     
    if ($admin)     
    {     
    echo &#39;登陆成功!&#39;;     
    include(&#39;admin.php&#39;);     
    }     
    else     
    {     
    echo &#39;你不是管理员,无法进行管理!&#39;;     
    }     
    ?>

この時点で http://daybook.diandian.com/login.php?admin=1 を送信しても機能しません。これは、変数を $ に初期化しているためです。先頭が admin = 0 の場合、この脆弱性を利用して管理者権限を取得することはできません。
2. SQL インジェクション (SQL インジェクション) を防ぐ
SQL インジェクションは、基本的に過去 2 年間で国内で普及したテクノロジである asp から php までを含め、現時点で最も有害なプログラムである必要があります。送信された変数の不正確さによってフィルタリングによって注入ポイントが形成され、悪意のあるユーザーが SQL クエリ ステートメントを送信できるようになり、その結果、重要なデータが盗まれたり、データが失われたり破損したり、バックエンド管理に侵入されたりする可能性があります。
注射侵入の基本的な方法は理解できたので、どうすればそれを防ぐことができるでしょうか?コードから始めましょう。
Web 上でデータを送信するには 2 つの方法があることはわかっています。1 つは get で、もう 1 つは post です。そのため、一般的な SQL インジェクションの多くは get メソッドから始まり、SQL がないため、インジェクション ステートメントにはいくつかの SQL ステートメントが含まれている必要があります。 SQL ステートメントには、select、update、delete、insert という 4 つの主要な文があるので、送信するデータをフィルタリングすれば、これらの問題を回避できるでしょうか。
そこで、正規表現を使用して次の関数を構築します:
PHP コード

<?php          
    function inject_check($sql_str)     
    {     
    return eregi(&#39;select|insert|update|delete|&#39;|     
    function verify_id($id=null)     
    {     
    if (!$id) { exit(&#39;没有提交参数!&#39;); } // 是否为空判断     
    elseif (inject_check($id)) { exit(&#39;提交的参数非法!&#39;); } // 注射判断     
    elseif (!is_numeric($id)) { exit(&#39;提交的参数非法!&#39;); } // 数字判断     
    $id = intval($id); // 整型化         
    return $id;     
    }     
    ?>
     呵呵,那么我们就能够进行校验了,于是我们上面的程序代码就变成了下面的:
PHP代码     
    <?php     
    if (inject_check($_GET[&#39;id&#39;]))     
    {     
    exit(&#39;你提交的数据非法,请检查后重新提交!&#39;);     
    }     
    else     
    {     
    $id = verify_id($_GET[&#39;id&#39;]); // 这里引用了我们的过滤函数,对$id进行过滤     
    echo &#39;提交的数据合法,请继续!&#39;;     
    }     
    ?>

さて、問題はここで解決されたように見えますが、投稿によって送信されたデータと大量のデータのバッチを考慮しましたか?
たとえば、「_」、「%」など、一部の文字はデータベースに悪影響を与える可能性があります。これらの文字は特別な意味を持っているため、これらを制御するとどうなるでしょうか?もう 1 つのポイントは、php.ini で magic_quotes_gpc = off に設定すると、データベースのルールに準拠していない送信されたデータの前に ' ' が自動的に追加されないことです。この場合、これらの問題を制御する必要があるため、次のように構築します。
PHP コード

 <?php        
    function str_check( $str )     
    {     
    if (!get_magic_quotes_gpc()) // 判断magic_quotes_gpc是否打开     
    {     
    $str = addslashes($str); // 进行过滤     
    }     
    $str = str_replace("_", "\_", $str); // 把 &#39;_&#39;过滤掉     
    $str = str_replace("%", "\%", $str); // 把&#39; % &#39;过滤掉     
         
    return $str;     
    }     
    ?>

サーバーが侵害される危険を再び回避しました。
最後に、投稿や記事やニュースの作成など、大量のデータを送信することを検討します。上記の関数に基づいて、次の関数を構築します。
PHP コード

    <?php      
    function post_check($post)     
    {     
    if (!get_magic_quotes_gpc()) // 判断magic_quotes_gpc是否为打开     
    {     
    $post = addslashes($post); // 进行magic_quotes_gpc没有打开的情况对提交数据的过滤     
    }     
    $post = str_replace("_", "\_", $post); // 把 &#39;_&#39;过滤掉     
    $post = str_replace("%", "\%", $post); // 把&#39; % &#39;过滤掉     
    $post = nl2br($post); // 回车转换     
    $post= htmlspecialchars($post); // html标记转换        
    return $post;     
    }     
    ?>

笑、基本的には、現時点ではいくつかの状況について話しましたが、少なくとも 2 つの側面についてしか話していないように感じます。また、セキュリティ全体についてはほとんど内容がありません。次回は、PHP セキュリティ設定、Apache セキュリティなどについてさらに詳しくお話します。そうすれば、セキュリティが全体として統合され、最も安全になるでしょう。
最後に、上記の内容を説明します: 1. 変数を初期化します 2. 変数をフィルターすることを忘れないでください


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

関連記事

続きを見る