宽字节注入原理_sqlmap宽字节注入
在mysql中,用于轉(zhuǎn)義的函數(shù)有addslashes,mysql_real_escape_string,mysql_escape_string等,
還有一種情況是magic_quote_gpc,不過(guò)高版本的PHP將去除這個(gè)特性。
首先,寬字節(jié)注入與HTML頁(yè)面編碼是無(wú)關(guān)的,筆者曾經(jīng)看到
<meta charset=utf8>
就放棄了嘗試,這是一個(gè)誤區(qū),SQL注入不是XSS。雖然他們中編碼的成因相似,不過(guò)發(fā)生的地點(diǎn)不同。
很多網(wǎng)上的材料都說(shuō)程序使用了寬字節(jié)來(lái)處理程序,卻又不指出具體是指什么程序。本文就介紹一下具體
漏洞發(fā)生的原理與簡(jiǎn)單的利用。在這里我們限定使用的語(yǔ)言是PHP5.4,數(shù)據(jù)庫(kù)MYSQL5.6。
涉及到的一些概念
字符、字符集與字符序
字符(character)是組成字符集(characterset)的基本單位。對(duì)字符賦予一個(gè)數(shù)值(encoding)
來(lái)確定這個(gè)字符在該字符集中的位置。
字符序(collation)指同一字符集內(nèi)字符間的比較規(guī)則。
UTF8
由于ASCII表示的字符只有128個(gè),因此網(wǎng)絡(luò)世界的規(guī)范是使用UNICODE編碼,但是用ASCII表示的字符使用UNICODE并不高效。
因此出現(xiàn)了中間格式字符集,被稱為通用轉(zhuǎn)換格式,及UTF(UniversalTransformationFormat)。
寬字節(jié)
GB2312、GBK、GB18030、BIG5、Shift_JIS等這些都是常說(shuō)的寬字節(jié),實(shí)際上只有兩字節(jié)。
寬字節(jié)帶來(lái)的安全問(wèn)題主要是吃ASCII字符(一字節(jié))的現(xiàn)象。
MYSQL的字符集轉(zhuǎn)換過(guò)程
1.MySQLServer收到請(qǐng)求時(shí)將請(qǐng)求數(shù)據(jù)從character_set_client轉(zhuǎn)換為character_set_connection;
2.進(jìn)行內(nèi)部操作前將請(qǐng)求數(shù)據(jù)從character_set_connection轉(zhuǎn)換為內(nèi)部操作字符集,其確定方法如下:
?使用每個(gè)數(shù)據(jù)字段的CHARACTERSET設(shè)定值;
?若上述值不存在,則使用對(duì)應(yīng)數(shù)據(jù)表的DEFAULTCHARACTERSET設(shè)定值(MySQL擴(kuò)展,非SQL標(biāo)準(zhǔn));
?若上述值不存在,則使用對(duì)應(yīng)數(shù)據(jù)庫(kù)的DEFAULTCHARACTERSET設(shè)定值;
?若上述值不存在,則使用character_set_server設(shè)定值。
將操作結(jié)果從內(nèi)部操作字符集轉(zhuǎn)換為character_set_results。
重點(diǎn):寬字節(jié)注入發(fā)生的位置就是PHP發(fā)送請(qǐng)求到MYSQL時(shí)字符集使用character_set_client設(shè)置值進(jìn)行了一次編碼。
PHP測(cè)試代碼:
<!DOCTYPE html><meta charset=”gbk”><!–僅用于基礎(chǔ)的顯示,換成utf8也行就是不好看–><?php
error_reporting(0);$conn =mysql_connect(‘127.0.0.1′,’root’,”);mysql_select_db(‘mysql’,$conn);mysql_query(“set names gbk”);//不安全的編碼設(shè)置方式$res =mysql_query(“show variables like ‘character%’;”);//顯示當(dāng)前數(shù)據(jù)庫(kù)設(shè)置的各項(xiàng)字符集while($row =mysql_fetch_array($res)){var_dump($row);}$user =addslashes($_GET[‘sql’]);//mysql_real_escape_string() magic_quote_gpc=On addslashes() mysql_escape_string()功能類似$sql =”SELECT host,user,password FROM user WHERE user='{$user}'”;echo $sql.'</br>’;if($res =mysql_query($sql)){while($row =mysql_fetch_array($res)){var_dump($row);}}else{echo “Error”.mysql_error().”<br/>”;}?>
http://localhost/xl.php?sql=root%df%27%20or%201=1%23
是可以執(zhí)行成功的!
URL解碼sql=root?’or1=1#
解析過(guò)程:
$_GET[‘sql’]經(jīng)過(guò)addslashes編碼之后帶入了‘\’
1、root%df%5C%27%20or%201=1%232、帶入mysql處理時(shí)使用了gbk字符集%df%5c->運(yùn)成功的吃掉了%5c%27->‘單引號(hào)成功閉合
執(zhí)行了插入的sql語(yǔ)句。
怎么吃的:
GBK編碼,它的編碼范圍是0x8140~0xFEFE(不包括xx7F),在遇到%df(ascii(223))>ascii(128)時(shí)自動(dòng)拼接%5c,
因此吃掉‘\’,而%27、%20小于ascii(128)的字符就保留了。
補(bǔ)充:
GB2312是被GBK兼容的,它的高位范圍是0xA1~0xF7,低位范圍是0xA1~0xFE(0x5C不在該范圍內(nèi)),因此不能使用編碼吃掉%5c。
其它的寬字符集也是一樣的分析過(guò)程,要吃掉%5c,只需要低位中包含正常的0x5c就行了。
安全過(guò)濾
上文中代碼使用了mysql_query(“setnamesgbk”)來(lái)設(shè)置編碼,其實(shí)在mysql中是推薦mysql_set_charset(“gbk”);函數(shù)來(lái)進(jìn)行編碼設(shè)置的,
這兩個(gè)函數(shù)大致的功能相似,唯一不同之處是后者會(huì)修改mysql對(duì)象中的mysql->charset屬性為設(shè)置的字符集。
同時(shí)配套的過(guò)濾函數(shù)為mysql_real_escape_string()。上面代碼中列出了幾個(gè)過(guò)濾的函數(shù),他們之間的區(qū)別就是mysql_real_escape_string()
會(huì)根據(jù)mysql對(duì)象中的mysql->charset屬性來(lái)對(duì)待傳入的字符串,因此可以根據(jù)當(dāng)前字符集來(lái)進(jìn)行過(guò)濾。
同理可得
由上文可得寬字節(jié)注入是由于轉(zhuǎn)編碼而形成的,那具有轉(zhuǎn)編碼功能的函數(shù)也成了漏洞的成因。
轉(zhuǎn)碼函數(shù)
mb_convert_encoding()
iconv()
以下用iconv()來(lái)演示,修改上面的代碼:
<!DOCTYPE html><meta charset=”gbk”><?php
error_reporting(0);$conn =mysql_connect(‘127.0.0.1′,’root’,”);mysql_select_db(‘mysql’,$conn);mysql_set_charset(“utf8″);//推薦的安全編碼$user =mysql_real_escape_string(($_GET[‘sql’]));//推薦的過(guò)濾函數(shù)$user =iconv(‘GBK’,’UTF-8′,$user);$sql =”SELECT host,user,password FROM user WHERE user='{$user}'”;echo $sql.'</br>’;$res =mysql_query($sql);while($row =mysql_fetch_array($res)){var_dump($row);}?>
http://localhost/xl.php?sql=root%e5%27or%201=1%23
同樣可以執(zhí)行成功,編碼解析的過(guò)程依然如上。
總結(jié)一下漏洞成因:
代碼一
1、使用了不安全的字符集設(shè)置函數(shù)與過(guò)濾函數(shù)。
2、漏洞發(fā)生在PHP請(qǐng)求mysql時(shí)使用character_set_client值進(jìn)行一次轉(zhuǎn)碼。
代碼二
1、使用了推薦的設(shè)置函數(shù)與過(guò)濾函數(shù)。
2、解析錯(cuò)誤發(fā)生在iconv()函數(shù)轉(zhuǎn)碼時(shí),GBK轉(zhuǎn)向UTF8吃掉了“\”
3、PHP請(qǐng)求mysql時(shí)轉(zhuǎn)碼安全。
另外:
當(dāng)改變編碼方向時(shí)
這種情況下需要兩個(gè)參數(shù)來(lái)配合注入。
例如:
http://localhost/xl.php?sql=root%e9%8c%a6?=%20or%201=1%23
總結(jié):
寬字節(jié)注入跟HTML頁(yè)面編碼無(wú)關(guān)。
Mysql編碼與過(guò)濾函數(shù)推薦使用mysql_real_escape_string(),mysql_set_charset()。
轉(zhuǎn)編碼函數(shù)同樣會(huì)引起寬字節(jié)注入,即使使用了安全的設(shè)置函數(shù)。
參考文獻(xiàn)
mysql字符集的設(shè)置:http://www.laruence.com/2008/01/05/12.html
總結(jié)
以上是生活随笔為你收集整理的宽字节注入原理_sqlmap宽字节注入的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 调查一下 大家用vs时做网页时,都用的什
- 下一篇: sop流程图模板_这是一份标准作业流程S