PHP安全性漫談

 

最近剛作完兩個PHP的網站項目,客戶雖然沒有安全性的相關需求,可是本身不能放過對本身的要求,況且對之後作電子商務的項目至關有幫助,呵呵,早準備早超生,通過查看PHP 幫助和相關資料~~~~                 本文所討論的安全性環境是在Linux+Apache+Mysql+PHP。超出此範圍的安全性問題不在本文範疇以內。
1、apache server安全性設置                                   一、以Nobody用戶運行
通常狀況下,Apache是由Root 來安裝和運行的。若是Apache Server進程具備Root用戶特權,那麼它將給系統的安全構成很大的威脅,應確保Apache Server進程以最可能低的權限用戶來運行。經過修改httpd.conf文件中的下列選項,以Nobody用戶運行Apache 達到相對安全的目的。 User nobody Group# -1
二、ServerRoot目錄的權限
爲了確保全部的配置是適當的和安全的,須要嚴格控制Apache 主目錄的訪問權限,使非超級用戶不能修改該目錄中的內容。Apache 的主目錄對應於Apache Server配置文件httpd.conf的Server Root控制項中,應爲: Server Root /usr/local/apache
三、SSI的配置
在配置文件access.conf 或httpd.conf中的確Options指令處加入Includes NO EXEC選項,用以禁用Apache Server 中的執行功能。避免用戶直接執行Apache 服務器中的執行程序,而形成服務器系統的公開化。
四、阻止用戶修改系統設置
在Apache 服務器的配置文件中進行如下的設置,阻止用戶創建、修改 .htaccess文件,防止用戶超越能定義的系統安全特性。
而後再分別對特定的目錄進行適當的配置。
五、改變Apache 服務器的缺省訪問特性
Apache 的默認設置只能保障必定程度的安全,若是服務器可以經過正常的映射規則找到文件,那麼客戶端便會獲取該文件,如http://local host/~ root/ 將容許用戶訪問整個文件系統。在服務器文件中加入以下內容:
將禁止對文件系統的缺省訪問。
六、CGI腳本的安全考慮
CGI腳本是一系列能夠經過Web服務器來運行的程序。爲了保證系統的安全性,應確保CGI的做者是可信的。對CGI而言,最好將其限制在一個特定的目 錄下,如cgi-bin之下,便於管理;另外應該保證CGI目錄下的文件是不可寫的,避免一些欺騙性的程序駐留或混跡其中;若是可以給用戶提供一個安全性 良好的CGI程序的模塊做爲參考,也許會減小許多沒必要要的麻煩和安全隱患;除去CGI目錄下的全部非業務應用的腳本,以防異常的信息泄漏。
七、SSL連接加密
以上這些經常使用的舉措能夠給Apache Server 一個基本的安全運行環境,顯然在具體實施上還要作進一步的細化分解,制定出符合實際應用的安全配置方案。
2、PHP安全性設置           服務器並不能阻止全部的安全問題,例如程序漏洞問題、用戶輸入表單問題、PHP文件權限問題等。 也能夠經過一些手段來迷惑黑客或者別有用心者。 一、程序代碼漏洞問題

不少 PHP 程序所存在的重大弱點並非 PHP  語言自己的問題,而是編程者的安全意識不高而致使的。所以,必須時時注意每一段代碼可能存在的問題,去發現非正確數據提交時可能形成的影響。php

<?php unlink ($evil_var); fwrite ($fp, $evil_var); system ($evil_var); exec  ($evil_var); ?>html

必須時常留意你的代碼,以確保每個從客戶端提交的變量都通過適當的檢查,而後問本身如下一些問題:web

  • 此腳本是否只能影響所預期的文件?
  • 非正常的數據被提交後可否產生做用?
  • 此腳本能用於計劃外的用途嗎?
  • 此腳本可否和其它腳本結合起來作壞事?
  • 是否全部的事務都被充分記錄了?

在寫代碼的時候問本身這些問題,不然之後可能要爲了增長安全性而重寫代碼了。注意了這些問題的話,也許還不徹底能保證系統的安全,可是至少能夠提升安全性。sql

還能夠考慮關閉 register_globals,magic_quotes 或者其它使編程更方便但會使某個變量的合法性,來源和其值被搞亂的設置。數據庫

二、用戶輸入表單問題 驗證用戶輸入的任何數據,保證PHP代碼的安全。 注意1:JS只是爲了提升來訪用戶的體驗而產生的,而不是驗證的工具。由於任何一個來訪的用戶均可能會,也有可能無心間就禁用了客戶端腳本的執行,從而跳過這層驗證。因此咱們必須在PHP的服務器端程序上檢驗這些數據。 注意2:不要使用$_SERVER['HTTP_REFERER']這個超級變量來檢查數據的來源地址,一個很小的菜鳥黑客都會利用工具來僞造這個變量的數據,儘量利用Md5,或者rand等函數來產生一個令牌,驗證來源的時候,驗證這個令牌是否匹配。
三、PHP文件權限問題

PHP 被設計爲以用戶級別來訪問文件系統,因此徹底有可能經過編寫一段 PHP 代碼來讀取系統文件如  /etc/passwd,更改網絡鏈接以及發送大量打印任務等等。所以必須確保 PHP 代碼讀取和寫入的是合適的文件。 請看下面的代碼,用戶想要刪除本身主目錄中的一個文件。假設此情形是經過 web 界面來管理文件系統,所以 Apache 用戶有權刪除用戶目錄下的文件。apache

<?php $username =  $_POST['user_submitted_name']; $homedir  = "/home/$username"; $file_to_delete  = "$userfile"; unlink  ("$homedir/$userfile"); echo "$file_to_delete has been deleted!"; ?>

既然 username 變量能夠經過用戶表單來提交,那就能夠提交別人的用戶名和文件名,並刪除該文件。這種狀況下,就要考慮其它方式的認證:編程

  • 只給 PHP 的 web 用戶頗有限的權限。
  • 檢查全部提交上來的變量。
如下是更加安全的文件名和變量的驗證和檢查: <?php $username  = $_SERVER['REMOTE_USER']; $homedir =  "/home/$username";
if (!ereg('^[^./][^/]*$',  $userfile)) die('bad  filename');
if (!ereg('^[^./][^/]*$',  $username)) die('bad  username'); ?>

四、隱藏PHP擴展名

通常而言,經過隱藏的手段提升安全性被認爲是做用不大的作法。但某些狀況下,儘量的多增長一份安全性都是值得的。數組

一些簡單的方法能夠幫助隱藏 PHP,這樣作能夠提升攻擊者發現系統弱點的難度。在 php.ini  文件裏設置 expose_php = off ,能夠減小他們能得到的有用信息。安全

另外一個策略就是讓 web 服務器用 PHP 解析不一樣擴展名。不管是經過 .htaccess  文件仍是 Apache 的配置文件,均可以設置能誤導攻擊者的文件擴展名:服務器

# 使PHP看上去像其它的編程語言 AddType  application/x-httpd-php .asp .py .pl
# 使 PHP 看上去像未知的文件類型 AddType  application/x-httpd-php .bop .foo .133t
# 使 PHP 代碼看上去像 HTML 頁面 AddType application/x-httpd-php  .htm .html
要讓此方法生效,必須把 PHP 文件的擴展名改成以上的擴展名。這樣就經過隱藏來提升了安全性,雖然防護能力很低並且有些缺點。 3、Mysql數據庫安全性設置

PHP 自己並不能保護數據庫的安全。下面的章節只是講述怎樣用 PHP 腳本對數據庫進行基本的訪問和操做。記住一條簡單的原則:深刻防護。保護數據庫的措施越多,攻擊者就越難得到和使用數據庫內的信息。正確地設計和應用數據庫能夠減小被攻擊的擔心。

一、數據庫設計問題

應用程序永遠不要使用數據庫全部者或超級用戶賬號來鏈接數據庫,由於這些賬號能夠執行任意的操做,好比說修改數據庫結構(例如刪除一個表)或者清空整個數據庫的內容。如下截圖的用戶設置是危險的。

 


 

應該爲程序的每一個方面建立不一樣的數據庫賬號,並賦予對數據庫對象的極有限的權限。僅分配給能完成其功能所需的權限,避免同一個用戶能夠完成另外一個用戶的事情。這樣即便攻擊者利用程序漏洞取得了數據庫的訪問權限,也最多隻能作到和該程序同樣的影響範圍。

 

 

 

2.數據庫鏈接問題

把鏈接創建在 SSL 加密技術上能夠增長客戶端和服務器端通訊的安全性,或者 SSH  也能夠用於加密客戶端和數據庫之間的鏈接。若是使用了這些技術的話,攻擊者要監視服務器的通訊或者獲得數據庫的信息是很困難的。

3.數據庫數據的加密

SSL/SSH 能保護客戶端和服務器端交換的數據,但 SSL/SSH 並不能保護數據庫中已有的數據。SSL 只是一個加密網絡數據流的協議。

若是攻擊者取得了直接訪問數據庫的許可(繞過 web  服務器),敏感數據就可能暴露或者被濫用,除非數據庫本身保護了這些信息。對數據庫內的數據加密是減小這類風險的有效途徑,可是隻有不多的數據庫提供這些加密功能。

對於這個問題,有一個簡單的解決辦法,就是建立本身的加密機制,而後把它用在 PHP 程序內,最多見的例子就是把密碼通過 MD5 加密後的散列存進數據庫來代替原來的明文密碼。

<?php
$query  =  sprintf("INSERT INTO  users(name,pwd) VALUES('%s','%s');", addslashes($username),  md5($password)); $result  = pg_query($connection,  $query);
$query = sprintf("SELECT 1 FROM users WHERE name='%s' AND  pwd='%s';", addslashes($username),  md5($password)); $result  = pg_query($connection,  $query);
if (pg_num_rows($result) > 0) { echo 'Welcome, $username!'; } else { echo 'Authentication failed for $username.'; }
?>

四、SQL注入問題

直接 SQL 命令注入就是攻擊者經常使用的一種建立或修改已有 SQL  語句的技術,從而達到取得隱藏數據,或覆蓋關鍵的值,甚至執行數據庫主機操做系統命令的目的。這是經過應用程序取得用戶輸入並與靜態參數組合成 SQL  查詢來實現的。下面將會給出一些真實的例子。

<?php
$query  = "SELECT id, name,  inserted, size FROM products WHERE size = '$size' ORDER BY $order LIMIT $limit, $offset;"; $result  = odbc_exec($conn, $query);
?>

能夠在原來的查詢的基礎上添加另外一個 SELECT 查詢來得到密碼:

union select '1',  concat(uname||'-'||passwd) as name, '1971-01-01', '0' from  usertable;

假如上述語句(使用 '--)被加入到  $query 中的任意一個變量的話,那麼就麻煩了。

這些攻擊老是創建在發掘安全意識不強的代碼上的。因此,永遠不要信任外界輸入的數據,特別是來自於客戶端的,包括選擇框、表單隱藏域和  cookie。就如上面的第一個例子那樣,就算是正常的查詢也有可能形成災難。

  • 永遠不要使用超級用戶或全部者賬號去鏈接數據庫。要用權限被嚴格限制的賬號。
  • 檢查輸入的數據是否具備所指望的數據格式。PHP 有不少能夠用於檢查輸入的函數,從簡單的和(好比 ,)到複雜的 均可以完成這個工做。
  • 若是程序等待輸入一個數字,能夠考慮使用  來檢查,或者直接使用  來轉換它的類型,也能夠用  把它格式化爲數字。

一個更安全的防止SQL注入的分頁顯示方法: <?phpsettype($offset, 'integer'); $query  = "SELECT id, name FROM products ORDER BY name LIMIT 20  OFFSET $offset;"; $query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20  OFFSET %d;", $offset);?>
相關文章
相關標籤/搜索