深入SQL注入
發表時間:2023-05-31 來源:明輝站整理相關軟件相關文章人氣:
[摘要]前面已經把SQL注入攻擊的簡單方法履了一遍 今天我們繼續就一些問題來好好研究一下前面我們說可以通過一些返回信息來判斷SQL注入, 但首先不一定每臺服務器的IIS都返回具體錯誤提示給客戶端, 如果...
前面已經把SQL注入攻擊的簡單方法履了一遍
今天我們繼續就一些問題來好好研究一下
前面我們說可以通過一些返回信息來判斷SQL注入, 但首先不一定每臺服務器的IIS都返回具體錯誤提示給客戶端, 如果程序中加了cint(參數)之類語句的話, SQL注入是不會成功的, 但服務器同樣會報錯, 具體提示信息為處理 URL 時服務器上出錯。 請和系統管理員聯絡。
其次, 部分對SQL注入有一點了解的程序員, 認為只要把單引號過濾掉就安全了, 這種情況不為少數, 如果你用單引號測試, 是測不到注入點的
那么, 什么樣的測試方法才是比較準確呢?答案如下:
① http://host/showdetail.asp?id=49
② http://host/showdetail.asp?id=49 ;;and 1=1
③ http://host/showdetail.asp?id=49 ;;and 1=2
這就是經典的1=1、1=2測試法了, 怎么判斷呢?看看上面三個網址返回的結果就知道了:
可以注入的表現:
① 正常顯示(這是必然的, 不然就是程序有錯誤了)
② 正常顯示, 內容基本與①相同
③ 提示BOF或EOF(程序沒做任何判斷時)、或提示找不到記錄(判斷了rs.eof時)、或顯示內容為空(程序加了on error resume next)
不可以注入就比較容易判斷了, ①同樣正常顯示, ②和③一般都會有程序定義的錯誤提示, 或提示類型轉換時出錯。
當然, 這只是傳入參數是數字型的時候用的判斷方法, 實際應用的時候會有字符型和搜索型參數, 下面我們在來坐分析。
不過我們先來說一個問題:
不同的數據庫的函數、注入方法都是有差異的, 所以在注入之前, 我們還要判斷一下數據庫的類型。 一般ASP最常搭配的數據庫是Access和SQLServer, 網上超過99%的網站都是其中之一。
怎么讓程序告訴你它使用的什么數據庫呢?來看看:
SQLServer有一些系統變量, 如果服務器IIS提示沒關閉, 并且SQLServer返回錯誤提示的話, 那可以直接從出錯信息獲取, 方法如下:
http://host/showdetail.asp?id=49 ;;and user>0
這句語句很簡單, 但卻包含了SQLServer特有注入方法的精髓, 我自己也是在一次無意的測試中發現這種效率極高的猜解方法。 讓我看來看看它的含義:首先, 前面的語句是正常的, 重點在and user>0, 我們知道, 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://host/showdetail.asp?id=49 ;;and (select count(*) from sysobjects)>0
http://host/showdetail.asp?id=49 ;;and (select count(*) from msysobjects)>0
如果數據庫是SQLServer, 那么第一個網址的頁面與原頁面http://host/showdetail.asp?id=49是大致相同的;而第二個網址, 由于找不到表msysobjects, 會提示出錯, 就算程序有容錯處理, 頁面也與原頁面完全不同。
如果數據庫用的是Access, 那么情況就有所不同, 第一個網址的頁面與原頁面完全不同;第二個網址, 則視乎數據庫設置是否允許讀該系統表, 一般來說是不允許的, 所以與原網址也是完全不同。 大多數情況下, 用第一個網址就可以得知系統所用的數據庫類型, 第二個網址只作為開啟IIS錯誤提示時的驗證。
們學會了SQL注入的判斷方法, 但真正要拿到網站的保密內容, 是遠遠不夠的。 接下來, 我們就繼續學習如何從數據庫中獲取想要獲得的內容, 首先, 我們先看看SQL注入的一般步驟:
第一節、SQL注入的一般步驟
首先, 判斷環境, 尋找注入點, 判斷數據庫類型, 這在入門篇已經講過了。
其次, 根據注入參數類型, 在腦海中重構SQL語句的原貌, 按參數類型主要分為下面三種:
(A) ID=49 這類注入的參數是數字型, SQL語句原貌大致如下:
Select * from 表名 where 字段=49
注入的參數為ID=49 And [查詢條件], 即是生成語句:
Select * from 表名 where 字段=49 And [查詢條件]
(B) Class=連續劇 這類注入的參數是字符型, SQL語句原貌大致概如下:
Select * from 表名 where 字段=’連續劇’
注入的參數為Class=連續劇’ and [查詢條件] and ‘’=’ , 即是生成語句:
Select * from 表名 where 字段=’連續劇’ and [查詢條件] and ‘’=’’
(C) 搜索時沒過濾參數的, 如keyword=關鍵字, SQL語句原貌大致如下:
Select * from 表名 where 字段like ’%關鍵字%’
注入的參數為keyword=’ and [查詢條件] and ‘%25’=’, 即是生成語句:
Select * from 表名 where字段like ’%’ and [查詢條件] and ‘%’=’%’
接著, 將查詢條件替換成SQL語句, 猜解表名, 例如:
ID=49 And (Select Count(*) from Admin)>=0
如果頁面就與ID=49的相同, 說明附加條件成立, 即表Admin存在, 反之, 即不存在(請牢記這種方法)。 如此循環, 直至猜到表名為止。
表名猜出來后, 將Count(*)替換成Count(字段名), 用同樣的原理猜解字段名。
有人會說:這里有一些偶然的成分, 如果表名起得很復雜沒規律的, 那根本就沒得玩下去了。 說得很對, 這世界根本就不存在100%成功的黑客技術, 蒼蠅不叮無縫的蛋, 無論多技術多高深的黑客, 都是因為別人的程序寫得不嚴密或使用者保密意識不夠, 才有得下手。
有點跑題了, 話說回來, 對于SQLServer的庫, 還是有辦法讓程序告訴我們表名及字段名的, 我們在高級篇中會做介紹。
最后, 在表名和列名猜解成功后, 再使用SQL語句, 得出字段的值, 下面介紹一種最常用的方法-Ascii逐字解碼法, 雖然這種方法速度很慢, 但肯定是可行的方法。
我們舉個例子, 已知表Admin中存在username字段, 首先, 我們取第一條記錄, 測試長度:
http://www.19cn.com/showdetail.asp?id=49 ;;and (select top 1 len(username) from Admin)>0
先說明原理:如果top 1的username長度大于0, 則條件成立;接著就是>1、>2、>3這樣測試下去, 一直到條件不成立為止, 比如>7成立, >8不成立, 就是len(username)=8
當然沒人會笨得從0,1,2,3一個個測試, 怎么樣才比較快就看各自發揮了。 在得到username的長度后, 用mid(username,N,1)截取第N位字符, 再asc(mid(username,N,1))得到ASCII碼, 比如:
id=49 and (select top 1 asc(mid(username,1,1)) from Admin)>0
同樣也是用逐步縮小范圍的方法得到第1位字符的ASCII碼, 注意的是英文和數字的ASCII碼在1-128之間, 可以用折半法加速猜解, 如果寫成程序測試, 效率會有極大的提高。
第二節、SQL注入常用函數
有SQL語言基礎的人, 在SQL注入的時候成功率比不熟悉的人高很多。 我們有必要提高一下自己的SQL水平, 特別是一些常用的函數及命令。
Access:asc(字符) SQLServer:unicode(字符)
作用:返回某字符的ASCII碼
Access:chr(數字) SQLServer:nchar(數字)
作用:與asc相反, 根據ASCII碼返回字符
Access:mid(字符串,N,L) SQLServer:substring(字符串,N,L)
作用:返回字符串從N個字符起長度為L的子字符串, 即N到N+L之間的字符串
Access:abc(數字) SQLServer:abc (數字)
作用:返回數字的絕對值(在猜解漢字的時候會用到)
Access:A between B And C SQLServer:A between B And C
作用:判斷A是否界于B與C之間
第三節、中文處理方法
在注入中碰到中文字符是常有的事, 有些人一碰到中文字符就想打退堂鼓了。 其實只要對中文的編碼有所了解, “中文恐懼癥”很快可以克服。
先說一點常識:
Access中, 中文的ASCII碼可能會出現負數, 取出該負數后用abs()取絕對值, 漢字字符不變。
SQLServer中, 中文的ASCII為正數, 但由于是UNICODE的雙位編碼, 不能用函數ascii()取得ASCII碼, 必須用函數unicode ()返回unicode值, 再用nchar函數取得對應的中文字符。
了解了上面的兩點后, 是不是覺得中文猜解其實也跟英文差不多呢?除了使用的函數要注意、猜解范圍大一點外, 方法是沒什么兩樣的。
好了, 今天寫了這么多有點累了
大家自己看看吧 我想應該可以把你這幾天學的關于SQL注入的種種東西作個總結吧。 頭腦中應該有個清晰的認識了吧
明天我們將說如果碰到表名列名猜不到, 或程序作者過濾了一些特殊字符, 怎么提高注入的成功率?怎么樣提高猜解效率?
明天見
忘了
想再強調一點 『特征字符的用法』
我們在注入的時候,通常是在網址后面加 and 1=1和 and 1=2去測試網址是否能注入
如果可以注入,一般有下面兩種情況:
A. and 1=1正常, and 1=2報HTTP錯誤,這種情況,NBSI可以自動做出判斷,無需輸入特征字符
B. and 1=1正常, and 1=2提示"找不到此記錄"之類的提示,但不報HTTP錯誤,這時,就需要我們輸入一個"特征字符",來幫助程序識別所傳入的SQL語句執行結果是True還是False
簡單的說,"特征字符"就是 and 1=1頁面中包含有而 and 1=2頁面中不包含有的字符串.
上面是電腦上網安全的一些基礎常識,學習了安全知識,幾乎可以讓你免費電腦中毒的煩擾。