自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

科普:寬字節(jié)注入詳解

安全 數(shù)據(jù)安全
在mysql中,用于轉(zhuǎn)義的函數(shù)有addslashes,mysql_real_escape_string,mysql_escape_string等,還有一種情況是magic_quote_gpc,不過高版本的PHP將去除這個(gè)特性。

前言

在mysql中,用于轉(zhuǎn)義的函數(shù)有addslashes,mysql_real_escape_string,mysql_escape_string等,還有一種情況是magic_quote_gpc,不過高版本的PHP將去除這個(gè)特性。

[[111226]]

首先,寬字節(jié)注入與HTML頁面編碼是無關(guān)的,筆者曾經(jīng)看到

<meta charset=utf8>

就放棄了嘗試,這是一個(gè)誤區(qū),SQL注入不是XSS。雖然他們中編碼的成因相似,不過發(fā)生的地點(diǎn)不同。

很多網(wǎng)上的材料都說程序使用了寬字節(jié)來處理程序,卻又不指出具體是指什么程序。本文就介紹一下具體漏洞發(fā)生的原理與簡單的利用。在這里我們限定使用的語言是PHP5.4,數(shù)據(jù)庫MYSQL5.6。

涉及到的一些概念

字符、字符集與字符序

字符(character)是組成字符集(character set)的基本單位。對(duì)字符賦予一個(gè)數(shù)值(encoding)來確定這個(gè)字符在該字符集中的位置。

字符序(collation)指同一字符集內(nèi)字符間的比較規(guī)則。

UTF8

由于ASCII表示的字符只有128個(gè),因此網(wǎng)絡(luò)世界的規(guī)范是使用UNICODE編碼,但是用ASCII表示的字符使用UNICODE并不高效。因此出現(xiàn)了中間格式字符集,被稱為通用轉(zhuǎn)換格式,及UTF(Universal Transformation Format)。

寬字節(jié)

GB2312、GBK、GB18030、BIG5、Shift_JIS等這些都是常說的寬字節(jié),實(shí)際上只有兩字節(jié)。寬字節(jié)帶來的安全問題主要是吃ASCII字符(一字節(jié))的現(xiàn)象。

MYSQL的字符集轉(zhuǎn)換過程

1. MySQL Server收到請求時(shí)將請求數(shù)據(jù)從character_set_client轉(zhuǎn)換為character_set_connection;

2. 進(jìn)行內(nèi)部操作前將請求數(shù)據(jù)從character_set_connection轉(zhuǎn)換為內(nèi)部操作字符集,其確定方法如下:

• 使用每個(gè)數(shù)據(jù)字段的CHARACTER SET設(shè)定值;

• 若上述值不存在,則使用對(duì)應(yīng)數(shù)據(jù)表的DEFAULT CHARACTER SET設(shè)定值(MySQL擴(kuò)展,非SQL標(biāo)準(zhǔn));

• 若上述值不存在,則使用對(duì)應(yīng)數(shù)據(jù)庫的DEFAULT CHARACTER SET設(shè)定值;

• 若上述值不存在,則使用character_set_server設(shè)定值。

將操作結(jié)果從內(nèi)部操作字符集轉(zhuǎn)換為character_set_results。

重點(diǎn):寬字節(jié)注入發(fā)生的位置就是PHP發(fā)送請求到MYSQL時(shí)字符集使用character_set_client設(shè)置值進(jìn)行了一次編碼。

PHP測試代碼:

  1. <!DOCTYPE html>  
  2. <meta charset="gbk"><!--僅用于基礎(chǔ)的顯示,換成utf8也行就是不好看-->  
  3. <?php  
  4. error_reporting(0);  
  5. $conn = mysql_connect('127.0.0.1','root','');  
  6. mysql_select_db('mysql',$conn);  
  7. mysql_query("set names gbk");  //不安全的編碼設(shè)置方式  
  8. $res = mysql_query("show variables like 'character%';"); //顯示當(dāng)前數(shù)據(jù)庫設(shè)置的各項(xiàng)字符集  
  9. while($row = mysql_fetch_array($res)){  
  10. var_dump($row);  
  11. }  
  12. $user = addslashes($_GET['sql']); //mysql_real_escape_string() magic_quote_gpc=On addslashes() mysql_escape_string()功能類似  
  13. $sql = "SELECT host,user,password FROM user WHERE user='{$user}'";  
  14. echo $sql.'</br>';  
  15. if($res = mysql_query($sql)){  
  16. while($row = mysql_fetch_array($res)){  
  17. var_dump($row);  
  18. }  
  19. }  
  20. else{  
  21. echo "Error".mysql_error()."<br/>";  
  22. }  
  23. ?> 
http://localhost/xl.php?sql=root%df%27%20or%201=1%23

是可以執(zhí)行成功的!

科普:寬字節(jié)注入詳解

URL解碼sql=rootß’ or 1=1#

解析過程:

$_GET[‘sql’] 經(jīng)過 addslashes編碼之后帶入了‘\’
1、root%df%5C%27%20or%201=1%23
2、帶入mysql處理時(shí)使用了gbk字符集
%df%5c -> 運(yùn) 成功的吃掉了%5c
%27 -> ‘ 單引號(hào)成功閉合

執(zhí)行了插入的sql語句。

怎么吃的:

GBK編碼,它的編碼范圍是0×8140~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。

其它的寬字符集也是一樣的分析過程,要吃掉%5c,只需要低位中包含正常的0x5c就行了。

安全過濾

上文中代碼使用了mysql_query(“set names gbk”)來設(shè)置編碼,其實(shí)在mysql中是推薦mysql_set_charset(“gbk”);函數(shù)來進(jìn)行編碼設(shè)置的,這兩個(gè)函數(shù)大致的功能相似,***不同之處是后者會(huì)修改mysql對(duì)象中的mysql->charset屬性為設(shè)置的字符集。

同時(shí)配套的過濾函數(shù)為mysql_real_escape_string()。上面代碼中列出了幾個(gè)過濾的函數(shù),他們之間的區(qū)別就是mysql_real_escape_string()會(huì)根據(jù)mysql對(duì)象中的mysql->charset屬性來對(duì)待傳入的字符串,因此可以根據(jù)當(dāng)前字符集來進(jìn)行過濾。

具體差別可參考:http://www.laruence.com/2010/04/12/1396.html

同理可得

由上文可得寬字節(jié)注入是由于轉(zhuǎn)編碼而形成的,那具有轉(zhuǎn)編碼功能的函數(shù)也成了漏洞的成因。

轉(zhuǎn)碼函數(shù)

mb_convert_encoding()

iconv()

以下用iconv()來演示,修改上面的代碼:

  1. <!DOCTYPE html>  
  2. <meta charset="gbk">  
  3. <?php  
  4. error_reporting(0);  
  5. $conn = mysql_connect('127.0.0.1','root','');  
  6. mysql_select_db('mysql',$conn);  
  7. mysql_set_charset("utf8"); //推薦的安全編碼  
  8. $user = mysql_real_escape_string(($_GET['sql'])); //推薦的過濾函數(shù)  
  9. $user = iconv('GBK''UTF-8',$user);  
  10. $sql = "SELECT host,user,password FROM user WHERE user='{$user}'";  
  11. echo $sql.'</br>';  
  12. $res = mysql_query($sql);  
  13. while($row = mysql_fetch_array($res)){  
  14. var_dump($row);  
  15. }  
  16. ?> 


 

http://localhost/xl.php?sql=root%e5%27or%201=1%23

同樣可以執(zhí)行成功,編碼解析的過程依然如上。

總結(jié)一下漏洞成因:

代碼一

1、使用了不安全的字符集設(shè)置函數(shù)與過濾函數(shù)。

2、漏洞發(fā)生在PHP請求mysql時(shí)使用character_set_client值進(jìn)行一次轉(zhuǎn)碼。

代碼二

1、使用了推薦的設(shè)置函數(shù)與過濾函數(shù)。

2、解析錯(cuò)誤發(fā)生在iconv()函數(shù)轉(zhuǎn)碼時(shí),GBK轉(zhuǎn)向UTF8吃掉了“\”

3、PHP請求mysql時(shí)轉(zhuǎn)碼安全。

另外:

當(dāng)改變編碼方向時(shí)$user = iconv(‘UTF-8′, ’gbk’,$user);

通過訪問http://localhost/xl.php?sql=root%e9%8c%a6可以帶入一個(gè)\,進(jìn)而注釋掉單引號(hào)。

這種情況下需要兩個(gè)參數(shù)來配合注入。

例如:

http://localhost/xl.php?sql=root%e9%8c%a6¶=%20or%201=1%23

總結(jié):

寬字節(jié)注入跟HTML頁面編碼無關(guān)。

Mysql編碼與過濾函數(shù)推薦使用mysql_real_escape_string(),mysql_set_charset()。

轉(zhuǎn)編碼函數(shù)同樣會(huì)引起寬字節(jié)注入,即使使用了安全的設(shè)置函數(shù)。

責(zé)任編輯:藍(lán)雨淚 來源: 網(wǎng)絡(luò)安全攻防實(shí)驗(yàn)室
相關(guān)推薦

2009-03-27 10:53:52

注入SQLMySQL

2017-10-10 14:38:35

2014-07-09 15:41:51

2017-08-10 10:23:59

2014-04-16 15:56:17

2015-06-23 09:22:13

2011-04-15 09:44:45

Spring

2009-07-10 11:07:00

WebWork注入Servlet方法

2020-09-26 22:15:36

無線網(wǎng)絡(luò)網(wǎng)絡(luò)IBSS

2010-11-26 15:38:32

MySQL注入

2017-03-01 14:16:20

2021-11-23 10:30:35

Android技術(shù)代碼

2023-07-19 10:09:18

架構(gòu)倉庫SSD

2009-12-03 18:23:23

2024-11-27 00:24:04

2017-02-17 08:14:27

2010-09-09 14:31:31

SQL函數(shù)數(shù)據(jù)庫

2009-04-23 10:04:55

2011-03-01 13:45:41

Spring3Annotation

2016-12-12 16:06:41

BI商業(yè)智能
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)