安全|问题
値は多少異なる場合がありますが、ほとんどの UNIX® システムでは /usr/local/lib/php.ini が一般的な場所であり、ほとんどの Microsoft® Windows® システムでは C:phpphp.ini または C:WINDOWSphp.ini が配置されます。公共の場所。ファイルが存在しない場合は、ファイルを作成し、そのファイルに上記の error_reporting 行を入力します。 php.ini ファイルを変更した後、新しい設定を有効にするために PHP の Web サーバーを再起動する必要があります。
有时候,您的业务可能涉及到 PHP 应用程序的安全性。当您遇到审计任务时,您知道如何执行查找吗?本系列将带您进入 PHP,并帮您在一定程序上了解它,让您在进行安全审计时知道查找什么。第 1 部分向您介绍 register_globals 设置。
入门知识
我在此假定您对 PHP 的语法有一个大致的了解,至少能够编写“Hello World”之类的程序。如果您不具备基础知识,则请首先学习 PHP 手册和某些基本的 PHP 教程(参阅 参考资料)。很多出版商都有关于 PHP 的好书。建议初学者一开始先看看入门书籍或食谱形式的书籍。
在生产环境的准确副本上执行审计。您不需要复制硬件,但是需要确保软件版本尽量和实际的完全一样。PHP 配置必须精确匹配,这一点在 php.ini 文件中、在 .htaccess 文件的 Apache 指令中或在 httpd.conf 中已经指定。您需要准备一个单独的环境,因为您将显示和记录可能包含敏感的密码及其他信息的错误。此外,您将尝试中断站点的安全性,这一点是您在活动应用程序中极力避免的。
第一步是将 PHP 的 error_reporting 设置更改为 E_ALL。设置更改后,每当使用未初始化的变量、进行错误的文件访问及发生其他(大多数)无害错误时,PHP 都会报告一条警告消息,但也存在这是一个潜在攻击矢量的可能性。这些错误一般情况下只是表明编程草率,所以如果这是您的代码,您把它们清除掉即可。
该设置如下所示:
error_reporting = E_ALL
如果您不知道 php.ini 文件在哪里,则可以通过创建包含以下文本的 .php 脚本来查找:
phpinfo();
输出的上面部分有一行列出了 PHP 查找 php.ini 的位置:
图 1. PHP 查找 php.ini 的位置
[[The No.1 Picture.]]
これまでに phpinfo() ページを作成したことがない場合は、今すぐ作成できます。 2 番目のメインセクションには「構成」というラベルが付けられており、PHP のセットアップ方法に関する多くの役立つ情報が含まれています。このセクションには、設定名、ローカル値、および xmaster 値の 3 つの列が含まれています。マスター値は、マシン上のすべての PHP スクリプトの php.ini ディレクティブを介してグローバルに設定される値です。ローカル値は、現在のスクリプトに有効な値です。これは、.htaccess 設定、httpd.conf の
カスタマイズする必要がある他の 2 つの設定は、display_errors と log_errors です。これら 2 つの設定のうち少なくとも 1 つ、または両方を有効にする必要があります。 log_errors は、メモ、警告、エラーをファイルに記録するように PHP に指示し、display_errors は記録されたメモ、警告、エラーを画面に表示します。これらは相互に排他的ではありません。少なくとも 1 つを有効にすると、セキュリティの脆弱性につながる可能性のあるプログラミング エラーを効果的に検出できます。
どのような種類のセキュリティ問題を探す必要がありますか?
ありがたいことに、セキュリティの脆弱性につながる多くのプログラミング エラーが PHP に存在することは不可能です。スタック オーバーフローとバッファ オーバーフローは、C および C++ 環境における 2 つの一般的な問題です。 PHP がメモリを管理するため、PHP コードがスタック オーバーフローやバッファ オーバーフローを引き起こすことはありません。
しかし、PHP自体もC言語で書かれており、メモリの問題がPHPの根幹に深く関わることがあります。したがって、セキュリティ情報やアップデートに随時注意を払う必要があります。 PHP は、Web サイト (「参考文献」を参照) で新しい PHP バージョンを発表し、セキュリティ修正が含まれているかどうかを示します。
PHP アプリケーションの問題のほとんどは、ユーザーが提供したデータを、使用して操作を実行する前に事前検証やサニタイズを行わずに使用することに関連しています。クロスサイト スクリプティング (XSS) と呼ばれる脆弱性について聞いたことがあるかもしれません。 XSS 攻撃は、プログラムが予期しない入力を提供し、プログラムが不正な入力を処理する方法を悪用することによって攻撃します。適切に作成されたプログラムは、これらの仮定を回避します。空港のセキュリティでは、乗客の手荷物検査に PHP プログラムが使用されます。
その他の問題は軽微な論理エラーです。たとえば、一連のパラメーターをチェックして、ユーザーがリソースへのアクセスを許可されているかどうか、または括弧の位置が間違っていて、一部のユーザーがアクセスすべきではない場所にアクセスしていないかどうかを確認します。私たちは、アプリケーションが適切に整理され、一元化されたロジックを備えていることを望んでいます。
ユーザー入力の識別に関して最も注意が必要なことの 1 つは、外部ソース (ユーザー、別の Web サイト、またはその他のリソースなど) からの信頼できない入力と検証済みのデータをどのように区別するかです。誰かが「すべてを信頼するわけではない」という議論を行い、すべての関数について、そのデータの出所に関係なく、そのデータを検証する必要があると主張しました。このアプローチにはいくつかの点が含まれます。1 つ目は、検証はコンテキストによって異なる意味を持ちます。2 つ目は、アプリケーションのすべてのレベルで検証を迅速に実行するのは面倒でエラーが発生しやすいことです。3 つ目は、アプリケーションを最初から書き直すのではなく監査することです。既存のコードを通じてユーザー入力を追跡する必要がありますが、表示されるすべての変数を検証関数でラップすることはできません。
予期しないユーザー入力
ユーザー入力はどこから来たのか?最初のソースは GET、POST、COOKIE データです。一般に GPC データと呼ばれます。このデータを識別するプロセスは、物議を醸している php.ini 設定 register_globals に依存しています。 PHP V4.3.0 では、register_globals はデフォルトで Off に設定されています。しかし、数年前、PHP では register_globals のデフォルト値が on だったので、それを必要とするコードがたくさんありました。
register_globals自体はセキュリティリスクではありません。ただし、ユーザー入力を追跡し、アプリケーションを保護することがより困難になります。なぜこうなった? register_globals がオンになっている場合、PHP スクリプトに渡されるすべての GET、POST、および COOKIE 変数は、グローバル名前空間と $_GET、$_POST、または $_COOKIE 配列に作成されるためです。
これがどのように機能するのか、なぜそれが重要なのかの例を次に示します。
リスト 1. COOKIE SECURITY
1 2
3 // ユーザーが秘密の Cookie を持っているかどうかを確認します。
4 if (!empty ( $_COOKIE['secret'])) {
5 $authorized = true;
6 }
7
8 // 次に、プレスリリースのリストを見て、それらを表示しましょう
9 $releases = get_press_releases();
10 foreach ($release として $release) {
11
12 // 一部のリリースは表示できる人にのみ表示されます
13 // シークレットを参照してください
14 if ($release['secret']) {
15 if (!$authorized) {
16 continue;
17 }
18 }
19
20 // We should be allowed to see it.
21 showRelease($release);
22 }
注意すべき点がいくつかあります。まず、ユーザーが認証されているかどうかを Cookie に依存するのは得策ではありません。ユーザーは独自の Cookie 値を簡単に設定できるからです。これについては別の記事で説明します。とにかく、このスクリプトの欠点は、 register_globals がオンになっている場合は安全ではないことです。
以下にpress.phpというスクリプトを紹介します。一般に、ユーザーがプレス配布のスクリプトにアクセスすると、ブラウザーには http://www.example.com/company/press.php が表示されます。
ここで、ユーザーが http://www.example.com/company/press.php?authorized=1? に変更すると何が起こるかに注目してください。
前のコードを見てください: $authorized は、ユーザーが Cookie を使用する場合にのみ設定されます。 false に設定されることはありません。その後 register_globals が導入されました。これは、先ほど使用した $_GET['authorized'] を置き換えるもので、グローバル スコープ内に値 1 を持つ変数 $authorized もありました。したがって、ユーザーが Cookie チェックに失敗した場合でも、後で foreach ループで参照されるときに $authorized は true として検証されます。
この不具合を修正するには2つの方法があります。 1 つは、もちろん register_globals をオフにすることです。これをオフにしても運用サイトに影響がない場合は、オフにすることをお勧めします。アプリケーションをテストして、壊れないことを確認する必要があります。
もう一つのアプローチは「守りのプログラミング」に似ています。 Cookie チェックを次の形式に変更するだけです:
リスト 2. COOKIE を使用してセキュリティを向上させる
1 2
3 // ユーザーが秘密の Cookie を持っているかどうかを確認します。
4 $authorized = false;
5 if (!empty($_COOKIE['secret'])) {
6 $authorized = true;
7 }
...
このとき、ユーザーが?authorized=1をscript URL では、$authorized 変数は依然として 1 に設定されていますが、$authorized = false で上書きされ、実際にシークレット Cookie を持っているユーザーのみが制限されたプレス リリースを閲覧できるようになります。独自のクッキーをデザインすることもできます。
コード監査からの教訓: register_globals をオフにしてみてください。 register_globals をオンにしないとアプリケーションが実行されず、変更できない場合、またはアプリケーションを実行する必要がある PHP 構成を制御できない場合は、条件ブロックですべてのグローバル変数設定を見つけるか、いくつかの関数呼び出しスコープを介してグローバル。 register_globals がオンの場合、どちらの場合もユーザーが変数を任意の値に設定することが原因で発生します。
これらの変数を見つける良い方法は、php.ini 設定 error_reporting を E_ALL に設定し、log_errors または display_errors を使用することです。これにより、すべての PHP 警告とエラーがそれぞれファイルに記録されるか、画面に表示されます。初期化されていない変数 (値があると想定される) を使用すると、E_NOTICE が返されます。これは、C 言語や Java 言語のように、PHP で変数の宣言を必要とするのとは異なります。その結果、最初のバージョンのスクリプトを実行すると、次のようなエラー メッセージが表示されました。