程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> php sql注入與防注入經典案例分析

php sql注入與防注入經典案例分析

編輯:關於PHP編程

對於sql注入與防注入其實就是一個攻與防的,今天我們要告訴大家最基本的注入和防止方法,原理都是利用了php或mysql的一些特性而我們沒注意所造成的。

一個簡單的SQL注入攻擊案例
假如我們有一個公司網站,在網站的後台數據庫中保存了所有的客戶數據等重要信息。假如網站登錄頁面的代碼中有這樣一條命令來讀取用戶信息。

 代碼如下 復制代碼

<?

$q = "SELECT `id` FROM `users` WHERE `username`= ' " .$_GET['username']. " ' AND `password`= ' " .$_GET['password']. " ' ";

?>

現在有一個黑客想攻擊你的數據庫,他會嘗試在此登錄頁面的用戶名的輸入框中輸入以下代碼:

 代碼如下 復制代碼

' ; SHOW TABLES;

點擊登陸鍵,這個頁面就會顯示出數據庫中的所有表。如果他現在使用下面這行命令:

 代碼如下 復制代碼

'; DROP TABLE [table name];

這樣他就把一張表刪除了!

當然,這只是一個很簡單的例子,實際的SQL注入方法比這個要復雜得多,黑客也願意花大量的時間來不斷嘗試來攻擊你的代碼。有一些程序軟件也可以自動地來不斷嘗試SQL注入攻擊。了解了SQL注入的攻擊原理後,我們來看一下如何防范SQL注入攻擊。

magic_quotes_gpc = On 時的注入攻擊
  當 magic_quotes_gpc = On 時,攻擊者無法對字符型的字段進行 SQL 注入。這並不代表這就安全了。這時,可以通過數值型的字段進行SQL注入。

  在最新版的 MYSQL 5.x 中,已經嚴格了數據類型的輸入,已默認關閉自動類型轉換。數值型的字段,不能是引號標記的字符型。也就是說,假設 uid 是數值型的,在以前的 mysql 版本中,這樣的語句是合法的:

 代碼如下 復制代碼

INSERT INTO tbl_user SET uid="1";
SELECT * FROM tbl_user WHERE uid="1";

  在最新的 MYSQL 5.x 中,上面的語句不是合法的,必須寫成這樣:

 代碼如下 復制代碼

INSERT INTO tbl_user SET uid=1;
SELECT * FROM tbl_user WHERE uid=1;

  這樣我認為是正確的。因為作為開發者,向數據庫提交正確的符合規則的數據類型,這是最基本的要求。

  那麼攻擊者在 magic_quotes_gpc = On 時,他們怎麼攻擊呢?很簡單,就是對數值型的字段進行 SQL 注入。以下列的 php 腳本為例:

 代碼如下 復制代碼

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

}
?>
<html><head><title>sample test</title></head>
<body>
<form method=post action="">
  User ID: <input type="text" name="f_uid" size=30><br>

  Password: <input type=text name="f_pwd" size=30><br>
  <input type="submit" name="f_login" value="登錄">
</form>
</body>


  上面這段腳本要求用戶輸入 userid 和 password 登入。一個正常的語句,用戶輸入 1001和abc123,提交的 sql 語句如下:

 代碼如下 復制代碼 SELECT * FROM tbl_users WHERE userid=1001 AND password = 'abc123' LIMIT 0,1

  如果攻擊者在 userid 處,輸入:1001 OR 1 =1 #,則注入的sql語句如下:

 代碼如下 復制代碼 SELECT * FROM tbl_users WHERE userid=1001 OR 1 =1 # AND password = 'abc123' LIMIT 0,1

  攻擊者達到了目的。

 

防范SQL注入 - 使用mysql_real_escape_string()函數

在數據庫操作的代碼中用這個函數mysql_real_escape_string()可以將代碼中特殊字符過濾掉,如引號等。如下例:

 代碼如下 復制代碼

<?

$q = "SELECT `id` FROM `users` WHERE `username`= ' " .mysql_real_escape_string( $_GET['username'] ). " ' AND `password`= ' " .mysql_real_escape_string( $_GET['password'] ). " ' ";

?>

防范SQL注入 - 使用mysql_query()函數

mysql_query()的特別是它將只執行SQL代碼的第一條,而後面的並不會執行。回想在最前面的例子中,黑客通過代碼來例後台執行了多條SQL命令,顯示出了所有表的名稱。所以mysql_query()函數可以取到進一步保護的作用。我們進一步演化剛才的代碼就得到了下面的代碼:

 代碼如下 復制代碼

<?

//connection
$database = mysql_connect("localhost", "username","password");

//db selection
mysql_select_db("database", $database);

$q = mysql_query("SELECT `id` FROM `users` WHERE `username`= ' " .mysql_real_escape_string( $_GET['username'] ). " ' AND `password`= ' " .mysql_real_escape_string( $_GET['password'] ). " ' ", $database); 

?>

除此之外,我們還可以在PHP代碼中判斷輸入值的長度,或者專門用一個函數來檢查輸入的值。所以在接受用戶輸入值的地方一定要做好輸入內容的過濾和檢查。當然學習和了解最新的SQL注入方式也非常重要,這樣才能做到有目的的防范。如果使用的是平台式的網站系統如Wordpress,要注意及時打上官方的補丁或升級到新的版本。如果有講得不對的地方或不理解的請在評論區留言。

php.ini 中的 display_errors 選項,應該設為 display_errors = off。這樣 php 腳本出錯之後,不會在 web 頁面輸出錯誤,以免讓攻擊者分析出有作的信息。
調用 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 rn錯誤信息".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 rn錯誤信息".mysql_query();
  exit;
}


關於 sql防注入內容 http://www.bKjia.c0m/phper/phpanqn/37704.htm

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved