SQL注入防御繞過(guò)——寬字節(jié)注入

01 背景知識(shí)

字符集

在了解寬字節(jié)注入之前嵌溢,我們先來(lái)看一看字符集是什么。字符集也叫字符編碼逸雹,是一種將符號(hào)轉(zhuǎn)換為二進(jìn)制數(shù)的映射關(guān)系止潘。
幾種常見(jiàn)的字符集:

  • ASCII編碼:?jiǎn)巫止?jié)編碼
  • latin1編碼:?jiǎn)巫止?jié)編碼
  • gbk編碼:使用一字節(jié)和雙字節(jié)編碼,0x00-0x7F范圍內(nèi)是一位,和 ASCII 保持一致法绵。雙字節(jié)的第一字節(jié)范圍是0x81-0xFE
  • UTF-8編碼:使用一至四字節(jié)編碼箕速,0x00–0x7F范圍內(nèi)是一位,和 ASCII 保持一致朋譬。其它字符用二至四個(gè)字節(jié)變長(zhǎng)表示盐茎。

寬字節(jié)就是兩個(gè)以上的字節(jié),寬字節(jié)注入產(chǎn)生的原因就是各種字符編碼的不當(dāng)操作徙赢,使得攻擊者可以通過(guò)寬字節(jié)編碼繞過(guò)SQL注入防御字柠。

MySQL字符轉(zhuǎn)換

數(shù)據(jù)提交到MySQL數(shù)據(jù)庫(kù),需要進(jìn)行字符集的轉(zhuǎn)換狡赐,使得MySQL數(shù)據(jù)庫(kù)可以對(duì)數(shù)據(jù)進(jìn)行處理窑业,這一過(guò)程一般有以下三個(gè)步驟:

  1. 收到請(qǐng)求,將請(qǐng)求數(shù)據(jù)從 character_set_client ->character_set_connection枕屉。
  2. 內(nèi)部操作常柄,將數(shù)據(jù)從character_set_connection-> 表創(chuàng)建的字符集
  3. 結(jié)果輸出搀擂,將數(shù)據(jù)從表創(chuàng)建的字符集 -> character_set_results西潘。

當(dāng)執(zhí)行set names "charset",相當(dāng)于執(zhí)行
set character_set_client = charset
set character_set_connection = charset
set character_set_results = charset

client 指的是PHP程序
connection 指的是PHP客戶(hù)端與MySQL服務(wù)器之間連接層
results 指的是MySQL服務(wù)器返回給PHP客戶(hù)端的結(jié)果

MySQL常見(jiàn)的亂碼問(wèn)題就是這三個(gè)字符集的設(shè)置不當(dāng)所引起的哨颂。

02 寬字節(jié)注入

這里的演示環(huán)境為 sqli-labs\Less-32

<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");

function check_addslashes($string)
{
    $string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string);          //escape any backslash
    $string = preg_replace('/\'/i', '\\\'', $string);                               //escape single quote with a backslash
    $string = preg_replace('/\"/', "\\\"", $string);                               //escape double quote with a backslash
    return $string;
}

// take the variables 
if(isset($_GET['id']))
{
$id=check_addslashes($_GET['id']);
//echo "The filtered request is :" .$id . "<br>";

//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);

// connectivity 

mysql_query("SET NAMES gbk");
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

    if($row)
    {
    echo '<font color= "#00FF00">'; 
    echo 'Your Login name:'. $row['username'];
    echo "<br>";
    echo 'Your Password:' .$row['password'];
    echo "</font>";
    }
    else 
    {
    echo '<font color= "#FFFF00">';
    print_r(mysql_error());
    echo "</font>";  
    }
}
    else { echo "Please input the ID as parameter with numeric value";}
?>

普通注入

當(dāng)用戶(hù)提交
http://127.0.0.1/Less-32/?id=1'
此時(shí)喷市,發(fā)生如下轉(zhuǎn)換
第一步:'check_addslashes 函數(shù)轉(zhuǎn)義為 \'

第二步:在執(zhí)行sql查詢(xún)之前,也即\'代入MySQL服務(wù)器之前威恼,mysql_query("SET NAMES gbk");將MySQL的三個(gè)字符集設(shè)置為 gbk 編碼

第三步:character_set_client告訴MySQL Server品姓,傳入的是gbk編碼,也就是\'被當(dāng)做了%5C%27傳入

第四步:character_set_client -> character_set_connection編碼完全一致沃测,數(shù)據(jù)沒(méi)有做任何轉(zhuǎn)換缭黔,所以輸入是%5C%27,輸出的是%5C%27

第五步:character_set_connection-> table charset這里我們需要關(guān)注下所使用的表的字符集

table_charset

可以看到id參數(shù)沒(méi)有設(shè)置編碼方式蒂破,不會(huì)對(duì)%5C%27進(jìn)行處理馏谨。在這里MySQL服務(wù)器將查詢(xún)語(yǔ)句執(zhí)行,并返回結(jié)果附迷。
執(zhí)行的SQL語(yǔ)句為:
$sql="SELECT * FROM users WHERE id='1\'' LIMIT 0,1";
'被轉(zhuǎn)義無(wú)法進(jìn)行注入

第六步:table charset -> character_set_results由于character_set_results字符集也設(shè)定為 gbk 惧互,保證了輸出內(nèi)容沒(méi)有亂碼。

通過(guò)上面的分析喇伯,我們發(fā)現(xiàn)用戶(hù)提交的數(shù)據(jù)實(shí)際上只被處理了兩次喊儡,一次是check_addslashes對(duì)危險(xiǎn)字符的處理,另一次是gbk編碼稻据。所以艾猜,我們可以將以上步驟簡(jiǎn)化為:

數(shù)據(jù) ==== (check_addslashes)====XXX====(GBK)====代入數(shù)據(jù)庫(kù)執(zhí)行的內(nèi)容

寬字節(jié)注入

提交:
http://127.0.0.1/Less-32/?id=1%df'('瀏覽器自動(dòng)進(jìn)行url編碼%27)
根據(jù)以上分析,發(fā)生如下轉(zhuǎn)換:
%df%27====>(check_addslashes)====>%df%5c%27====>(GBK)====>運(yùn)'
MySQL執(zhí)行的語(yǔ)句為:
$sql="SELECT * FROM users WHERE id='1運(yùn)'' LIMIT 0,1";成功將單引號(hào)閉合,可以進(jìn)行SQL注入匆赃。

寬字節(jié)注入2.0

為了避免漏洞淤毛,網(wǎng)站一般會(huì)設(shè)置UTF-8編碼,然后進(jìn)行轉(zhuǎn)義過(guò)濾算柳。但是由于一些不經(jīng)意的字符集轉(zhuǎn)換低淡,又會(huì)導(dǎo)致漏洞。
使用set names UTF-8指定了UTF-8字符集瞬项,并且也使用轉(zhuǎn)義函數(shù)進(jìn)行轉(zhuǎn)義蔗蹋。有時(shí)候,為了避免亂碼囱淋,會(huì)將一些用戶(hù)提交的GBK字符使用iconv函數(shù)先轉(zhuǎn)為UTF-8猪杭,然后再拼接入SQL語(yǔ)句。

mysql_query(“set names UTF-8”) ;  
$bar =iconv(“GBK”,”UTF-8”, addslashes($_GET[‘’bar])) ; 

提交:
http://127.0.0.1/Less-32/?id=1%e5%5c%27
轉(zhuǎn)換:(%e5%5c轉(zhuǎn)為UTF-8為e9%8c%a6
%e5%5c%27====>(addslashes)====>%e5%5c%5c%5c%27====(iconv)====>%e9%8c%a6%5c%5c%27
可以看到绎橘,多出了一個(gè)%5c胁孙,將轉(zhuǎn)義符(反斜杠)本身轉(zhuǎn)義唠倦,使得后面的%27單引號(hào)發(fā)揮了作用

03 寬字節(jié)注入防御(參考源)

對(duì)于寬字節(jié)編碼称鳞,有一種最好的修補(bǔ)就是:

(1)使用mysql_set_charset(GBK)指定字符集

(2)使用mysql_real_escape_string進(jìn)行轉(zhuǎn)義

原理是,mysql_real_escape_stringaddslashes的不同之處在于其會(huì)考慮當(dāng)前設(shè)置的字符集稠鼻,不會(huì)出現(xiàn)前面e5和5c拼接為一個(gè)寬字節(jié)的問(wèn)題冈止,但是這個(gè)“當(dāng)前字符集”如何確定呢?

就是使用mysql_set_charset進(jìn)行指定候齿。

上述的兩個(gè)條件是“與”運(yùn)算的關(guān)系熙暴,少一條都不行。
<meta charset="utf-8">

測(cè)試;

1

輸出:

2
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末慌盯,一起剝皮案震驚了整個(gè)濱河市周霉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌亚皂,老刑警劉巖俱箱,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異灭必,居然都是意外死亡狞谱,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)禁漓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)跟衅,“玉大人,你說(shuō)我怎么就攤上這事播歼×骢危” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)叭莫。 經(jīng)常有香客問(wèn)我磷支,道長(zhǎng),這世上最難降的妖魔是什么食寡? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任雾狈,我火速辦了婚禮,結(jié)果婚禮上抵皱,老公的妹妹穿的比我還像新娘善榛。我一直安慰自己,他們只是感情好呻畸,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布移盆。 她就那樣靜靜地躺著,像睡著了一般伤为。 火紅的嫁衣襯著肌膚如雪咒循。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天绞愚,我揣著相機(jī)與錄音叙甸,去河邊找鬼。 笑死位衩,一個(gè)胖子當(dāng)著我的面吹牛裆蒸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播糖驴,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼僚祷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了贮缕?” 一聲冷哼從身側(cè)響起辙谜,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎感昼,沒(méi)想到半個(gè)月后装哆,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抑诸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年烂琴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜕乡。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡奸绷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出层玲,到底是詐尸還是另有隱情号醉,我是刑警寧澤反症,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站畔派,受9級(jí)特大地震影響铅碍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜线椰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一胞谈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧憨愉,春花似錦烦绳、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至躺孝,卻和暖如春享扔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背植袍。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工惧眠, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人奋单。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓锉试,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親览濒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 網(wǎng)頁(yè)出現(xiàn)亂碼的原因: 客戶(hù)端與數(shù)據(jù)庫(kù)的數(shù)據(jù)傳輸處編碼拖云、數(shù)據(jù)庫(kù)存儲(chǔ)處編碼贷笛,兩者編碼不同,就會(huì)出現(xiàn)亂碼宙项。還有一種情況乏苦,...
    FKTX閱讀 2,707評(píng)論 0 0
  • 0x00概述 寬字節(jié)注入主要源于程序員設(shè)置數(shù)據(jù)庫(kù)編碼與php編碼設(shè)置為不同的兩種編碼,那么就可能產(chǎn)生寬字節(jié)注入 例...
    queena_閱讀 1,272評(píng)論 0 1
  • 寬字節(jié)注入是因?yàn)閿?shù)據(jù)庫(kù)使用了GBK編碼尤筐,不過(guò)現(xiàn)在大都使用unicode國(guó)際編碼汇荐,大多數(shù)網(wǎng)站都使用了utf-8的編碼...
    CSeroad閱讀 28,093評(píng)論 7 4
  • 一封老郵件: 之前出現(xiàn)的問(wèn)題就是當(dāng)數(shù)據(jù)庫(kù)字符集設(shè)置為gbk時(shí),%bf%27這個(gè)調(diào)用mysql_real_escap...
    書(shū)豪吳閱讀 336評(píng)論 0 0
  • 這是一個(gè)細(xì)弱的貓一樣的女孩子,安靜地?fù)Пеp膝油昂,蜷縮在地板的角落革娄,長(zhǎng)長(zhǎng)的披散著的頭發(fā)倾贰,遮住了整張面孔。 ...
    劉小柯閱讀 453評(píng)論 0 5