如果把用戶輸入到一個網頁,將其插入到MySQL數據庫,有機會離開了發生安全問題被稱為SQL注入敞開。這一課將教如何幫助防止這種情況的發生,並幫助保護腳本和MySQL語句。
注入通常發生在處理一個用戶輸入,如他們的名字,而不是一個名字,他們給一個會在不知不覺中你的數據庫上運行的MySQL語句。
永遠不要信任用戶提供的數據,只能驗證後處理這些數據,作為一項規則,這是通過模式匹配。在下面的例子中,用戶名被限制為字母數字字符加下劃線的長度在8到20個字符之間 - 根據需要修改這些規則。
代碼如下 復制代碼 if (preg_match("/^w{8,20}$/", $_GET['username'], $matches))為了說明這個問題,認為這是摘要:
代碼如下 復制代碼// supposed input
$name = "Qadir'; DELETE FROM users;";
mysql_query("SELECT * FROM users WHERE name='{$name}'");
函數調用應該是從用戶表中的名稱列的名稱相匹配用戶指定的檢索記錄。在正常情況下,名稱只包含字母數字字符或空間,如字符串髂骨。但在這裡,給$name通過附加一個全新的查詢,調用數據庫變成災難:注入DELETE查詢刪除用戶的所有記錄。
幸運的是,如果使用MySQL,在mysql_query()函數不會允許查詢堆疊,或在一個單一的函數調用執行多個查詢。如果嘗試到堆放查詢則調用失敗。
其他PHP數據庫擴展,如SQLite和PostgreSQL則愉快地進行堆查詢,執行在一個字符串中的所有的查詢,並創建一個嚴重的安全問題。
防止SQL注入:
可以處理所有的轉義字符巧妙的腳本語言,比如Perl和PHP。 PHP的MySQL擴展提供的函數mysql_real_escape_string()輸入到MySQL的特殊字符進行轉義。
if (get_magic_quotes_gpc())
{
$name = stripslashes($name);
}
$name = mysql_real_escape_string($name);
mysql_query("SELECT * FROM users WHERE name='{$name}'");
LIKE困境:
為了解決的LIKE問題,一個自定義的轉義機制必須用戶提供的%和_字符轉換成文字。使用addcslashes()函數,讓可以指定一個字符范圍轉義。
代碼如下 復制代碼$sub = addcslashes(mysql_real_escape_string("%something_"), "%_");
// $sub == %something_
mysql_query("SELECT * FROM messages WHERE subject LIKE '{$sub}%'");
上面只是很簡單的,下面看一些常用的注入
一、SQL注入漏洞的判斷
一般來說,SQL注入一般存在於形如:HTTP://xxx.xxx.xxx/abc.asp?id=XX等帶有參數的ASP動態網頁中,有時一個動態網頁中可能只有一個參數,有時可能有N個參數,有時是整型參數,有時是字符串型參數,不能一概而論。總之只要是帶有參數的動態網頁且此網頁訪問了數據庫,那麼就有可能存在SQL注入。如果ASP程序員沒有安全意識,不進行必要的字符過濾,存在SQL注入的可能性就非常大。
為了全面了解動態網頁回答的信息,首選請調整IE的配置。把IE菜單-工具-Internet選項-高級-顯示友好HTTP錯誤信息前面的勾去掉。
為了把問題說明清楚,以下以HTTP://xxx.xxx.xxx/abc.asp?p=YY為例進行分析,YY可能是整型,也有可能是字符串。
1、整型參數的判斷
當輸入的參數YY為整型時,通常abc.asp中SQL語句原貌大致如下:
select * from 表名 where 字段=YY,所以可以用以下步驟測試SQL注入是否存在。
①HTTP://xxx.xxx.xxx/abc.asp?p=YY’(附加一個單引號),此時abc.ASP中的SQL語句變成了
select * from 表名 where 字段=YY’,abc.asp運行異常;
②HTTP://xxx.xxx.xxx/abc.asp?p=YY and 1=1, abc.asp運行正常,而且與HTTP://xxx.xxx.xxx/abc.asp?p=YY運行結果相同;
③HTTP://xxx.xxx.xxx/abc.asp?p=YY and 1=2, abc.asp運行異常;
如果以上三步全面滿足,abc.asp中一定存在SQL注入漏洞。
2、字符串型參數的判斷
當輸入的參數YY為字符串時,通常abc.asp中SQL語句原貌大致如下:
select * from 表名 where 字段='YY',所以可以用以下步驟測試SQL注入是否存在。
①HTTP://xxx.xxx.xxx/abc.asp?p=YY’(附加一個單引號),此時abc.ASP中的SQL語句變成了
select * from 表名 where 字段=YY’,abc.asp運行異常;
②HTTP://xxx.xxx.xxx/abc.asp?p=YY&nb ... 39;1'='1', abc.asp運行正常,而且與HTTP://xxx.xxx.xxx/abc.asp?p=YY運行結果相同;
③HTTP://xxx.xxx.xxx/abc.asp?p=YY&nb ... 39;1'='2', abc.asp運行異常;
如果以上三步全面滿足,abc.asp中一定存在SQL注入漏洞。
3、特殊情況的處理
有時ASP程序員會在程序員過濾掉單引號等字符,以防止SQL注入。此時可以用以下幾種方法試一試。
①大小定混合法:由於VBS並不區分大小寫,而程序員在過濾時通常要麼全部過濾大寫字符串,要麼全部過濾小寫字符串,而大小寫混合往往會被忽視。如用SelecT代替select,SELECT等;
②UNICODE法:在IIS中,以UNICODE字符集實現國際化,我們完全可以IE中輸入的字符串化成UNICODE字符串進行輸入。如+ =%2B,空格=%20 等;URLEncode信息參見附件一;
③ASCII碼法:可以把輸入的部分或全部字符全部用ASCII碼代替,如U=chr(85),a=chr(97)等,ASCII信息參見附件二;
二、分析數據庫服務器類型
一般來說,ACCESS與SQL-SERVER是最常用的數據庫服務器,盡管它們都支持T-SQL標准,但還有不同之處,而且不同的數據庫有不同的攻擊方法,必須要區別對待。
1、 利用數據庫服務器的系統變量進行區分
SQL-SERVER有user,db_name()等系統變量,利用這些系統值不僅可以判斷SQL-SERVER,而且還可以得到大量有用信息。如:
① HTTP://xxx.xxx.xxx/abc.asp?p=YY and user>0 不僅可以判斷是否是SQL-SERVER,而還可以得到當前連接到數據庫的用戶名
②HTTP://xxx.xxx.xxx/abc.asp?p=YY&n ... db_name()>0 不僅可以判斷是否是SQL-SERVER,而還可以得到當前正在使用的數據庫名;
2、利用系統表
ACCESS的系統表是msysobjects,且在WEB環境下沒有訪問權限,而SQL-SERVER的系統表是sysobjects,在WEB環境下有訪問權限。對於以下兩條語句:
①HTTP://xxx.xxx.xxx/abc.asp?p=YY and (select count(*) from sysobjects)>0
②HTTP://xxx.xxx.xxx/abc.asp?p=YY and (select count(*) from msysobjects)>0
若數據庫是SQL-SERVE,則第一條,abc.asp一定運行正常,第二條則異常;若是ACCESS則兩條都會異常。