來自i春秋作者:萬年死宅

0x00 目錄

  • 0x00 目錄
  • 0x01 MySQL注射的簡單介紹
  • 0x02 對于information_schema庫的研究
  • 0x03 注射第一步——確定查詢語句的查詢對象個數
  • 0x04 注射第二步——UNION聯合查詢
  • 0x05 注射第三步——MySQL基礎信息收集
  • 0x06 注射第四步——通過利用點GET敏感表及列
  • 0x07 注射第五步——通過已知表、列GET數據

0x01 MySQL注射的簡單介紹

MySQL的注射,我們就來簡單的總結下,我們MySQL注射的利用點。 首先,我們先來說下現在幾乎沒什么網站用的Access數據庫吧,在最早期的Web安全技術的學習中,我們最早接觸到的工具相信都是啊D和明小子,而這兩款工具正是針對與Access數據庫的注射漏洞的利用工具。 而提到Access的注射,相信大家都能想到兩個字“爆破”或者是“猜解”。對,這就是Access數據庫存在SQL注射漏洞時的利用點,而我們第4篇文章中所演示的MySQL注射的利用點,自然不是“猜解”。(順便說一下,我說的只是針對于MySQL5及以上版本)這種注射的利用點是information_schema這個默認數據庫,這里面記錄了該MySQL數據庫所存儲的所有數據。 所以,針對于MySQL數據庫的注射都是利用提取information_schema庫里的信息來獲取表名與列名的。

0x02 對于information_schema庫的研究

既然這類注射的利用點在于information_schema這個默認庫,那么自然,我們就應該增進對于這個庫的一些了解,接下來,我們就來研究下這個information_schema庫。 首先,我們啟動MySQL服務,并且登錄MySQL:

然后,我們還是來看下存在的數據庫:

我們看到了information_schema數據庫,也就證明了我安裝的MySQL版本大于5,我們可以來看下具體版本:

我們可以看到版本是5.6.17。接著,我們進入information_schema庫:

接著,我們來show一下表:

可以看到,這個庫里面有很多表,而我們獲取其他數據庫里的表、列名情況所利用的是一個叫tables的表,如下圖:

我們看看這個tables表里存在那些column: 可以看到,tables表里情況復雜。。。我們所需要學習的只是其中幾個,包括table_name、colum_name、table_schema,如圖:

還有一個沒圈到,可能是在下面,也可能是我眼睛不好。。。。我先來了解下table_schema這個列:

這里面包含了所有我們安裝在這個MySQL上的數據庫的db_name,會有很多重復,接著,我們來看下table_name里的情況: 這個表里則包含了該MySQL安裝過的表的名字,好了,關于這個infromation_schema的庫,我就寫到這里,because我們的主題不是這個。

0x03 注射第一步——確定查詢語句的查詢對象個數

(之前相關文章可在i春秋查看 http://bbs.ichunqiu.com/)

我們在第4篇的通用注射方式里的第一步就是確定原查詢語句的查詢對象的個數,什么意思呢? 其實很簡單,我們還是使用第4篇的栗子,我把MySQL切換到sqli數據庫:

然后,用上節課的SQL模型,如下:

這個X的位置,便是我們能夠注射的位置,這個查詢對象是什么意思呢? 其實,在這里查詢對象就是data,個數就是1。這樣或許大家還是不能理解,那我們舉如下栗子:

這次查詢對象就變為了,但是長度卻改變了,因為代表的是ALL的意思,那我們就來看看在news表中到底有幾個對象:

我們能看到,news表中有兩個列,所以,這次的查詢對象個數就是2。 但是,我們進行SQL注射只能控制SQL語句的一個部分,而不能知道原本的查詢語句啊,那怎么辦? 這時,我們就只能勞靠order by了,我們來看如下的栗子(還是一樣的SQL模型)

我們在上面的栗子中可以看到,第一次查詢是正常的查詢,返回正常的查詢結果,而第二次查詢則是加了order by 1,達到的效果就是返回正常查詢結果,因為原SQL模型的查詢對象個數就是1,而第三次查詢則使用了order by 2,而原查詢語句的查詢對象個數是1,而不是2,所以產生了錯誤。 這就是利用order by來獲取未知查詢語句的查詢對象個數。

0x04 注射第二步——UNION聯合查詢

好滴,接下來,我們就要使用聯合查詢了,這個union到底是拿來干啥的啊,很不解對吧,那我們就先來學習一下union。 我們先來執行如下SQL語句,并查看結果:

可以看到select什么就是什么,接著,我們來看一下下面這個圖(別閑枯燥,都是為了后面做鋪墊):

這就是news表里的全部數據,我們想一下,我們有如下程序:

這個程序,我們假設它叫test.php吧,關于getData()函數,圖上有注釋,我們想,當id為1~9的時候,這個程序確實沒任何問題,但是試想,當id等于10的時候,就沒法查詢出結果,說不定還會報錯,這樣很影響用戶體驗。 所以,有時,可以使用union來解決這種問題,例如如下SQL模型就能解決這種問題:

X的位置就是剛才那個程序的id參數的拼接處,這樣就解決了剛才說的問題,不信我們來看:

可以看到,在第一次查詢時id為1,的確存在這個數據,于是正常返回查詢結果,其實也不完全正常,因為還多了個Error,但是這個很好處理,直接在mysql_fetch_array()之后的返回值里取數組的[0]就可以了。 而第二次查詢,id為10,不存在這條數據,于是,語句錯誤了,所以查詢結果就變成了Error。 Ok,就是這樣,這就是UNION的基礎用法,但是還沒轉過彎來的同學可能還會問那剛才為什么要order by? 其實,這也怪我,沒講清楚,我們來看如下栗子:

很明了吧,嘿嘿,好了。我們最后在說一個問題,當我們有原語句出現錯誤時,我們的union的內容就會替換掉查詢結果,其實類似于如下等式:

select * from news where id=10 union select 'Error',1000;
=
select 'Error',1000;

好了,接著就是下一個內容了。

0x05 注射第三步——MySQL基礎信息收集

Ok,基礎的東西終于嘮完了,我們就來玩玩吧,我們先看下面這樣一個列表:

  • database() 當前數據庫
  • version() 數據庫版本
  • user() 當前用戶

就這樣三個基礎信息吧,我們先直接查詢下:

我們可以看到如下幾個基礎信息,根據我們0x04里最后提的等式,可以構造出如下SQL語句來GET這些信息:

OK,長話短說了我們試試吧,首先是GET當前庫:

接著是數據庫版本: 最后是當前用戶:

OK,就這么簡單,其實注射并不難,只是缺少系統性的資料以及各種資料的“質量”參差不齊才導致有很多朋友覺得SQL注射很難學。

0x06 注射第四步——通過利用點GET敏感表及列

好滴,接著,我們來到了0x06,真心寫得好累,阿西吧,神吶。。。好了,利用點自然是information_schema庫。 我們首先想獲取的自然是當前庫里的所有表,大家還記得吧,在0x02的地方,我曾說過information_schema庫里的tables表里存著我們想要的信息,首先table_schema里存的是啥?是所有數據庫名吧,那table_name里存的啥?是所有表名吧,既然如此,只需要將select database()查出來的當前庫名對應一下,自然就能得到所有屬于當前庫的表名了哎。 所以,我們來先正常嘗試一下(額,對了跨庫的話就“from 庫名.表名”就行了):

可以看到,確實獲取了屬于sqli庫的所有表名,此時一看,哪個敏感一幕了然啊,嘿嘿,讓我們猥瑣的繼續:

就這么簡單,通過前面那個等式,大家就能夠通過這兩個語句直接構造攻擊的Payload了吧,嘿嘿(容我猥瑣的笑會兒~~)

0x07 注射第五步——通過已知表、列GET數據

好了,最后,我們就能通過已知的表、列GET想要的數據了,例如:

但是例如php程序在處理查詢結果時有點坑咋辦?就例如mysql_fetch_array()后只取了[0]咋辦?難道一個一個查?那不累死? 所以還是用第4篇里講到過的group_concat()函數來解決吧,如下例:

好了,這篇paper就到這里了,接下來還會有更多更高級的SQL注射技巧等著大家~~

去i春秋查看更多:http://bbs.ichunqiu.com/thread-10222-1-1.html?from=paper


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/21/