天天看點

淺談sql注入<一>

     關于sql注入,作為一個測試人員是必須要關注的,目前關于web的安全性測試中sql注入已經成為了主流的漏洞之一,我們不容忽視。作為開發人員那就更應該了解了,如果沒能正确的認識sql注入,就很難做到防患于未然,因為我們大多數程式中之是以出現sql注入是由于程式缺乏很嚴謹的邏輯設計,還有一方面就是開發人員經驗不足所展現出來的。

通常sql注入是從正常的www端口通路的,從表面來看,跟一般的web通路沒有差別,是以目前市場上的防火牆并沒有對sql注入給出相關的警報,一般如果管理者沒有檢視日志的習慣,可能系統被入侵很長時間了都不會被發覺。先來看我做的一個簡單的登入系統,看看如何破解進去的,具體如下圖:

淺談sql注入<一>

這是一個簡單的登入系統,包括使用者名和密碼,正确的使用者名和密碼都為sa,通過簡單的sql語句的構造如下圖;

淺談sql注入<一>

登入成功頁面就是傳回并顯示登入的使用者名和密碼,成功頁面上顯示的使用者是sa,而密碼是' or 1 = '1,為什麼會出現這種情況呢,并不是背景資料庫中存在這樣的密碼,我們來看看這個登入背景是如何驗證使用者資訊的,背景的實作方式是通過這樣一個sql語句來實作的,select * from user where username = '' and password = '',當使用者名和密碼與背景資料庫進行比對的時候,就表示登入驗證通過,就可以進入系統并獲得操作權限,然後再來看這個語句:select * from user where username = '' and password = '' or 1 = '1',我們可以驚訝的發現當後面跟上一個或語句時,整個判斷條件就發生了質的變化,‘或’判斷就是隻要有一個條件成立就表示整個判斷為為true,是以這個簡單的sql語句構造就可以繞過登入使用者名和密碼的驗證,直接進入系統,這就是sql注入。

     sql注入的構造手法相當靈活,在注入時會碰到很多意想不到的情況,能不能根據具體的情況來分析,構造更加巧妙的sql語句,擷取更多的資料資訊,這就是高手與菜鳥的差別。這裡我将總結一些常見的sql注入,并進行分類,避免在測試sql注入時太盲目,進行合理的分析後開始進行測試,将會大大提高工作效率。

首先,在測試sql注入之前,我們需要設定IE浏覽器,第一步先把IE菜單=>工具=>Internet選項=>進階=>顯示友好 HTTP 錯誤資訊前面的勾去掉。否則,不論伺服器傳回什麼錯誤,IE都隻顯示為HTTP 500伺服器錯誤,不能獲得更多的提示資訊。我們通常在測試過程中,會碰到測試一些頁面出現異常的時候,提示一些具體的程式代碼,或者是資料庫不比對什麼的,這些都是最直覺的錯誤資訊,一般是程式開發人員進行相關調試時留下,也有些是本身沒有發現的,在測試階段發現是最好不過,如果等到上線被使用者發現,那就是攻擊的最好入口。通常我們在位址欄上會見到這樣的URL位址,如:http://bbs.xxx.cn/viewthread.php?tid=274932,如果我們在後面加上’,頁面會出現如下提示資訊

Microsoft JET Database Engine 錯誤 '80040e14'

字元串的文法錯誤 在查詢表達式 'tid=274932'' 中。等等資訊,通過以上提示我們可以得出如下資訊:

1.網站使用的是Access資料庫,通過JET引擎連接配接資料庫,而不是通過ODBC。

2.程式沒有判斷用戶端送出的資料是否符合程式要求。

3.該SQL語句所查詢的表中有一名為tid的字段。

從上面的例子我們可以看出,sql注入的原理就是通過用戶端送出一些特殊的代碼,進而擷取伺服器端的資訊,進而分析得到我們想要資訊。

 其次,就是分析頁面能否進行sql注入,通常情況下不是每個伺服器都會給出錯誤提示資訊,一旦缺乏背景提供的錯誤資訊,我們将如何來進行sql注入呢;而且目前程式員對sql注入有一點的了解,就會做出相應的控制和判斷,一般都會過濾單引号之類的,如果這樣的話,那前面的方法就不得行了。還是前面的位址http://bbs.xxx.cn/viewthread.php?tid=274932,如果在後面加上and 1=1或者1=2來看看頁面給我什麼提示,通過驗證一般會出現以下幾種情況:

1.1=1時與之前頁面顯示一樣,也就是正常顯示

2.1=2時顯示資訊記錄存在等,或者是找不到記錄等等

以上也是表示可以注入的,關于如何建構這類sql語句,将在下節中講到。

第三,就是判斷資料庫類型以及注入方法

不同的資料庫的函數、注入方法都是有差異的,是以在注入之前,我們還要判斷一下資料庫的類型。一般ASP最常搭配的資料庫是Access和SQLServer,網上超過99%的網站都是其中之一。

   怎麼讓程式告訴你它使用的什麼資料庫呢?來看看:

   SQLServer有一些系統變量,如果伺服器IIS提示沒關閉,并且SQLServer傳回錯誤提示的話,那可以直接從出錯資訊擷取,方法如下:

   http://bbs.xxx.cn/viewthread.php?tid=274932 and user>0 這裡我們重點關注user>0,通常使用sqlserver比較多的人應該知道,user是sqlserver的内置變量,它的值是目前連接配接的使用者名,類型為nvarchar。拿一個nvarchar的值跟int的數0比較,系統會先試圖将nvarchar的值轉成int型,當然,轉的過程中肯定會出錯,SQLServer的出錯提示是:将nvarchar值 ”abc” 轉換資料類型為 int 的列時發生文法錯誤,呵呵,abc正是變量user的值,這樣,不廢吹灰之力就拿到了資料庫的使用者名。   還有就是衆所周知的,SQLServer的使用者sa是個等同Adminstrators權限的角色,拿到了sa權限,幾乎肯定可以拿到主機的Administrator了。上面的方法可以很友善的測試出是否是用sa登入,要注意的是:如果是sa登入,提示是将”dbo”轉換成int的列發生錯誤,而不是”sa”。

   如果伺服器IIS不允許傳回錯誤提示,那怎麼判斷資料庫類型呢?我們可以從Access和SQLServer和差別入手,Access和SQLServer都有自己的系統表,比如存放資料庫中所有對象的表,Access是在系統表[msysobjects]中,但在Web環境下讀該表會提示“沒有權限”,SQLServer是在表[sysobjects]中,在Web環境下可正常讀取。

在确認可以注入的情況下,使用下面的語句:

http://bbs.xxx.cn/viewthread.php?tid=274932 and (select count(*) from sysobjects)>0

http://bbs.xxx.cn/viewthread.php?tid=274932 and (select count(*) from msysobjects)>0

如果資料庫是SQLServer,那麼第一個網址的頁面與原頁面http://bbs.xxx.cn/viewthread.php?tid=274932是大緻相同的;而第二個網址,由于找不到表msysobjects,會提示出錯,就算程式有容錯處理,頁面也與原頁面完全不同。

   如果資料庫用的是Access,那麼情況就有所不同,第一個網址的頁面與原頁面完全不同;第二個網址,則視乎資料庫設定是否允許讀該系統表,一般來說是不允許的,是以與原網址也是完全不同。大多數情況下,用第一個網址就可以得知系統所用的資料庫類型,第二個網址隻作為開啟IIS錯誤提示時的驗證。