淺析php中open_basedir存在安全隱患

來源:互聯網
上載者:User

先看一段我們不考慮open_basedir安全問題代碼

在php寫了句require_once ‘../Zend/Loader.php’; 報錯:
Warning: require_once() [function.require-once]: open_basedir restriction in effect. File(../Zend/Loader.php) is not within the allowed path(s): (D:/phpnow/vhosts/zf.com;C:/Windows/Temp;) in D:/phpnow/vhosts/zf.com/index.php on line 6

Warning: require_once(../Zend/Loader.php) [function.require-once]: failed to open stream: Operation not permitted in D:/phpnow/vhosts/zf.com/index.php on line 6

Fatal error: require_once() [function.require]: Failed opening required '../Zend/Loader.php' (include_path='D:/phpnow/vhosts/zf.comZend;.;C:/php5/pear') in D:/phpnow/vhosts/zf.com/index.php on line 6字面分析是受到了open_basedir的限制,造成Operation not permitted(操作不被允許)。


開啟php.ini跳轉到open_basedir相關設定段落:

; open_basedir, if set, limits all file operations to the defined directory
; and below.  This directive makes most sense if used in a per-directory
; or per-virtualhost web server configuration file. This directive is
; *NOT* affected by whether Safe Mode is turned On or Off.

;open_basedir =如果設定了open_basedir,那麼所有能被操作的檔案就只能限制在open_basedir指定的目錄裡面。 這個在虛擬機器主機裡面這個指令相當有用。不管安全模式是否開啟,這個指令都不受影響。 看來php.ini沒有設定open_basedir。 開啟apache虛擬機器主機設定檔:

 代碼如下 複製代碼

<virtualhost *>
    <directory "../vhosts/zf.com">
        Options -Indexes FollowSymLinks
    </directory>
    ServerAdmin admin@zf.com
    DocumentRoot "../vhosts/zf.com"
    ServerName zf.com:80
    ServerAlias *.zf.com
    ErrorLog logs/zf.com-error_log
    php_admin_value open_basedir "D:/phpnow/vhosts/zf.com;C:/Windows/Temp;"
</virtualhost>

裡面的php_admin_value open_basedir就限定了操作目錄。我這裡是本地測試,安全因素不考慮,直接將 php_admin_value open_basedir “D:/phpnow/vhosts/zf.com;C:/Windows/Temp;” 刪除掉,重新啟動apache,

上面如果給利用完可以可隨意刪除伺服器檔案了,但是比較幸運的是目前php網站的安全配置基本是open_basedir+safemode,確實很無敵、很安全,即使在許可權沒有很好設定的環境中,這樣配置都是相當安全的,當然了,不考慮某些可以繞過的情況。本文討論兩點開啟open_basedir後可能導致的安全隱患(現實遇到的),一個也許屬於php的一個小bug,另外一個可能是由於配置不當產生的。

一、open_basedir中處理檔案路徑時沒有嚴格考慮目錄的存在,這將導致當地套件含或者本地檔案讀取的繞過。

看一個本地檔案任意讀取的例子:

 代碼如下 複製代碼
<?php
$file = $_GET['file'];
preg_match("/^img/", $file) or die('error_file');
$file='/home/www/upload/'.$file;
file_exists($file) or die('no_such_file');
$f = fopen("$file", 'r');
$jpeg = fread($f, filesize("$file"));
fclose($f);
Header("Content-type: image/jpeg");
Header("Content-disposition: inline; filename=test.jpg");
echo $jpeg;
?>

雖然file是任意提交的,但是限制了首碼必須為img,我們如果想跳出目錄讀檔案,比如,讀取網站根目錄下的config.php,我們得提交?file=img/../../config.php,但是此處有個限制條件,就是upload目錄下不存在img檔案夾,在windows檔案系統裡,系統不會去考慮目錄存在不存在,會直接跳轉目錄從而導致漏洞;但linux檔案系統非常嚴謹,它會仔細判斷每一層目錄是否存在,比如這裡由於不存在img,則跳出去讀取檔案的時候直接報錯。看如下一個示意圖:


再看一個類似的當地套件含的例子:

 代碼如下 複製代碼
<?php
include "aaa".$_GET['lang'].".php";
?>

由於linux檔案系統的限制,我們無法利用旁註去包含tmp下的檔案。

linux嚴謹的考慮在php那裡顯然沒有得到深刻的體會。在開啟了open_basedir的時候,php對傳入的檔案路徑進行了取真實路徑的處理,然後跟open_basedir中設定的路徑進行比較:

 代碼如下 複製代碼

……
/* normalize and expand path */
if (expand_filepath(path, resolved_name TSRMLS_CC) == NULL) {
return -1;
}

path_len = strlen(resolved_name);
memcpy(path_tmp, resolved_name, path_len + 1); /* safe */
……

但php在處理的時候忽略了檢查路徑是否存在,於是在開啟了open_basedir時,上面那個檔案讀取的例子,我們可以使用?file=img/../../config.php來直接讀取了,此時提交的路徑已經被處理成/home/www/config.php了,所以不存在任何讀取問題了。

問題由滲透測試的時候遇到繞過的情況從而導致疑問,經分析環境差異,然後xi4oyu牛指點有可能是open_basedir的問題後測試總結出這是php的一個小的bug,但是很有可能導致安全隱患。

二、open_basedir的值配置不當,有可能導致目錄跨越。

很多管理員都知道設定open_basedir,但在配置不當的時候可能發生目錄跨越的問題。

錯誤的配置:/tmp:/home/www,正確的配置:/tmp/:/home/www/

 代碼如下 複製代碼

……
/* Resolve open_basedir to resolved_basedir */
if (expand_filepath(local_open_basedir, resolved_basedir TSRMLS_CC) != NULL) {
/* Handler for basedirs that end with a / */
resolved_basedir_len = strlen(resolved_basedir);
if (basedir[strlen(basedir) - 1] == PHP_DIR_SEPARATOR) {
if (resolved_basedir[resolved_basedir_len - 1] != PHP_DIR_SEPARATOR) {
resolved_basedir[resolved_basedir_len] = PHP_DIR_SEPARATOR;
resolved_basedir[++resolved_basedir_len] = '/0';
}
} else {
resolved_basedir[resolved_basedir_len++] = PHP_DIR_SEPARATOR;
resolved_basedir[resolved_basedir_len] = '/0';
}
……

php考慮了以/結束的路徑,但是如果沒有/,就直接帶入下文比較了。

於是,當建立一個網站為 /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 檔案中中,open_basedir 可以像其它任何配置選項一樣用“php_admin_value open_basedir none”的方法關閉(例如某些虛擬機器主機中)。

在 Windows 中,用分號分隔目錄。在任何其它系統中用冒號分隔目錄。作為 Apache 模組時,父目錄中的 open_basedir 路徑自動被繼承。

用 open_basedir 指定的限制實際上是首碼,不是目錄名。也就是說“open_basedir = /dir/incl”也會允許訪問“/dir/include”和“/dir/incls”,如果它們存在的話。如果要將訪問限制在僅為指定的目錄,用斜線結束路徑名。例如:“open_basedir = /dir/incl/”。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.