php防sql注入辦法

如何防止 php sql 注入***?我認爲最重要的一點,就是要對數據類型進行檢查和轉義。總結的幾點規則如下:
  1. php.ini 中的 display_errors 選項,應該設爲 display_errors = off。這樣 php 腳本出錯之後,不會在 web 頁面輸出錯誤,以免讓***者分析出有作的信息。
  2. 調用 mysql_query 等 mysql 函數時,前面應該加上 @,即 @mysql_query(...),這樣 mysql 錯誤不會被輸出。同理以免讓***者分析出有用的信息。另外,有些程序員在做開發時,當 mysql_query出錯時,習慣輸出錯誤以及 sql 語句,例如:
    $t_strSQL = "SELECT a from b....";
    if ( mysql_query($t_strSQL) )
    {
      // 正確的處理
    }
    else
    {
      echo "錯誤! SQL 語句:$t_strSQL \r\n錯誤信息".mysql_query();
      exit;
    }
    

      這種做法是相當危險和愚蠢的。如果一定要這麼做,最好在網站的配置文件中,設一個全局變量或定義一個宏,設一下 debug 標誌:

    全局配置文件中:
    define("DEBUG_MODE",0);	// 1: DEBUG MODE; 0: RELEASE MODE
    
    //調用腳本中:
    $t_strSQL = "SELECT a from b....";
    if ( mysql_query($t_strSQL) )
    {
      // 正確的處理
    }
    else 
    {
      if (DEBUG_MODE)
        echo "錯誤! SQL 語句:$t_strSQL \r\n錯誤信息".mysql_query();
      exit;
    }
    
  3. 對提交的 sql 語句,進行轉義和類型檢查

 四. 我寫的一個安全參數獲取函數

  爲了防止用戶的錯誤數據和 php + mysql 注入 ,我寫了一個函數 PAPI_GetSafeParam(),用來獲取安全的參數值:

define("XH_PARAM_INT",0);
define("XH_PARAM_TXT",1);
function PAPI_GetSafeParam($pi_strName, $pi_Def = "", $pi_iType = XH_PARAM_TXT)
{
  if ( isset($_GET[$pi_strName]) ) 
    $t_Val = trim($_GET[$pi_strName]);
  else if ( isset($_POST[$pi_strName]))
    $t_Val = trim($_POST[$pi_strName]);
  else 
    return $pi_Def;

  // INT
  if ( XH_PARAM_INT == $pi_iType)
  {
    if (is_numeric($t_Val))
      return $t_Val;
    else
      return $pi_Def;
  }
  
  // String
  $t_Val = str_replace("&", "&",$t_Val); 
  $t_Val = str_replace("<", "&lt;",$t_Val);
  $t_Val = str_replace(">", "&gt;",$t_Val);
  if ( get_magic_quotes_gpc() )
  {
    $t_Val = str_replace("\\\"", "&quot;",$t_Val);
    $t_Val = str_replace("\\''", "&#039;",$t_Val);
  }
  else
  {
    $t_Val = str_replace("\"", "&quot;",$t_Val);
    $t_Val = str_replace("'", "&#039;",$t_Val);
  }
  return $t_Val;
}

  在這個函數中,有三個參數:

$pi_strName: 變量名
$pi_Def: 默認值
$pi_iType: 數據類型。取值爲 XH_PARAM_INT, XH_PARAM_TXT, 分別表示數值型和文本型。

  如果請求是數值型,那麼調用 is_numeric() 判斷是否爲數值。如果不是,則返回程序指定的默認值。

  簡單起見,對於文本串,我將用戶輸入的所有危險字符(包括HTML代碼),全部轉義。由於 php 函數 addslashes()存在漏洞,我用 str_replace()直接替換。get_magic_quotes_gpc() 函數是 php 的函數,用來判斷 magic_quotes_gpc 選項是否打開。

 

  剛纔第二節的示例,代碼可以這樣調用:

<?
if ( isset($_POST["f_login"] ) )
{
  // 連接數據庫...
  // ...代碼略...
 
  // 檢查用戶是否存在
  $t_strUid = PAPI_GetSafeParam("f_uid", 0, XH_PARAM_INT);
  $t_strPwd = PAPI_GetSafeParam("f_pwd", "", XH_PARAM_TXT);
  $t_strSQL = "SELECT * FROM tbl_users WHERE uid=$t_strUid AND password = '$t_strPwd' LIMIT 0,1";
  if ( $t_hRes = mysql_query($t_strSQL) )
  {
    // 成功查詢之後的處理. 略...
  } 
}
?>

  這樣的話,就已經相當安全了。PAPI_GetSafeParam的代碼有點長,但犧牲這點效率,對保證安全,是值得的。希望大家多批評指正。:)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章