該頁面旨在為開發者和管理者提供有關PHP安全的基本提示。請注意,為了確保Web應用的安全性,僅通過本頁說明的提示可能還不够。
PHP概要
PHP是最常用的服務器側面程式設計語言,根據W3 Techs 81.8%的Web服務器被採用。
作為開放源的科技PHP,是語言的同時Web框架也有這樣的點獨特,標準的Web框架機能被語言編入。和其他Web語言一樣,存在諸如圖書館等大型社區,有助於PHP程式設計的安全性。在致力於PHP網站的安全確保時,需要全部考慮這個3個側面(語言,框架,庫)的全部。
與其說PHP是慎重被設計了的語言,倒不如說是反復增長的語言,容易容易記述了不安全的PHP應用程序。為了安全地使用PHP,必須預先掌握那個潜在的危險性。
語言的問題點
指定弱型
PHP關於型號指定是鬆散。也就是說,在PHP中,不合適類型的數據會自動轉換成應該處理的類型。這個功能往往掩蓋了開發者錯誤和不適當的數據的插入,導致脆弱性(關於例子參照下麵的「輸入處理」)。
使用不進行隱式轉換的函數和運算子。例如,使用===而不是==並不是所有的運算子都具有嚴格的版本(如更大、更小等)。此外,在許多嵌入函數(in_array等)中,定義了類型較弱的比較函數。這使得難以描述合適的程式碼。
==
===
in_array
==
===
in_array
例外處理和錯誤處理
大體上全部PHP嵌入函數和多的PHP庫不使用例外,用另外的方法(通知等)報告錯誤。囙此,即使有缺陷的程式碼也可以繼續執行。結果會覆蓋很多錯誤。在與PHP競爭的多種其他語言和大多數高階語言中,一旦開發者失誤或開發者無法預測的執行時發生錯誤,程式就會停止運行。這是最安全的對策。
讓我們看看下一個程式碼吧。此程式碼使用資料庫査詢來限制用戶名是否包含在黑名單中。
此程式碼可能在運行時發生各種錯誤。例如,由於密碼錯誤、服務器關閉等原因導致資料庫連接失敗,或者用戶端打開的連接被服務器關閉。在這種情況下,mysqli_函數組發出警告或通知,但不會發生例外或致命錯誤。總之,程式碼就那樣繼續。變數$row成為NULL。PHP$row[0]也評估為NULL,型號指定較弱(int)$row[0]評估為0。最終can_access_feature函數返回true,不管黑名單是否被刊登,都允許所有用戶訪問。
mysqli_
$row
NULL
$row[0]
NULL
(int)$row[0]
can_access_feature
true
mysqli_
$row
NULL
$row[0]
NULL
(int)$row[0]
can_access_feature
true
使用這些本地資料庫API,您必須在每個地方添加錯誤檢查。但是,因為要求多餘的工作所以容易被省略,既定不安全。另外,需要很多規定的程式碼記述。囙此,除非有明確的原因,不能不採用本地驅動程序和精緻的錯誤檢查,建議使用PHP數據對象(PDO)來指定ERRMODE_WARNING標誌或ERRMODE_EXCEPTION標誌。對。
另外,在很多情况下,最好使用error_reporting函數將錯誤報告級別設定得盡可能高。請絕對不要抑制錯誤消息。請務必按照警告記下更堅固的程式碼。
php.ini
PHP程式碼的行動大體上取決於多種配寘值。這包括基本操作的變更,例如錯誤的處理方法。囙此,在所有環境中描述正確的操作程式碼是極難的業。由於關於這些設定的設定和要求根據庫的不同而不同,囙此很難適當地使用協力廠商程式碼。下麵的“設定”中對一部分進行了說明。
無用的嵌入函數
一般認為PHP安全用的嵌入函數多數被準備,不過(addslashes,mysql_escape_string,mysql_real_escape_string等),那個多淨是bug,實際對安全問題的處理不有用。這些函數的一部分正在被廢除和删除,但是從低相容性的策略開始,需要很長的時間。
addslashes
mysql_escape_string
mysql_real_escape_string
addslashes
mysql_escape_string
mysql_real_escape_string
在PHP裏(上)array這個資料結構也被準備,在PHP編碼和內部寬廣地被使用,不過,這個排列和dexyonari一起做了的容易混淆的東西。由於這種混亂的原因,即使是積累了經驗的PHP開發者,也帶入了像Drupal SA-CORE-2014-005(參照補丁)一樣的重大的安全的脆弱性。
框架的問題點
URL路由
嵌入到PHP中的URL路由機制是使用目錄結構內的“.php”結束的檔案。從這裡產生象下麵一樣的脆弱性。
- 對於遠程執行檔名不縮放的所有文件上傳功能的脆弱(即,提供服務的Web服務器執行任意命令)。保存上傳的檔案時請務必正確地顯示內容和檔名。
- 原始程式碼(包括設定檔)將與下載檔案(靜態資產等)一起保存在公共可訪問的目錄中。如果設定錯誤,或者忘記設定,包含機密資訊的原始程式碼和構成檔案可能會被攻擊者下載(換句話說,Web服務器提供應該私人或執行專用的資源)。.htaccess使用限制訪問。這個因為既定不安全不能說是理想的,不過,代替這個的手段沒有其他的。
.htaccess
.htaccess
- URL路由機制與模塊系統相同。這意味著在很多情况下,攻擊者可以將檔案作為與設計意圖不同的入侵點。由此,有可能發生認證機制完全被迂回這樣的脆弱性。總之,有發生由於到另外的檔案取出編碼的單純的反射的脆弱性的可能。這個PHP特別能簡單。因為PHP有全球可訪問的請求數據($_GET等)所以即使請求處理程式碼不在函數定義內,檔案級的程式碼也可以成為基於請求動作的指令程式碼。
- 因為不存在合適的URL路由機制,開發者多會開發獨自的場合的管道。這些管道往往不是安全的,對不同的請求處理功能沒有適當的許可限制。
輸入處理
攻擊者使用以下査詢字串時,
美元supplied_nonce成為排列。此後,strcmp()函數返回(這個對遙遠方便,不過,不是衝破例外)NULL。型指定的弱點和==(同一性)不是運算子=(相當性)因為使用運算子,比較成功(因為PHP中式NULL==0是真的)。囙此,攻擊者不用指定正確的nonce,就可以重置密碼。
$supplied_nonce
strcmp()
NULL
===
==
NULL == 0
$supplied_nonce
strcmp()
NULL
===
==
NULL == 0
與這個完全相同的問題,與PHP array資料結構的容易混淆組合,有由於Drupal SA-CORE-2014-005等的問題被惡用的可能。請參照惡用例子。
範本語言
PHP基本上是範本語言。可是,既定不進行HTML逃脫。為此,成為在Web應用程序的使用非常問題多的語言。請參照下麵的“XSS”區域。
其他缺點
除此之外,還有如既定開啟的CSRF對策機制等,Web框架應提供的重要功能。因為PHP初步性的Web框架附屬著,這個對於Web網站的製作充分實用,多的人CSRF對策沒有必要的知識製作Web網站。
協力廠商PHP程式碼
由於上述問題,PHP中記述的庫和項目往往是危險的。特別,如果恰當的Web框架沒被使用。因為乍一看好象無害的編碼安全的脆弱性也大量地潜藏的可能性,在Web上發現了的PHP編碼請不要信用。
不完全記述的PHP碼警告被發出的事多,容易引起問題。一般的解決辦法是關閉全部的通知,不過,這個與恰當的對應相反(上述參照),程式碼更加惡化。
定期更新
請注意定期更新正在運行的服務器上的PHP的視圖。每天新的脆弱性PHP找到,被發表。攻擊者經常利用任何服務器上的這種新的脆弱性。
有很多與安全相關的設定選項。下麵是其中一部分。
塞特Handler
PHP碼請設定為“SetHandler”使用目錄執行。在許多情况下,錯誤地使用“AddHander”目錄設定。這樣也可以操作,不過,其他的檔案也作為PHP編碼變得可執行。例如,檔名“foo.php.txt”作為PHP碼被處理,不過,如果這個檔不是打算執行的情况和(樣本程式碼等),是來自惡意的文件上傳的東西,成為非常嚴重的遠程執行的脆弱性有。
用戶輸入的結果或副產品的數據都不可靠。必須通過適當的方法驗證數據,或者進行過濾處理。這樣才可以看出數據沒有被污染。
$_SERVER
$_GET
$_POST
$_REQUEST
$_FILES
$_COOKIE
$_SERVER
上傳文件
從用戶接受的檔案,特別是其他用戶能下載那個的話,成為各種各樣的安全威脅的原因。特別,能考慮象下麵一樣的威脅。
- 作為HTML提供的檔案全部XSS攻擊有利用的可能性。
- 作為PHP處理的檔案全部可能被非常重大的攻擊利用(遠程執行的脆弱性)。
因為PHP是能非常簡單地執行PHP編碼(簡單地有適當的副檔名的檔案)的設計,在PHP網站(PHP被安裝設定的全部的網站)中,保存上傳了的檔案的時候必定sanitizu的檔名特別重要。
$_FILES陣列處理中的一般錯誤
在互聯網上經常可以看到進行類似下麵程式碼處理的程式碼寵物。
在這裡,$mimeType是更恰當被確認了的檔案類型。這個方法會使服務器的資源消耗更多,但是可以防止用戶發送危險的檔案,欺騙程式碼使其置信為影像。影像檔案通常被認為是安全的檔案類型。
$_使用REQUEST
美元_REQUEST強烈建議您不要使用。不能推薦這個超級全域變數的理由,不僅僅是POST和GET的數據,根據請求被發送了的Cookie也包含在這個變數中。所有這些數據都匯總到一個佈局,囙此資料來源的定義幾乎是不可能的。這招致混亂,用程式碼變得容易犯錯誤。囙此,可能會導致安全問題。
SQL噴射的脆弱性如果有1個,Web網站的入侵變得可能。囙此,每個駭客都會首先突破SQL注射的脆弱性。囙此,修正SQL噴射的脆弱性是確保基於PHP的應用的安全的第一步。請遵守以下規則。
在SQL中絕對不進行數據的連接和內插
請不要使用連接來創建包含用戶數據的SQL字串。
請不要使用內插。
逃生是不安全的
mysql_real_escape_string不安全。關於SQL噴射的對策,請不要指望這個。
理由:所有變數使用mysql_real_escape_string,將其連接到査詢時,肯定會忘記一次的。那個一次成為致命傷。絕對不要忘記是誰都不可能的。另外,在SQL內也必須確實使用引號,但是在假定數據為數值的情况下,這是不自然的行為。代替,請使用預付語句或者,經常執行適當的SQL逃脫的同等的API(大部分的ORM除了做這個逃避以外,製作SQL)。
使用預付語句
預付語句非常安全。在預付語句中,數據已從SQL命令中分離。將所有用戶輸入的內容視為數據,並保持原始狀態保存在表格中。
請參照PHP檔案的“MySQLi prepared statements”和“PDO prepared statements”。
如果首碼語句無效
如果您需要創建動態査詢或設定不支持作為預付變數的變數,或者如果資料庫引擎不支持預付語句。例如,不支持PDO MySQL中的?作為LIMIT指定子。同時,預付語句在`SELECT`句子錶名和列等也不能使用。在這種情況下,如果在框架中準備了査詢生成器,就使用它。如果您沒有提供査詢創建器,您可以從Composer和Packagist中使用多個包。請不要使用自己的東西。
ORM
ORM(對象關係映射)是恰當的安全慣例。在PHP項目中即使使用ORM(Doctrine等)也可能受到SQL噴射攻擊。在ORM中插入査詢比通常要難得多,但是如果連接了ORM査詢,就會產生與SQL査詢連接時的脆弱性。囙此,發送到資料庫的字串絕對不要連接。ORM也對應於預付語句。
請務必檢查所使用的所有ORM的程式碼,並確認該程式碼所生成的SQL的執行將如何處理。確認不是內部連接值,而是使用了預付語句,或者遵守了適當的安全對策。
編碼問題
除了不得已的情况,使用UTF-8
許多新的攻擊向量是基於編碼的迂回。請使用UTF-8,除非您必須使用不同的編碼,否則資料庫和應用程序的字元集。
除了SQL以外,PHP中也存在幾個可執行且一般的注册。
殼式噴射
下麵列出的少數PHP函數是:
- shell_exec
- exec
- passthru
- system
- 背景音樂(背景音樂)運算子(`)
將字串作為形狀腳本或命令來執行。傳遞給這些函數的輸入(尤其是與函數不同的尾碼(尾碼)運算子)。根據設定,根據sheruskureputo的注射應用程序的設定和構成洩漏,也有服務器全體被奪取的可能性。這是非常危險的噴射,被認為是攻擊者的天堂。
除非有絕對的危險信心(這必須是白名單化),受污染的輸入(即,用戶進行了某些操作的輸入)請絕對不要交給上述函數。逃避和其他對策都沒有效果。為了回避各自的對策的向量多數存在。不成熟的開發者說的話請不要相信。
程式碼注入
以PHP為首,任何解釋語言都準備了接受字串並在語言中執行的函數。PHP中將此函數稱為eval()使用eval是非常壞的慣例。不僅在安全方面。如果eval以外沒有方法的事有絕對的信心,被污染了的輸入完全沒有的狀態使用eval。另外,eval通常執行得慢。
不要將preg_replace()函數與未縮略的用戶輸入一起使用。有效載荷在eval()中被評估。
反射也可能是程式碼噴射的缺陷。這是個高度的話題,請參攷有關迴響的合適檔案。
其他注釋
執行LDAP、XPath和字串的其他協力廠商應用程序對於噴射來說很脆弱。字串有時不是數據而是指令,所以要時刻留意,確保安全,然後傳遞到協力廠商庫。
有關XSS有下麵的2個劇本。各自有必要採取適當的對策。
無標記
大多數情况下,在輸出時,無需將未解脫的HTML標籤包含在用戶輸入數據中。例如,當翻轉文字方塊的值或輸出儲存格中的用戶數據時。
如果範本使用了標準PHP,或者使用了`echo`等,可以通過將'htmlspecialchars'或'htmlspecialchars'或'echars'等函數(實質上是'htmlspecialchars'的更方便的包裝器)應用於數據,來減輕XSS。但是,我不推薦這個。問題在於,必須記住每次都適用,即使一次忘記也會產生XSS的脆弱性。既定而又不安全的方法論,必須作為危險的東西來對待。
作為替代,推薦您使用默認的範本引擎,該範本引擎適用於HTML逃生(見下麵)。HTML請全部通過範本引擎傳遞。
如果不能切換到安全範本引擎,請使用以下函數將不可靠的全部數據:
在危險的要素(style,script,image src,a等)使用用戶輸入的時候,這個劇本不能減輕XSS,請注意。但是,一般不會這樣做。另外,請注意,不打算包含HTML標籤的輸出,需要全部用下麵函數過濾之後發送給瀏覽器。
不可靠的標籤
輸出時使用HTML標籤的輸入允許用戶輸入(富有的部落格評論、論壇投稿、部落格投稿等),當用戶不信任時,必須使用安全的編碼庫。但是,這通常是很困難的,實行也會比較慢。幾乎所有的應用程序XSS的脆弱性就是這個原因。OWASP ESAPI準備了用於對數據的各種部分進行編碼的程式碼組。同時,也有OWASP AntiSammy和PHP用的HTMLPurifier。無論哪一個都需要進行適當的設定和學習,但是要開發好的應用軟體,這些都是必不可少的。
範本發動機
在數據的輸出,以及從幾乎XSS脆弱性的防禦中支援程式師和設計者的範本引擎存在幾個。範本引擎的主要目的不是安全性,而是設計擴展的提高,但主要範本引擎的大部分會自動地逃脫輸出上的變數,如果有不能逃脫的變數的情况會強制開發者明示。囙此,變數的輸出帶有白名單的性質。這樣的引擎存在複數,不過,那個好例子是twig[1]。其他一般範本引擎包括Smarty、Haanga、Rain TPL。
因為手動應用了逃脫,過分容易忘記,XSS恰當的處理,用白名單管道逃脫的範本引擎不可缺少。同時,如果開發者重視安全性,必須採用既定安全的系統。
其他提示
- 請不要在任何Web應用程序上設定可靠的區域。很多開發者把管理者領域作為XSS對策的對象外,不過,入侵者關注管理者Cookie和XSS。如果輸出含有變數,則必須使用上述函數清除所有輸出。將echo、print和printf的所有實例從應用程序中删除,替換為安全範本引擎。
- 上述函數僅適用於HTML語法功能。如果不用引號包住元素的内容,會遭受慘痛的打擊。請注意妥當的HTML。
- 反射型XSS與普通的XSS同樣危險,一般潜藏著在應用程序最難顯眼的地方。請找那個減輕一點。
- 全部PHP安裝mhash擴展功能並不是動作著。如果需要進行散列化,請在使用前確認。如果mhash不工作,則無法執行SHA-256雜湊化。
- 全部PHP安裝mcrypt擴展機能並不是動作著。如果沒有操作則無法執行AES。如果需要AES請確認。
CSRF對策在理論上很簡單,但是要正確實施還是很難的。首先,對CSRF的一些提示。
- 進行什麼值得關注的操作的要求,CSRF對策是必要的。值得注意的操作是系統的變更和長時間的讀取。
- 大部分的情况,CSRF GET發生,不過,POST也容易發生。絕對不要認為POST是安全的。
OWASP PHP CSRFGuard是表示CSRF的對策方法的碼斯尼寵物。只是複製粘貼這個是不够的。在不久的將來,可以複製&粘貼的版本可能得到吧(希望的觀測)。現時,這個和以下的提示組合應對。
PHP沒有附帶馬上就可用的認證模塊。您必須單獨實現或使用PHP框架。遺憾的是,大部分PHP框架都是由開放原始碼的開發商社區開發的,不是安全專家,離完美還差得很遠。接下來,給出幾個有益的提示。
會話管理
認為PHP既定的會話功能是安全的。生成PHPSessionID充分是隨機,不過,保存不一定安全。
- 會話檔案被臨時資料夾(/tmp)保存,如果不安裝suPHP,從全世界能寫入。囙此,有由於LFI和其他的洩漏被操作的可能。
- 在默認設置中,每個會話都被保存在檔案中,但是訪問量大在Web網站上會非常慢。替代地,您可以將會話保存到存儲資料夾中(在UNIX情况下)。
- 不依賴PHP,可以實現獨立的會話機构。在這種情況下,請將會話數據保存到資料庫中。根據需要,可以使用全部或一部分PHP的會話處理功能,也可以不使用1。
應對會話劫持
將會話綁定到IP地址是恰當的慣例。這樣,您可以封锁大部分會話劫持腳本(但不能封锁)。但是,其中說不定有使用匿名化工具(Tor等)的用戶。這樣的使用者服務會造成障礙。
要實現此操作,您可以簡單地在創建會話時將用戶端的IP存儲在會話中,然後強制執行此操作。下一個程式碼寵物返回用戶端的IP地址。
禁用會話ID
違規(例如,IP地址2被觀測等)每當發生時,請禁用會話(Cookie的解除、會話保存的解除、追跡的删除)。日誌活動可能有用。很多的應用程序,登入用戶也通知(GMail等)。
會話ID
每次陞級時請滾動會話ID。例如,如果用戶登錄,會話的重要性就會發生變化,所以需要更改會話ID。
會話ID
會話ID一般認為守秘性高(貴)。請注意不要讓應用程序在任何地方曝光會話ID(尤其是被登入用戶綁定的情况)。請不要使用URL作為會話ID的媒體。
如果會話包含機密資訊,則必須經由TLS轉發會話ID。否則,埋伏攻擊者可執行會話劫持。
固定會話
用戶登錄後(或每項請求後)使用session_regenerate_id()禁用會話ID。
會話過期
在一定空閒時間之後,以及經過一定活動時間後會話必須過期。有效期過期處理意味著禁用並删除會話,如果另一個請求來了,則創建一個新的會話。
此外,關閉[註銷]按鈕,退出時取消所有會話的追跡箭頭。
空閒時間超時
如果當前請求已經從上次請求中超過X秒,則會話將過期。這需要每次請求時更新會話數據的請求時間。一般的設定時間是30分鐘,但很大程度上左右了應用程序的條件。
這個過期對登入到能够訪問公共的機器的用戶忘記註銷時有用。啟用會話劫持。
一般超時
如果當前會話持續一段時間,即使處於活動狀態,會話也會過期。根據這個變得容易掌握狀況。時間各不相同,但通常是1天到1周左右可以。要執行此操作,必須存儲會話的起始時間。
沉默寡言
用PHP腳本處理Cookie,有幾個訣竅。
不序列化
請絕對不要將Cookie中存儲的數據序列化。操作簡單,可能會新增作用範圍中的變數。
適當删除
要安全删除Cookie,請使用以下小寵物。
1確保瀏覽器中的Cookie有效期滿。2行是删除Cookie的標準方法(false不能存儲在Cookie)。3從腳本中删除第行的Cookie。很多導遊建議開發者使用time()-3600來過期,但如果瀏覽器的時間不正確,則有可能無法運行。
另外,使用session_name()可以獲得既定的PHP會話Cookie名稱。
Internet Explorer的問題點
作為傾向Internet Explorer的很多版本有關Cookie的問題。通常,將有效期限設定為0,以消除問題。
認證
自動登錄(Remember Me)功能
很多的網站對自動登錄功能有脆弱性。正確的方法是,對用戶生成1次限定的權杖,並將其保存到Cookie。為了驗證該權杖並分配給用戶,該權杖必須存在於應用的數據商店中。這個權杖必須與用戶名和密碼無關,安全且足够長的隨機數值是適當的。
為了防止對自動登錄的權杖的burotofosu攻擊,推薦這個。另外,請確保權杖的長度足够長。不然的話,攻擊者會對自動登錄用的權杖發起攻擊,不久就會沒有資格資訊登入用戶。
- 用戶名/請絕對不要將密碼和相關資訊保存在Cookie上。
請參照「PHP Configuration Cheat Sheet」。
Achim-Achim at owasp.org
Andrew van der Stock
Luke Plant
OWASP Cheat Sheets Project Homepage
- OWASP Cheat Sheet Series
Developer Cheat Sheets(Builder)
Assesment Cheat Sheets(Breaker)
- Attack Surface Analysis Cheat Sheet
- XSS Filter Evasion Cheat Sheet
- REST Assessment Cheat Sheet
- Web Application Security Testing Cheat Sheet
Mobile Cheat Sheets
- IOS Developer Cheat Sheet
- Mobile Jailbreaking Cheat Sheet
OpSec Cheat Sheets(Defender)
- Virtual Patching Cheat Sheet
Draft Cheat Sheets
- Access Control Cheat Sheet
- Application Security Architecture Cheat Sheet
- Business Logic Security Cheat Sheet
- PHP Security Cheat Sheet
- Secure Coding Cheat Sheet
- Secure SDLC Cheat Sheet
- Threat Modeling Cheat Sheet
- Grails Secure Code Review Cheat Sheet
- IOS應用程序安全測試備忘單
- 金鑰管理備忘單
- 不安全的直接對象引用預防備忘單
- 內容安全性原則備忘單