官术网_书友最值得收藏!

1.1.2 SQL注入進階

1.二次注入

二次注入是一種用來繞過輸入點防御的方法。通常開發人員會在用戶的輸入點進行關鍵字過濾和特殊字符轉義,給我們利用漏洞帶來了很大的困難。我們輸入的數據插入數據庫時會被還原并存儲在數據庫中,而當Web程序再次調用存儲在數據庫中的數據時,由于沒有將提取出來的數據進行轉義和過濾,就會執行我們插入的惡意SQL語句。下面介紹具體方法和步驟。

第一步,插入惡意數據。在向數據庫中插入數據時(如創建新用戶、添加評論、修改用戶信息等),Web程序對插入的數據進行轉義和過濾,在寫入數據庫時又將數據還原。

第二步,引用惡意數據。當Web程序將數據從數據庫中取出并調用時,惡意SQL語句被代入原始語句中,造成SQL二次注入,如圖1-27所示。

圖1-27 二次注入原理示意圖

以2019-CISCN華北賽區Day1 Web5-CyberPunk題目為例,通過文件包含漏洞方法讀出源碼,這里不做詳述,如圖1-28~圖1-30所示。

圖1-28 index.php源碼

圖1-29 change.php源碼

圖1-30 search.php源碼

可以看到,address雖然經過了過濾,但是在修改地址的時候從數據庫中取出的是沒有過濾直接帶入的SQL語句,從而導致SQL注入,如圖1-31所示。

圖1-31 修改地址處沒有過濾

由于這里是update語句,因此我們使用報錯注入,代碼如下。

結果如圖1-32~圖1-34所示。

圖1-32 插入惡意語句

圖1-33 再次調用

圖1-34 注入成功

2.無列名注入

通常在注入時我們可以利用information_schema庫獲取所有庫的庫名、表名、列名,但是這個庫經常被WAF(Web Application Firewall,網站應用級入侵防御系統)過濾。無列名注入適用于已經獲取數據表,但無法查詢列的情況,在大多數CTF題目中,information_schema庫被過濾,使用這種方法可以獲取列名。

無列名注入的原理很簡單,類似于將我們不知道的列名進行取別名操作,在取別名的同時進行數據查詢。

先創建一個數據庫demo,再創建一個testuser表,結構如圖1-35所示。

圖1-35 創建數據庫和數據表

往testuser表里插入一些數據,代碼如下。

正常查詢,結果如圖1-36所示。

圖1-36 正常查詢結果

這時再使用一個union查詢,如圖1-37所示。

圖1-37 union查詢結果

利用數字3代替未知的列名,需要加上反引號。代碼后面加了一個a,是為了表示這個表(select 1,2,3 union select*from testuser)的別名,如圖1-38所示。

圖1-38 代替未知列名

當反引號不能使用時,用別名來代替,如圖1-39所示。

圖1-39 列名被替換

以2019-SWPU-Web1題目為例,本題主要考查無列名注入和空格繞過。我們在試出列數后直接注入即可,如圖1-40所示。

圖1-40 注入成功

3.堆疊注入

顧名思義,堆疊注入就是一堆SQL語句一起執行。在MySQL語句中,每條語句的結尾都有一個“;”,代表一條語句結束。我們將多個SQL語句用“;”連接起來,就可以達到多條語句一起執行的效果,從而造成SQL注入。堆疊注入和union聯合查詢本質上都是將兩條語句連接在一起執行,區別在于union查詢只能連接兩條查詢語句,而堆疊注入可以連接兩條任意的語句。當WAF沒有過濾show、rename、alert等關鍵詞時,我們就可以考慮使用堆疊注入。

執行下列語句達到堆疊的效果,運行結果如圖1-41所示。

圖1-41 列名被替換

以2019-強網杯-隨便注題目為例,利用堆疊注入查看表信息,如圖1-42所示。

圖1-42 查看表名

查看1919810931114514表中的字段(注意,要將表名用反引號引出),如圖1-43所示。

圖1-43 獲取字段名

發現flag字段后,查看words表中的字段,如圖1-44所示。

圖1-44 獲取words表的字段名

發現id和data兩個字段,因為沒有過濾rename和alert,考慮將1919810931114514表改名為words, flag字段改名為data。

流程是將words表名改為其他名字,然后將1919810931114514表改名為words,最后將flag字段更名為data,代碼如下。

查詢1即可獲得flag,如圖1-45所示。

圖1-45 獲取flag

4.SQL注入與其他漏洞結合

有些時候,SQL注入漏洞并不能直接獲取flag,而是為了配合其他漏洞的使用,如SSTI(Server-Side Template Injection,服務端模板注入)、SSRF(Server Side Request Forgery,服務端請求偽造)等,其原理是控制某個漏洞處引用的值,從而達到文件讀取或RCE(Remote Command/Code Execute,遠程命令/代碼執行)的目的。

以2018-科來杯-Web3題目為例,本題考查SQL注入與SSTI利用。注入點并不難發現,使用常規的union聯合查詢就可以輕松發現注入點,代碼如下,運行結果如圖1-46所示。

圖1-46 發現注入點

這個時候利用SQL注入去拖庫會發現庫里什么都沒有。利用SSTI漏洞的原理就是在注入點處,Web程序將查詢到的內容再次引入具有SSTI漏洞的代碼。下面我們進行SSTI的測試(這里可以使用十六進制編碼),如圖1-47所示。

圖1-47 打印出配置信息

接下來就是常規的SSTI獲取服務器權限,代碼如下,效果如圖1-48所示。

圖1-48 獲取flag

上述代碼等同于如下代碼。

以2018-網鼎杯-Fakebook題目為例,本題的原理和上一題基本相同,都是先將可控點的值設為惡意代碼,然后由Web程序帶入另一段有漏洞的代碼中實現利用。可以理解為SQL注入起到的只是控制變量的作用。該題目首先具有源碼泄露,如圖1-49所示。

圖1-49 備份文件中得到源碼

在注冊界面輸入的blog字段經過了isValidBlog()函數的過濾。由于get()函數存在SSRF漏洞,因此直接在注冊界面輸入file://var/www/html/flag.php就能拿到flag。

這時我們注冊一個賬號進入,如圖1-50所示。

圖1-50 注冊用戶登錄

使用admin賬號登錄后發現URL里面有參數no,嘗試注入、爆庫,具體操作不再贅述,直接給出最終獲取數據的Payload。

獲取數據如圖1-51所示。

圖1-51 獲取數據

data數據段是一個序列化串,程序正常應該是從data字段中取出序列化串,然后進行反序列化,最終把信息展示給我們。我們在data字段中將blog的值修改為file:///var/www/html/flag.php,即可觸發SSRF漏洞并獲取flag,代碼如下。

運行結果如圖1-52所示。

圖1-52 獲取flag

最后進行Base64解碼即可。

本題還有一種非預期解法,因為出題人忘記對load_file函數進行過濾,導致我們可以直接任意讀取文件,如圖1-53所示,代碼如下。

圖1-53 用非預期解法獲取flag

主站蜘蛛池模板: 偏关县| 金堂县| 铁岭县| 巴林右旗| 鄯善县| 沭阳县| 株洲市| 兴仁县| 凤山市| 威信县| 大悟县| 乌兰察布市| 诸暨市| 收藏| 朝阳区| 南溪县| 伊川县| 合肥市| 高阳县| 腾冲县| 永泰县| 金湖县| 榆林市| 永州市| 江永县| 连山| 上林县| 察隅县| 吴川市| 吉安县| 黔西县| 阿尔山市| 叶城县| 天台县| 定陶县| 汾阳市| 云梦县| 越西县| 环江| 东辽县| 栾川县|