PHP安全配置2

來源:互聯網
上載者:User

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."上傳成功!點擊<a href=\"$PHP_SELF\">繼續上傳</a>";
 exit;
}
?>
<html>
<head>
<title>檔案上傳</title>
<meta http-equiv="Content-Type"
 content="text/html; charset=gb2312">
</head>
<body bgcolor="#FFFFFF">
<form enctype="multipart/form-data" method="post">
上傳檔案:
<input type="file"  name="file" size="30">
<input type="submit" name="upload" value="上傳">
</form>
</body>
</html>
 

這樣的上傳代碼存在讀取任意檔案和執行命令的重大問題。

下面的請求可以把/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變數的值,上傳覆蓋任意有寫入權限的檔案。

攻擊者還可以上傳PHP指令碼執行主機的命令。

解決方案:

PHP-4.0.3以後提供了is_uploaded_file和move_uploaded_file函數,可以檢查操作的檔案是否是使用者上傳的檔案,從而避免把系統檔案拷貝到web目錄。

使用$HTTP_POST_FILES數組來讀取使用者上傳的檔案變數。

嚴格檢查上傳變數。比如不允許是php指令檔。

把PHP指令碼操作限制在web目錄可以避免程式員使用copy函數把系統檔案拷貝到web目錄。move_uploaded_file不受open_basedir的限制,所以不必修改php.ini裡upload_tmp_dir的值。

把PHP指令碼用phpencode進行加密,避免由於copy操作泄漏源碼。

嚴格設定檔和目錄的許可權,只允許上傳的目錄能夠讓nobody使用者可寫。

對於上傳目錄去掉PHP解釋功能,可以通過修改httpd.conf實現:

<Directory /usr/local/apache/htdocs/upload>
  php_flag engine off
  #如果是php3換成php3_engine off
</Directory>
 

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

6、命令執行

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

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

<?
//test_6.php
system("traceroute $a_query",$ret_strs);
?>
 

由於程式沒有過濾$a_query變數,所以攻擊者可以用分號來追加執行命令。

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

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

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

解決方案:

要求程式員使用escapeshellcmd()函數過濾使用者輸入的shell命令。

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

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攻擊。

對於數字類型的欄位,很多程式員會這樣寫:

select * from test where id=$id
 

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

解決方案:

要求程式員對所有使用者提交的要放到SQL語句的變數進行過濾。

即使是數字類型的欄位,變數也要用單引號擴起來,MySQL自己會把字串處理成數字。

在MySQL裡不要給PHP程式進階別許可權的使用者,只允許對自己的庫進行操作,這也避免了程式出現問題被 SELECT INTO OUTFILE ... 這種攻擊。

8、警告及錯誤資訊

PHP預設顯示所有的警告及錯誤資訊:

error_reporting  =  E_ALL & ~E_NOTICE
display_errors = On
 

在平時開發調試時這非常有用,可以根據警告資訊馬上找到程式錯誤所在。

正式應用時,警告及錯誤資訊讓使用者不知所措,而且給攻擊者泄漏了指令碼所在的實體路徑,為攻擊者的進一步攻擊提供了有利的資訊。而且由於自己沒有訪問到錯誤的地方,反而不能及時修改程式的錯誤。所以把PHP的所有警告及錯誤資訊記錄到一個記錄檔是非常明智的,即不給攻擊者泄漏實體路徑,又能讓自己知道程式錯誤所在。

修改php.ini中關於Error handling and logging部分內容:

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

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

disable_functions = phpinfo, get_cfg_var
 

可以指定多個函數,用逗號分開。重啟apache後,phpinfo, get_cfg_var函數都被禁止了。建議關閉函數phpinfo, get_cfg_var,這兩個函數容易泄漏伺服器資訊,而且沒有實際用處。

10、disable_classes

這個選項是從PHP-4.3.2開始才有的,它可以禁用某些類,如果有多個用逗號分隔類名。disable_classes也不能在httpd.conf裡設定,只能在php.ini設定檔裡修改。

11、open_basedir

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

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

四、其它安全配置

1、取消其它使用者對常用、重要系統命令的讀寫執行許可權

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

如果要取消某程如果是在chroot環境裡,這個工作比較容易實現,否則,這項工作還是有些挑戰的。因為取消一些程式的執行許可權會導致一些服務運行不正常。PHP的mail函數需要/bin/sh去調用sendmail發信,所以/bin/bash的執行許可權不能去掉。這是一項比較累人的工作,

2、去掉apache日誌其它使用者的讀許可權

apache的access-log給一些出現當地套件含漏洞的程式提供了方便之門。通過提交包含PHP代碼的URL,可以使access-log包含PHP代碼,那麼把包含檔案指向access-log就可以執行那些PHP代碼,從而獲得本地存取權限。

如果有其它虛擬機器主機,也應該相應去掉該記錄檔其它使用者的讀許可權。

當然,如果你按照前面介紹的配置PHP那麼一般已經是無法讀取記錄檔了。



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.