深入SQL注入

2021-12-29 21:24:24 字數 4734 閱讀 9680

前面已經把sql注入攻擊的簡單方法履了一遍

今天我們繼續就一些問題來好好研究一下

前面我們說可以通過一些返回資訊來判斷sql注入,但首先不一定每台伺服器的iis都返回具體錯誤提示給客戶端,如果程式中加了cint(引數)之類語句的話,sql注入是不會成功的,但伺服器同樣會報錯,具體提示資訊為處理 url 時伺服器上出錯。請和系統管理員聯絡。

其次,部分對sql注入有一點了解的程式設計師,認為只要把單引號過濾掉就安全了,這種情況不為少數,如果你用單引號測試,是測不到注入點的

那麼,什麼樣的測試方法才是比較準確呢?答案如下:

這就是經典的1=1、1=2測試法了,怎麼判斷呢?看看上面三個**返回的結果就知道了:

可以注入的表現:

① 正常顯示(這是必然的,不然就是程式有錯誤了)

② 正常顯示,內容基本與①相同

③ 提示bof或eof(程式沒做任何判斷時)、或提示找不到記錄(判斷了rs.eof時)、或顯示內容為空(程式加了on error resume next)

不可以注入就比較容易判斷了,①同樣正常顯示,②和③一般都會有程式定義的錯誤提示,或提示型別轉換時出錯。

當然,這只是傳入引數是數字型的時候用的判斷方法,實際應用的時候會有字元型和搜尋型引數,下面我們在來坐分析。

不過我們先來說乙個問題:

不同的資料庫的函式、注入方法都是有差異的,所以在注入之前,我們還要判斷一下資料庫的型別。一般asp最常搭配的資料庫是access和sqlserver,網上超過99%的**都是其中之一。

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

sqlserver有一些系統變數,如果伺服器iis提示沒關閉,並且sqlserver返回錯誤提示的話,那可以直接從出錯資訊獲取,方法如下:

這句語句很簡單,但卻包含了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環境下可正常讀取。

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

如果資料庫是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欄位,首先,我們取第一條記錄,測試長度:

;;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為正數,但由

SQL注入全過程深入分析

初步注入 繞過驗證,直接登入 公司 登陸框如下 可以看到除了賬號密碼之外,還有乙個公司名的輸入框,根據輸入框的形式不難推出sql的寫法如下 複製 如下 select from table where name xx anwww.cppcns.comd password yy and corp zz ...

SQL注入(三) sql注入 bugku

原理 mysql 在使用 gbk 編碼的時候,會認為兩個字元為乙個漢字,例如 aa 5c 就是乙個 漢字 前乙個 ascii碼大於 128 才能到漢字的範圍 我們在過濾 的時候,往往利用的思 路是將 轉換為 換的函式或者思路會在每一關遇到的時候介紹 因此我們在此想辦法將 前面新增的 除掉,一般有兩種...

SQL注入 報錯注入

乙個帶get引數的 並且不從資料庫返回資料,但存在報錯資訊 檢視字段情況 報錯注入語句格式 and 1 2 union select1,2,3 from select count concat floor rand 0 2 sql語句 a from information schema.tables...