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

淺析白盒審計(jì)中的字符編碼及SQL注入

安全 應(yīng)用安全 數(shù)據(jù)安全
盡管現(xiàn)在呼吁所有的程序都使用unicode編碼,所有的網(wǎng)站都使用utf-8編碼,來一個(gè)統(tǒng)一的國際規(guī)范。但仍然有很多,包括國內(nèi)及國外(特別是非英語國家)的一些cms,仍然使用著自己國家的一套編碼,比如gbk,作為自己默認(rèn)的編碼類型。

盡管現(xiàn)在呼吁所有的程序都使用unicode編碼,所有的網(wǎng)站都使用utf-8編碼,來一個(gè)統(tǒng)一的國際規(guī)范。但仍然有很多,包括國內(nèi)及國外(特別是非英語國家)的一些cms,仍然使用著自己國家的一套編碼,比如gbk,作為自己默認(rèn)的編碼類型。也有一些cms為了考慮老用戶,所以出了gbk和utf-8兩個(gè)版本。

[[111422]]

我們就以gbk字符編碼為示范,拉開帷幕。gbk是一種多字符編碼,具體定義自行百度。但有一個(gè)地方尤其要注意:

通常來說,一個(gè)gbk編碼漢字,占用2個(gè)字節(jié)。一個(gè)utf-8編碼的漢字,占用3個(gè)字節(jié)。在php中,我們可以通過輸出

echo strlen("和");

來測試。當(dāng)將頁面編碼保存為gbk時(shí)輸出2,utf-8時(shí)輸出3。

除了gbk以外,所有ANSI編碼都是2個(gè)字節(jié)。ansi只是一個(gè)標(biāo)準(zhǔn),在不用的電腦上它代表的編碼可能不相同,比如簡體中文系統(tǒng)中ANSI就代表是GBK。

以上是一點(diǎn)關(guān)于多字節(jié)編碼的小知識,只有我們足夠了解它的組成及特性以后,才能更好地去分析它身上存在的問題。

說了這么多廢話,現(xiàn)在來研究一下在SQL注入中,字符編碼帶來的各種問題。

0×01 MYSQL中的寬字符注入

這是一個(gè)老話題了,也被人玩過無數(shù)遍。但作為我們這篇文章的序幕,也是基礎(chǔ),是必須要提的。

我們先搭建一個(gè)實(shí)驗(yàn)環(huán)境。暫且稱之為phithon內(nèi)容管理系統(tǒng)v1.0,首先先新建一個(gè)數(shù)據(jù)庫,把如下壓縮包中的sql文件導(dǎo)入:

測試代碼及數(shù)據(jù)庫:http://pan.baidu.com/s/1eQmUArw 提取密碼:75tu

之后的phithon內(nèi)容管理系統(tǒng)會(huì)逐步完善,但會(huì)一直使用這個(gè)數(shù)據(jù)表。

源碼很簡單(注意先關(guān)閉自己php環(huán)境的magic_quotes_gpc):

//連接數(shù)據(jù)庫部分,注意使用了gbk編碼,把數(shù)據(jù)庫信息填寫進(jìn)去

  1. <?php  
  2. //連接數(shù)據(jù)庫部分,注意使用了gbk編碼,把數(shù)據(jù)庫信息填寫進(jìn)去  
  3. $conn = mysql_connect('localhost''root''toor!@#$'or die('bad!');  
  4. mysql_query("SET NAMES 'gbk'");  
  5. mysql_select_db('test'$conn) OR emMsg("連接數(shù)據(jù)庫失敗,未找到您填寫的數(shù)據(jù)庫");  
  6. //執(zhí)行sql語句  
  7. $id = isset($_GET['id']) ? addslashes($_GET['id']) : 1;  
  8. $sql = "SELECT * FROM news WHERE tid='{$id}'";  
  9. $result = mysql_query($sql$connor die(mysql_error()); //sql出錯(cuò)會(huì)報(bào)錯(cuò),方便觀察  
  10. ?>  
  11. <!DOCTYPE html>  
  12. <html>  
  13. <head>  
  14. <meta charset="gbk" />  
  15. <title>新聞</title>  
  16. </head>  
  17. <body>  
  18. <?php  
  19. $row = mysql_fetch_array($result, MYSQL_ASSOC);  
  20. echo "<h2>{$row['title']}</h2><p>{$row['content']}<p>\n";  
  21. mysql_free_result($result);  
  22. ?>  
  23. </body>  
  24. </html> 

SQL語句是SELECT * FROM news WHERE tid='{$id}',就是根據(jù)文章的id把文章從news表中取出來。

在這個(gè)sql語句前面,我們使用了一個(gè)addslashes函數(shù),將$id的值轉(zhuǎn)義。這是通常cms中對sql注入進(jìn)行的操作,只要我們的輸入?yún)?shù)在單引號中,就逃逸不出單引號的限制,無法注入,如下圖:

那么怎么逃過addslashes的限制?眾所周知addslashes函數(shù)產(chǎn)生的效果就是,讓’變成\’,讓引號變得不再是“單引號”,只是一撇而已。一般繞過方式就是,想辦法處理\’前面的\:

1.想辦法給\前面再加一個(gè)\(或單數(shù)個(gè)即可),變成\\’,這樣\被轉(zhuǎn)義了,’逃出了限制
2.想辦法把\弄沒有。

我們這里的寬字節(jié)注入是利用mysql的一個(gè)特性,mysql在使用GBK編碼的時(shí)候,會(huì)認(rèn)為兩個(gè)字符是一個(gè)漢字(前一個(gè)ascii碼要大于128,才到漢字的范圍)。如果我們輸入%df’看會(huì)怎樣:

淺析白盒審計(jì)中的字符編碼及SQL注入

我們可以看到,已經(jīng)報(bào)錯(cuò)了。我們看到報(bào)錯(cuò),說明sql語句出錯(cuò),看到出錯(cuò)說明可以注入了。

為什么從剛才到現(xiàn)在,只是在’也就是%27前面加了一個(gè)%df就報(bào)錯(cuò)了?而且從圖中可以看到,報(bào)錯(cuò)的原因就是多了一個(gè)單引號,而單引號前面的反斜杠不見了。

這就是mysql的特性,因?yàn)間bk是多字節(jié)編碼,他認(rèn)為兩個(gè)字節(jié)代表一個(gè)漢字,所以%df和后面的\也就是%5c變成了一個(gè)漢字“運(yùn)”,而’逃逸了出來。

因?yàn)閮蓚€(gè)字節(jié)代表一個(gè)漢字,所以我們可以試試“%df%df%27”:

淺析白盒審計(jì)中的字符編碼及SQL注入

不報(bào)錯(cuò)了。因?yàn)?df%df是一個(gè)漢字,%5c%27不是漢字,仍然是\’。

那么mysql怎么判斷一個(gè)字符是不是漢字,根據(jù)gbk編碼,第一個(gè)字節(jié)ascii碼大于128,基本上就可以了。比如我們不用%df,用%a1也可以:

淺析白盒審計(jì)中的字符編碼及SQL注入

%a1%5c他可能不是漢字,但一定會(huì)被mysql認(rèn)為是一個(gè)寬字符,就能夠讓后面的%27逃逸了出來。

于是我可以構(gòu)造一個(gè)exp出來,查詢管理員賬號密碼:

淺析白盒審計(jì)中的字符編碼及SQL注入 #p#

0×02 GB2312與GBK的不同

曾經(jīng)有一個(gè)問題一直困擾我很久。

gb2312和gbk應(yīng)該都是寬字節(jié)家族的一員。但我們來做個(gè)小實(shí)驗(yàn)。把phithon內(nèi)容管理系統(tǒng)中set names修改成gb2312:

淺析白盒審計(jì)中的字符編碼及SQL注入

結(jié)果就是不能注入了:

淺析白盒審計(jì)中的字符編碼及SQL注入

有些同學(xué)不信的話,也可以把數(shù)據(jù)庫編碼也改成gb2312,也是不成功的。

為什么,這歸結(jié)于gb2312編碼的取值范圍。它的高位范圍是0xA1~0xF7,低位范圍是0xA1~0xFE,而\是0x5c,是不在低位范圍中的。所以,0x5c根本不是gb2312中的編碼,所以自然也是不會(huì)被吃掉的。

所以,把這個(gè)思路擴(kuò)展到世界上所有多字節(jié)編碼,我們可以這樣認(rèn)為:只要低位的范圍中含有0x5c的編碼,就可以進(jìn)行寬字符注入。#p#

0×03 mysql_real_escape_string解決問題?

部分cms對寬字節(jié)注入有所了解,于是尋求解決方案。在php文檔中,大家會(huì)發(fā)現(xiàn)一個(gè)函數(shù),mysql_real_escape_string,文檔里說了,考慮到連接的當(dāng)前字符集。

淺析白盒審計(jì)中的字符編碼及SQL注入

于是,有的cms就把a(bǔ)ddslashes替換成mysql_real_escape_string,來抵御寬字符注入。我們繼續(xù)做試驗(yàn),phithon內(nèi)容管理系統(tǒng)v1.2:,就用mysql_real_escape_string來過濾輸入:

淺析白盒審計(jì)中的字符編碼及SQL注入

我們來試試能不能注入:

淺析白盒審計(jì)中的字符編碼及SQL注入

一樣沒壓力注入。為什么,明明我用了mysql_real_escape_string,但卻仍然不能抵御寬字符注入。

原因就是,你沒有指定php連接mysql的字符集。我們需要在執(zhí)行sql語句之前調(diào)用一下mysql_set_charset函數(shù),設(shè)置當(dāng)前連接的字符集為gbk。

淺析白盒審計(jì)中的字符編碼及SQL注入

就可以避免這個(gè)問題了:

淺析白盒審計(jì)中的字符編碼及SQL注入 #p#

0×04 寬字符注入的修復(fù)

在3中我們說到了一種修復(fù)方法,就是先調(diào)用mysql_set_charset函數(shù)設(shè)置連接所使用的字符集為gbk,再調(diào)用mysql_real_escape_string來過濾用戶輸入。

這個(gè)方式是可行的,但有部分老的cms,在多處使用addslashes來過濾字符串,我們不可能去一個(gè)一個(gè)把a(bǔ)ddslashes都修改成mysql_real_escape_string。我們第二個(gè)解決方案就是,將character_set_client設(shè)置為binary(二進(jìn)制)。

只需在所有sql語句前指定一下連接的形式是二進(jìn)制:

mysql_query("SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary", $conn);

這幾個(gè)變量是什么意思?

當(dāng)我們的mysql接受到客戶端的數(shù)據(jù)后,會(huì)認(rèn)為他的編碼是character_set_client,然后會(huì)將之將換成character_set_connection的編碼,然后進(jìn)入具體表和字段后,再轉(zhuǎn)換成字段對應(yīng)的編碼。

然后,當(dāng)查詢結(jié)果產(chǎn)生后,會(huì)從表和字段的編碼,轉(zhuǎn)換成character_set_results編碼,返回給客戶端。

所以,我們將character_set_client設(shè)置成binary,就不存在寬字節(jié)或多字節(jié)的問題了,所有數(shù)據(jù)以二進(jìn)制的形式傳遞,就能有效避免寬字符注入。

比如,我們的phithon內(nèi)容管理系統(tǒng)v2.0版本更新如下:

淺析白盒審計(jì)中的字符編碼及SQL注入

已經(jīng)不能夠注入了:

淺析白盒審計(jì)中的字符編碼及SQL注入

在我審計(jì)過的代碼中,大部分cms是以這樣的方式來避免寬字符注入的。這個(gè)方法可以說是有效的,但如果開發(fā)者畫蛇添足地增加一些東西,會(huì)讓之前的努力前功盡棄。#p#

0×05 iconv導(dǎo)致的致命后果

很多cms,不止一個(gè),我就不提名字了,他們的gbk版本都存在因?yàn)樽址幋a造成的注入。但有的同學(xué)說,自己測試了這些cms的寬字符注入,沒有效果呢,難道是自己姿勢不對?

當(dāng)然不是。實(shí)際上,這一章說的已經(jīng)不再是寬字符注入了,因?yàn)閱栴}并不是出在mysql上,而是出在php中了。

很多cms(真的很多哦,不信大家自己網(wǎng)上找找)會(huì)將接收到數(shù)據(jù),調(diào)用這樣一個(gè)函數(shù),轉(zhuǎn)換其編碼:

iconv(‘utf-8’, ‘gbk’, $_GET[‘word’]);

目的一般是為了避免亂碼,特別是在搜索框的位置。

比如我們的phithon內(nèi)容管理系統(tǒng)v3.0

淺析白盒審計(jì)中的字符編碼及SQL注入

我們可以看到,它在sql語句執(zhí)行前,將character_set_client設(shè)置成了binary,所以可以避免寬字符注入的問題。但之后其調(diào)用了iconv將已經(jīng)過濾過的參數(shù)$id給轉(zhuǎn)換了一下。

那我們來試試此時(shí)能不能注入:

淺析白盒審計(jì)中的字符編碼及SQL注入

居然報(bào)錯(cuò)了。說明可以注入。而我只是輸入了一個(gè)“錦'”。這是什么原因?

我們來分析一下。“錦”這個(gè)字,它的utf-8編碼是0xe98ca6,它的gbk編碼是0xe55c。

淺析白盒審計(jì)中的字符編碼及SQL注入 淺析白盒審計(jì)中的字符編碼及SQL注入

有的同學(xué)可能就領(lǐng)悟了。\的ascii碼正是5c。那么,當(dāng)我們的錦被iconv從utf-8轉(zhuǎn)換成gbk后,變成了%e5%5c,而后面的’被addslashes變成了%5c%27,這樣組合起來就是%e5%5c%5c%27,兩個(gè)%5c就是\\,正好把反斜杠轉(zhuǎn)義了,導(dǎo)致’逃逸出單引號,產(chǎn)生注入。

這正利用了我之前說的,繞過addslashes的兩種方式的第一種:將\轉(zhuǎn)義掉。

那么,如果我是用iconv將gbk轉(zhuǎn)換成utf-8呢?

淺析白盒審計(jì)中的字符編碼及SQL注入

我們來試試:

淺析白盒審計(jì)中的字符編碼及SQL注入

果然又成功了。這次直接用寬字符注入的姿勢來的,但實(shí)際上問題出在php而不是mysql。我們知道一個(gè)gbk漢字2字節(jié),utf-8漢字3字節(jié),如果我們把gbk轉(zhuǎn)換成utf-8,則php會(huì)每兩個(gè)字節(jié)一轉(zhuǎn)換。所以,如果\’前面的字符是奇數(shù)的話,勢必會(huì)吞掉\,’逃出限制。

那么為什么之前utf-8轉(zhuǎn)換成gbk的時(shí)候,沒有使用這個(gè)姿勢?

這跟utf-8的規(guī)則有關(guān),UTF-8的編碼規(guī)則很簡單,只有二條:

1)對于單字節(jié)的符號,字節(jié)的第一位設(shè)為0,后面7位為這個(gè)符號的unicode碼。因此對于英語字母,UTF-8編碼和ASCII碼是相同的。

2)對于n字節(jié)的符號(n>1),第一個(gè)字節(jié)的前n位都設(shè)為1,第n+1位設(shè)為0,后面字節(jié)的前兩位一律設(shè)為10。剩下的沒有提及的二進(jìn)制位,全部為這個(gè)符號的unicode碼。

從2我們可以看到,對于多字節(jié)的符號,其第2、3、4字節(jié)的前兩位都是10,也就是說,\(0x0000005c)不會(huì)出現(xiàn)在utf-8編碼中,所以utf-8轉(zhuǎn)換成gbk時(shí),如果有\(zhòng)則php會(huì)報(bào)錯(cuò):

淺析白盒審計(jì)中的字符編碼及SQL注入

 

但因?yàn)間bk編碼中包含了\,所以仍然可以利用,只是利用方式不同罷了。

總而言之,在我們處理了mysql的寬字符注入以后,也別認(rèn)為就可以高枕無憂了。調(diào)用iconv時(shí)千萬要小心,避免出現(xiàn)不必要的麻煩。#p#

0×06 總結(jié)

在逐漸國際化的今天,推行utf-8編碼是大趨勢。如果就安全性來說的話,我也覺得使用utf-8編碼能夠避免很多多字節(jié)造成的問題。

不光是gbk,我只是習(xí)慣性地把gbk作為一個(gè)典型的例子在文中與大家說明。世界上的多字節(jié)編碼有很多,特別是韓國、日本及一些非英語國家的cms,都可能存在由字符編碼造成的安全問題,大家應(yīng)該有擴(kuò)展性的思維。

總結(jié)一下全文中提到的由字符編碼引發(fā)的安全問題及其解決方案:

1.gbk編碼造成的寬字符注入問題,解決方法是設(shè)置character_set_client=binary。

2.矯正人們對于mysql_real_escape_string的誤解,單獨(dú)調(diào)用set name=gbk和mysql_real_escape_string是無法避免寬字符注入問題的。還得調(diào)用mysql_set_charset來設(shè)置一下字符集。

3.謹(jǐn)慎使用iconv來轉(zhuǎn)換字符串編碼,很容易出現(xiàn)問題。只要我們把前端html/js/css所有編碼設(shè)置成gbk,mysql/php編碼設(shè)置成gbk,就不會(huì)出現(xiàn)亂碼問題。不用畫蛇添足地去調(diào)用iconv轉(zhuǎn)換編碼,造成不必要的麻煩。

這篇文章是我對于自己白盒審計(jì)經(jīng)驗(yàn)的一點(diǎn)小總結(jié),但自己確實(shí)在很多方面存在欠缺,文中所提到的姿勢難免存在紕漏和錯(cuò)誤,希望有相同愛好的同學(xué)能與我指出,共同進(jìn)步。

這篇文章不像上篇xss的,能夠舉出很多0day實(shí)例來論證寬字符造成的危害。原因有二:

1.寬字符問題確實(shí)不如富文本xss那么普遍,gbk編碼的cms所占的比例也比較小,怪我才疏學(xué)淺,并不能每一章都找到相應(yīng)的實(shí)例。

‍‍2.注入的危害比xss大得多,如果作為0day發(fā)出來,影響很壞。但我確實(shí)在寫文章以及以前的審計(jì)過程中找到不少cms存在的編碼問題。

所以我用實(shí)驗(yàn)的形式,自己寫了的php小文件,給大家作為例子,希望不會(huì)因?yàn)槔C的不足,影響大家學(xué)習(xí)的效果。

例子php文件和sql文件打包下載:

鏈接:http://pan.baidu.com/s/1eQmUArw 提取密碼:75tu

本文PDF版本:鏈接: http://pan.baidu.com/s/1eprLs 密碼: yoyw

作者博客:http://www.leavesongs.com FROM XDSEC

責(zé)任編輯:藍(lán)雨淚 來源: FreeBuf
相關(guān)推薦

2009-02-12 10:14:16

2015-06-03 09:07:46

白盒審計(jì)PHPPHP自動(dòng)化審計(jì)

2021-07-14 14:19:34

網(wǎng)絡(luò)運(yùn)營白盒網(wǎng)絡(luò)白盒策略

2013-03-25 11:51:42

php漏洞代碼審計(jì)php

2020-05-28 07:00:00

黑盒測試白盒測試灰盒測試

2011-06-08 16:22:24

白盒測試

2020-08-30 14:34:42

Java語言安全編碼web安全

2022-09-19 00:34:32

滲透測試安全漏洞

2017-09-11 14:03:44

SDN白盒網(wǎng)絡(luò)

2023-12-01 16:21:42

2015-12-31 10:17:17

白盒網(wǎng)絡(luò)SDN

2012-01-13 12:21:45

Java

2019-12-13 10:24:05

PythonSQL注入ORM注入

2011-02-28 18:22:14

2024-02-22 08:51:46

大數(shù)據(jù)白盒化治理數(shù)據(jù)治理

2013-01-11 16:23:29

2018-02-10 09:44:19

2011-01-19 10:54:14

軟件評測師

2015-02-26 17:29:49

SDN白盒

2009-09-16 16:32:20

JavaScript靜
點(diǎn)贊
收藏

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