01 背景知識(shí)
一枚抵、為什么要進(jìn)行URL編碼
通常如果一樣?xùn)|西需要編碼线欲,說(shuō)明這樣?xùn)|西并不適合傳輸。對(duì)于URL來(lái)說(shuō)汽摹,編碼主要是為了避免引發(fā)歧義與混亂李丰。
例如,URL參數(shù)字符串中使用key=value鍵值對(duì)這樣的形式來(lái)傳參逼泣,鍵值對(duì)之間以&符號(hào)分隔趴泌,如/?name=abc&pwd=123
如果你的value字符串中包含了=或者&舟舒,那么勢(shì)必會(huì)造成接收Url的服務(wù)器解析錯(cuò)誤,因此必須將引起歧義的&和= 符號(hào)進(jìn)行轉(zhuǎn)義嗜憔,也就是對(duì)其進(jìn)行編碼秃励。
對(duì)于URL編碼的深入研究可以參看下面這些內(nèi)容:
為什么要進(jìn)行URL編碼
深入分析 web 請(qǐng)求響應(yīng)中的編碼問(wèn)題
二、URL傳輸過(guò)程中的編碼問(wèn)題
HTTP請(qǐng)求過(guò)程經(jīng)歷的幾個(gè)環(huán)節(jié):
瀏覽器【get/post】①========>服務(wù)器②========>瀏覽器顯示③
- ①:瀏覽器會(huì)把URL經(jīng)過(guò)編碼后發(fā)送給服務(wù)器吉捶,不同的瀏覽器對(duì)URL的編碼規(guī)則不同夺鲜。對(duì)于GET方式提交的數(shù)據(jù),瀏覽器會(huì)自動(dòng)進(jìn)行URL編碼帚稠;對(duì)于POST方式提交的數(shù)據(jù)谣旁,其編碼方式可以由開(kāi)發(fā)者進(jìn)行指定。
- ②:服務(wù)器根據(jù)其自身的配置文件對(duì)URL進(jìn)行解碼(解碼成Unicode)滋早,然后將顯示內(nèi)容編碼榄审。
- ③:瀏覽器按照指定的編碼顯示該網(wǎng)頁(yè)。
此外杆麸,在客戶端也就是瀏覽器上運(yùn)行的前端程序也會(huì)根據(jù)Web服務(wù)的需要對(duì)要傳輸?shù)臄?shù)據(jù)進(jìn)行一些編碼操作搁进,而在服務(wù)端除了服務(wù)器中間件會(huì)自動(dòng)對(duì)URL進(jìn)行解碼,后端的Web程序會(huì)對(duì)前端進(jìn)行編碼的數(shù)據(jù)進(jìn)行解碼操作昔头。
02 二次編碼注入
下面這幅圖片很好地解釋了二次編碼注入的原理(圖片來(lái)源為網(wǎng)易Web安全工程師課程饼问,侵刪):
從中我們也可以得知,二次編碼注入產(chǎn)生的原因是:
后端程序的編碼函數(shù)揭斧,如urldecode()等莱革,與PHP本身處理編碼時(shí),兩者配合失誤讹开,使得攻擊者可以構(gòu)造數(shù)據(jù)消滅\
看一下實(shí)例代碼:
//用GET方式獲取id值盅视,并對(duì)其中的特殊字符進(jìn)行轉(zhuǎn)義
$id = mysql_real_escap_string($_GET['id']);
//使用urldecode()函數(shù)進(jìn)行解碼
$id = urldecode($id);
$sql = "SELECT * FROM usres WHERE id = '$id' LIMIT 0,1;
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
上面的代碼就是一個(gè)二次注入的典型場(chǎng)景,這時(shí)如果我們提交:
http://127.0.0.1/sql.php?id=1%2527
就可以繞過(guò)對(duì)'
的轉(zhuǎn)義旦万,進(jìn)行SQL注入攻擊闹击。
在測(cè)試時(shí),如果發(fā)現(xiàn)了頁(yè)面可能存在二次編碼注入漏洞成艘,也可以使用sqlmap進(jìn)行自動(dòng)化攻擊
//只需在注入點(diǎn)后鍵入%2527即可
python sqlmap.py -u "http://127.0.0.1/sql.php?id=1%2527"
分享一個(gè)二次編碼注入的漏洞實(shí)例