在《SQL注入基礎》一文介紹了SQL注入的基本原理和實驗方法,那接下來就要問一下,SQL注入到底能什麼?mysql
估計不少朋友會這樣認爲:利用SQL注入最多隻能獲取當前表中的全部記錄,但沒法獲取其它表的內容,事實果然的如此?sql
正像小偷從窗戶爬進入房間,難道他只能在房間內偷東西?非也,他能夠將整個房子洗劫一空。數據庫
不相信?那來看看如何對MySQL進行爆庫。安全
若是做爲一名黑客,根本沒法知道系統中有哪些表,表中有哪些字段,那如何將數據庫的內容竊取出來呢?服務器
答案是MySQL數據有一個元數據庫,它會描述整個MySQL服務器有哪些數據庫,每一個數據有哪些表,每一個表有哪些字段,這就至關於把自家房子有什麼寶貝通通告訴別人了。學習
那這個元數據庫就一個根,只要抓住了這根據,沿着:測試
元數據庫 -> 數據庫列表->表列表->字段列表->表內容spa
這個樹狀分層的檢索順序,就能夠將整個數據庫內容所有竊取出來,下面就跟你們演示。.net
剛纔談到MySQL裏面有個元數據庫,但它在藏在哪裏呢?別急,請登陸MySQL數據庫,並運行show databases;
命令,就能夠獲取全部數據庫列表,以下圖所示:設計
圖片中標紅色的數據庫information_schema
就是元數據庫,裏面應用盡有,能夠盡情開拓處女地。
進入information_schema
數據庫,看看裏面有哪些數據表,使用以下命令:
咱們所說的根就在SCHEMATA
表,它裏面描述了整個MySQL 下全部數據庫。
而後再利用TABLES
表,則能夠看到數據下的表名,再利用COLUMNS
表,則能夠看到每一個表下的字段名。下面依次展現如何查看這些數據。
SCHEMATA表描述全部數據庫信息,只需標準的select語句:
SELECT * FROM information_schema.SCHEMATA
便可將該表的內容所有顯示出來:
請注意,從這裏開始再也不入進入某個數據庫以後再訪問表,而是採用<數據庫名>.<表名>的標準格式來訪問某個數據庫下的表。上述的
information_schema.SCHEMATA
表示查詢information_schema
數據庫下的SCHEMATA
表。
圖中SCHEMA_NAME
字段爲數據庫名,從查詢結果能夠知該MySQL服務器有5個數據庫。
有了數據庫列表,就能夠進一步查看某個數據庫下全部表(當前也能夠查看全部數據庫下的全部表)。好比查看lyt_test
數據庫下的全部表,使用SQL語句:
SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'lyt_test'
查詢結果以下圖所示:
TABLE_NAME
表示表名,左列TABLE_SCHEMA
爲數據庫名,因爲lyt_test數據庫下只有accounts這個表,因此輸出結果只有一列。
而後使用COLUMNS表能夠查詢表的全部字段信息,使用下面SQL語句可查詢accounts表的全部字段名和類型: SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE FROM information_schema.COLUMNS WHERE TABLE_NAME = 'accounts'
查詢出accounts表全部字段和類型信息以下圖所示:
查看accounts表中的內容更是小菜一碟了,學過數據庫的都知道SQL寫成下面這樣: SELECT * FROM lyt_test.accounts
結果以下:
好了,到這裏相信你已經學習如何從MySQL中竊取全部數據庫內容了。
偉大的物理學家阿某米德曾經說過:
給我一個支點,我能夠撬起整個地球
前面從技術上介紹了在不知道MySQL數據如何設計的狀況下,經過元數據庫informatio_schema
,一步步將整個數據庫內容竊取出來。
那麼如何利用SQL注入來竊取整個數據庫呢?,這就是要尋找的支點。
還記得上篇文章介紹的實驗嗎?利用SQL注入技術,能夠將userinfo表中的全部數據都竊取出來。但該SQL能注入的部分只是WHERE
部分,而SELECT ... FROM ...
部分中的字段和表名倒是沒法注入的,那怎麼能夠將其它表的數據竊取出來呢?
這個密祕就就是利用UNION
語句。是的,標準SQL提供了UNION
語句,能夠將兩個SELECT
結果聯合起來(即對兩個SELECT
結果做並集)。UNION
語句的語法以下:
SELECT column_name1(s) FROM table_name1 UNION SELECT column_name2(s) FROM table_name2
惟一的要求就是兩個SELECT
語句的列數要相等。
有了UNION
語句,就能夠將SELECT * from userinfo WHERE ...
和 SELECT * from lyt_test.accounts
兩個結果聯合起來。
等等,做爲一個黑客,沒有拿到源代碼,怎麼知道SELECT * from userinfo
查詢結果有多少列呢?
顯然是不知道的,但可經過試探方法拿到這個數值:依次注入UNION SELECT 1, ... N
這樣的語句來試探。先嚐試SELECT 1
, 再SELECT 1,2
, 而後SELECT 1,2,3
,直到不運行出錯爲止。能夠先在MySQL上測試一下,結果下圖所示:
從上圖測試結果可知UNION後面跟的SELECT
結果必須是兩列,不然會出錯。
對了,還記得注入時WHERE
後是兩個條件嗎?(name = ‘name′ANDpasswd=′passswd ‘),在實際代碼中可能會是更復雜的條件,甚至黑客也很難猜想的條件,那這個UNION
語然該插在那個變量呢?使得整個SQL仍是個合法的查詢語句。
最好安全的作法是將UNION SELECT ...
注入到第一個變量中,而後注入的尾部增長一個註釋符號,將後的語句註釋掉,就不會考慮後面的是什麼語句了。在MySQL數據庫,使用#
符號便可實現註釋。
說了這麼多,能夠作一下注入測試,驗證一下:
在username
文本框中輸入:ivan' union select 1,2#
,以下圖:
點login
按鈕後的運行結果以下圖所示:
請留注下紅框中生成的SQL
語句:
SELECT * FROM userinfo WHERE name = ‘ivan’ union select 1,2# AND passwd = 」
#
將後面的SQL內容註釋掉了,MySQL解析時直接將它幹掉,至關於下面的SQL語句:
SELECT * FROM userinfo WHERE name = ‘ivan’ union select 1,2
select 1, 2的結果是常數行, 在後面的例中嘗試從表中查詢數據,而不徹底是常數行。
好了 ,UNION
和#
就是撬動爆庫的那個支點
萬事俱備,只欠東風。那就讓吹起東風吹起來吧,吹得更猛烈一些。
如下實驗都是基於《SQL注入基礎》一文開發的數據庫應用demo來實驗的,若是讀者沒有SQL注入的基礎知識,建議看看這篇文章;同時建議SQL注入的初學者也按此文搭建相同的數據應用demo來實驗測試一把。
往username
中注入:
ivan’ union select 1,SCHEMA_NAME from information_schema.SCHEMATA #
便可查詢全部數據庫列表以下圖:
圖示標紅色框的就是數據庫列表。咱們在UNION SELECT ...
語句中第一列爲常數1,第二列是information_schema.SCHEMATA表中SCHEMA_NAME這一列,它恰好就是數據庫名。
爲了精減輸出結果,這裏只爆lyt_test數據庫下的表名,往username
中注入:
ivan’ union select 1,TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA = ‘lyt_test’#
便可查詢得lyt_test數據庫下全部表,以下圖所示:
不一樣的地方是lyt_test數據庫下只有accounts一個表,其它與爆數據庫原理相同,不做過多解釋。
這裏只爆accounts表下的全部字段,往username
中注入:
ivan’ union select 1, COLUMN_NAME from information_schema.COLUMNS WHERE TABLE_NAME = ‘accounts’ #
結果以下圖所示:
標紅的是字段名。那麼類型呢? 修改注入內容爲:
ivan’ union select 1, DATA_TYPE from information_schema.COLUMNS WHERE TABLE_NAME = ‘accounts’ #
就能夠獲取字段類型信息,以下圖所示:
標紅色的分別是前面兩個字段的類型,即ID
類型爲char
, balance
類型爲float
。
從上面能夠發現規律:每一個注入能夠獲取到目標表中的每一個列表數據, 若是表中有N表,注入N次能夠獲取完整的表信息。
這裏就不寫的,讀者能夠本身練習一下,原來跟上面徹底同樣。
原來SQL注入爆數據庫是這麼容易的,但有幾個必備條件
UNION
語句,能夠新增竊取其它數據合併到被注入SELECT
結果#
,讓注入能夠隨心所欲爆庫的精髓掌握了嗎?快來試試。
注:本文轉自http://blog.csdn.net/linyt/article/details/52966555#