ホームページ  >  記事  >  バックエンド開発  >  PHP_PHP チュートリアルでの open_basedir のセキュリティ リスクの簡単な分析

PHP_PHP チュートリアルでの open_basedir のセキュリティ リスクの簡単な分析

WBOY
WBOYオリジナル
2016-07-13 10:47:591256ブラウズ

php では、open_basedir はめったに使用されない関数ですが、open_basedir 関数により、誰かがサーバーに誤ってアクセスできるようになる可能性があります。open_basedir がいかに魔法であるかを見てみましょう。

まず、open_basedir のセキュリティ問題を考慮していないコードを見てみましょう

PHP で require_once '../Zend/Loader.php' を記述します:
警告: require_once() [function.require-once]: open_basedir 制限が有効です。ファイル (../Zend/Loader.php) が許可されたパス内にありません: (D:/phpnow/vhosts/zf.com) ;C:/Windows/Temp;) D:/phpnow/vhosts/zf.com/index.php の 6 行目

警告: require_once(../Zend/Loader.php) [function.require-once]: ストリームを開けませんでした: 6 行目の D:/phpnow/vhosts/zf.com/index.php では操作は許可されていません

致命的なエラー: require_once() [function.require]: 必要な '../Zend/Loader.php' を開くことができませんでした (include_path='D:/phpnow/vhosts/zf.comZend;.;C:/php5/pear) ') D:/phpnow/vhosts/zf.com/index.php の 6 行目 リテラル分析が open_basedir によって制限されているため、操作が許可されません。


php.ini を開き、open_basedir の関連する設定セクションに移動します。

; open_basedir を設定すると、すべてのファイル操作が定義されたディレクトリに制限されます
; 以下。このディレクティブはディレクトリごとに使用する場合に最も意味があります
。 ; または仮想ホストごとの Web サーバー構成ファイルです。 ; セーフ モードがオンかオフかは *影響を受けません。

;open_basedir =open_basedir が設定されている場合、操作できるすべてのファイルは open_basedir で指定されたディレクトリにのみ制限されます。 このコマンドは仮想ホストで非常に便利です。このコマンドは、セーフ モードがオンになっているかどうかに影響されません。 php.iniではopen_basedirの設定がされていないようです。 Apache 仮想ホスト構成ファイルを開きます:

コードは次のとおりですコードをコピー

<ディレクトリ「../vhosts/zf.com」>
オプション - インデックス FollowSymLinks

ServerAdmin admin@zf.com
ドキュメントルート「../vhosts/zf.com」
サーバー名 zf.com:80
サーバーエイリアス*.zf.com
ErrorLog ログ/zf.com-error_log
php_admin_value open_basedir "D:/phpnow/vhosts/zf.com;C:/Windows/Temp;"

open_basedir 内の php_admin_value は、操作ディレクトリを制限します。これはローカルテストです。セキュリティ要素は考慮していません。php_admin_value open_basedir「D:/phpnow/vhosts/zf.com;C:/Windows/Temp;」を削除して、Apache を再起動します。

上記の使用が終了したら、サーバーファイルを自由に削除できますが、幸いなことに、PHP サイトの現在のセキュリティ構成は基本的に open_basedir+safemode であり、権限が十分でない環境でも確かに無敵で安全です。もちろん、回避できるいくつかの状況を除いて、この構成は非常に安全です。この記事では、open_basedir をオンにすることによって引き起こされる可能性のある 2 つの潜在的なセキュリティ リスク (実際に発生する) について説明します。1 つは PHP の小さなバグで、もう 1 つは不適切な設定が原因である可能性があります。

1. Open_basedir は、ファイル パスを処理するときにディレクトリの存在を厳密に考慮しないため、ローカル インクルードまたはローカル ファイル読み取りがバイパスされます。

ローカル ファイルの任意の読み取りの例を見てください:

コードは次のとおりです $file = $_GET['ファイル'];

ファイルは任意に送信できますが、ディレクトリからファイルを読み込む場合、たとえば Web サイトのルート ディレクトリにある config.php を読み込む場合、プレフィックスは img でなければならないという制限があります。 submit?file=img/../.. /config.php ですが、ここには制限があります。つまり、Windows ファイル システムでは、img フォルダーがアップロード ディレクトリに存在しないかどうかがシステムによって考慮されません。ディレクトリが存在するかどうかを判断し、そのディレクトリに直接ジャンプするため、脆弱性が発生します。ただし、Linux では、各ディレクトリが存在するかどうかを慎重に判断します。たとえば、ここには img が存在しないため、直接レポートされます。ファイルを読み込むために飛び出したときにエラーが発生します。次の図を見てください:


ローカルインクルージョンの同様の例を見てみましょう:

コードをコピー
preg_match("/^img/", $file) または die('error_file');
$file='/home/www/upload/'.$file;
file_exists($file) または die('no_ such_file');
$f = fopen("$file", 'r');
$jpeg = fread($f, filesize("$file"));
fclose($f);
Header("コンテンツタイプ: image/jpeg");
Header("Content-disposition: inline; filename=test.jpg");
エコー $jpeg;
?>


コードは次のとおりです コードをコピー
include "aaa".$_GET['lang'].".php";
?>

Linux ファイル システムの制限により、サイド ノートを使用して tmp の下にファイルを含めることはできません。

Linux の厳密な考察は、明らかに PHP では深く理解されていません。 open_basedir がオンになっている場合、PHP は受信ファイル パスを処理して実際のパスを取得し、それを open_basedir に設定されているパスと比較します。

コードは次のとおりですコードをコピー
……

/* パスを正規化して展開します */
if (expand_filepath(path,solved_name TSRMLS_CC) == NULL) {
-1 を返します;
}

path_len = strlen(resolved_name);

memcpy(path_tmp,solved_name,path_len + 1); /* 安全 */

ただし、php は処理中にパスが存在するかどうかのチェックを無視するため、open_basedir がオンになっている場合、上記のファイル読み取りの例では、?file=img/../../config.php を使用して直接読み取ることができます。送信されたパスは /home/www/config.php に処理されているため、読み取りの問題はありません。

この問題は侵入テスト中のバイパス状況によって引き起こされたもので、環境の違いを分析した結果、open_basedir に問題がある可能性があると xi4oyu Niu 氏が指摘しました。 PHP ですが、セキュリティ リスクを引き起こす可能性が非常に高かったです。

2. open_basedir の値の設定が不適切であると、ディレクトリのスパニングが発生する可能性があります。

多くの管理者は open_basedir の設定方法を知っていますが、設定が不適切な場合にはディレクトリにまたがる問題が発生する可能性があります。

間違った構成: /tmp:/home/www、正しい構成: /tmp/:/home/www/

コードは次のとおりですコードをコピー

phpは/で終わるパスを考慮しますが、/がない場合はそのまま次の比較に持ち込まれます。

つまり、新しい Web サイトが /home/wwwoldjun/ である場合 (open_basedir は別途設定されています)、設定が間違っている場合は、/home/www/ ディレクトリから /home/wwwoldjun/ ディレクトリにジャンプできます。

たとえば、仮想ホストをレンタルする場合、IDC はスペース /home/wwwroot/userxxx/, /home/wwwroot/useryyy/... を割り当てますが、open_basedir は次のように誤って構成されています: /tmp:/home /wwwroot/userxxx, /tmp:/home/wwwroot/useryyy。設定エラーによって userxxx サイトに簡単に侵入したい場合は、どうすればよいでしょうか?


特別な値 . は、スクリプトの作業ディレクトリがベース ディレクトリとして使用されることを指定します。ただし、スクリプトの作業ディレクトリは chdir() によって簡単に変更できるため、これは多少危険です。

httpd.conf ファイルでは、「php_admin_value open_basedir none」メソッド (一部の仮想ホストなど) を使用して、他の構成オプションと同様に open_basedir をオフにすることができます。

Windows では、ディレクトリをセミコロンで区切ります。他のシステム上のディレクトリを区切るにはコロンを使用します。 Apache モジュールとして、親ディレクトリの open_basedir パスが自動的に継承されます。

open_basedir で指定される制限は、実際にはディレクトリ名ではなくプレフィックスです。これは、「open_basedir = /dir/incl」により、「/dir/include」および「/dir/incls」が存在する場合には、それらへのアクセスも許可されることを意味します。指定したディレクトリのみへのアクセスを制限したい場合は、パス名の末尾にスラッシュを付けます。例: 「open_basedir = /dir/incl/」。

……

/* open_basedir をsolved_basedir に解決します */
if (expand_filepath(local_open_basedir,solved_basedir TSRMLS_CC) != NULL) {
/* / */
で終わる basedirs のハンドラー solved_basedir_len = strlen(resolved_basedir);
if (basedir[strlen(basedir) - 1] == PHP_DIR_SEPARATOR) {
if (resolved_basedir[resolved_basedir_len - 1] != PHP_DIR_SEPARATOR) {
solved_basedir[resolved_basedir_len] = PHP_DIR_SEPARATOR;
solved_basedir[++resolved_basedir_len] = '/0';
}
} その他 {
solved_basedir[resolved_basedir_len++] = PHP_DIR_SEPARATOR;
solved_basedir[resolved_basedir_len] = '/0';
}

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/632831.html技術記事 php では、open_basedir はめったに使用されない関数ですが、open_basedir 関数により、誰かがサーバーに誤って侵入する可能性があります。open_basedir がどれほど素晴らしいかを見てみましょう...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。