内容字号:默认大号超大号

段落设置:段首缩进取消段首缩进

字体设置:切换到微软雅黑切换到宋体

Discuz x3.4前台SSRF

2018-12-03 20:55 出处:清屏网 人气: 评论(0

补丁: https://gitee.com/ComsenzDiscuz/DiscuzX/commit/41eb5bb0a3a716f84b0ce4e4feb41e6f25a980a3

可跨协议打

缺点: 由于payload构造中有第二次跳转,所以要求对方服务器的127.0.0.1:80也是dz

PHP版本: php ver > 5.3

触发漏洞点

漏洞点: source/module/misc/misc_imgcropper.php:55

$prefix = $_GET['picflag'] == 2 ? $_G['setting']['ftp']['attachurl'] : $_G['setting']['attachurl'];
    if(!$image->Thumb($prefix.$_GET['cutimg'], $cropfile, $picwidth, $picheight)) {

因为 $_G['setting']['ftp']['attachurl'] 默认是 / ,传入Thumb中的 $prefix.$_GET['cutimg'] 的后缀也可控

一路跟进,source/class/class_image.php:52 -> source/class/class_image.php:118

function init($method, $source, $target, $nosuffix = 0) {
        global $_G;

        $this->errorcode = 0;
        if(empty($source)) {
            return -2;
        }
        $parse = parse_url($source);
        if(isset($parse['host'])) {
            if(empty($target)) {
                return -2;
            }
            $data = dfsockopen($source);
            $this->tmpfile = $source = tempnam($_G['setting']['attachdir'].'./temp/', 'tmpimg_');
            if(!$data || $source === FALSE) {
                return -2;
            }
            file_put_contents($source, $data);
}

可以看到如果能够被 parse_url 函数解析出host即可进入 dfsockopen 里面进行curl请求

所以这个就是一个前缀限定为 / ,跟入 parse_url 函数底层会发现,它还支持这种作为url: //www.baidu.com

/php-5.4.45/ext/standard/url.c

继续跟入dz的 dfsockopen 函数

source/function/function_filesock.php:14

$matches = parse_url($url);
$scheme = $matches['scheme'];
$host = $matches['host'];
$path = $matches['path'] ? $matches['path'].($matches['query'] ? '?'.$matches['query'] : '') : '/';
...省略
curl_setopt($ch, CURLOPT_URL, $scheme.'://'.($ip ? $ip : $host).($port ? ':'.$port : '').$path);
...省略
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
...省略

由于协议是为null的,所以最后请求的url地址就是 http://://google.com/aaa ,也就是 http://127.0.0.1:80/google.com/aaa

所以此处需要一个url跳转才能进行下一步的ssrf攻击,当然这也能够攻击本地,不过很鸡肋.

PHP版本问题

仔细研究 parse_url 处理无协议的url时候, //www.baidu.com 在不同的php版本还有一些小差别

相对url是在php5.4才有进行处理

大致总结为

php5.4,能解析ok: //www.baidu.com/../aaa

php5.4后,需要加上端口号: //www.baidu.com:80/../aaa

本地url跳转构造

对于跳转的要求比较高,因为需要的是get型,、不登录、任意地址跳转

找了很久发现了一个很符合要求, logout 的时候会获取referer,然后进入301跳转

其中跳转的地址referer会有验证,验证其是否和本身host匹配,也就是限制了你不能进行任意地址跳转

/source/function/function_core.php:1498

function dreferer($default = '') {
    global $_G;

    $default = empty($default) && $_ENV['curapp'] ? $_ENV['curapp'].'.php' : '';
    $_G['referer'] = !empty($_GET['referer']) ? $_GET['referer'] : $_SERVER['HTTP_REFERER'];
    $_G['referer'] = substr($_G['referer'], -1) == '?' ? substr($_G['referer'], 0, -1) : $_G['referer'];

    if(strpos($_G['referer'], 'member.php?mod=logging')) {
        $_G['referer'] = $default;
    }

    $reurl = parse_url($_G['referer']);

    if(!$reurl || (isset($reurl['scheme']) && !in_array(strtolower($reurl['scheme']), array('http', 'https')))) {
        $_G['referer'] = '';
    }

    if(!empty($reurl['host']) && !in_array($reurl['host'], array($_SERVER['HTTP_HOST'], 'www.'.$_SERVER['HTTP_HOST'])) && !in_array($_SERVER['HTTP_HOST'], array($reurl['host'], 'www.'.$reurl['host']))) {
        if(!in_array($reurl['host'], $_G['setting']['domain']['app']) && !isset($_G['setting']['domain']['list'][$reurl['host']])) {
            $domainroot = substr($reurl['host'], strpos($reurl['host'], '.')+1);
            if(empty($_G['setting']['domain']['root']) || (is_array($_G['setting']['domain']['root']) && !in_array($domainroot, $_G['setting']['domain']['root']))) {
                $_G['referer'] = $_G['setting']['domain']['defaultindex'] ? $_G['setting']['domain']['defaultindex'] : 'index.php';
            }
        }
    } elseif(empty($reurl['host'])) {
        $_G['referer'] = $_G['siteurl'].'./'.$_G['referer'];
    }

    $_G['referer'] = durlencode($_G['referer']);
    return $_G['referer'];
}

因为跳转地址是否合法性的验证是通过 parse_url 解析出 host ,与 $_SERVER['HTTP_HOST'] 进行判断。后面跳转后的地址是进入了curl中进行请求。所以这里牵涉到一个东西就是 parse_urlcurl 的差异性。

当地址为下面链接时,parse_url解析出来为 localhost ,但是进入curl后便是 www.baidu.com

http://localhost#@www.baidu.com/

所以最终跳转的链接如下

htp://localhost/code-src/dz/Discuz_TC_BIG5/upload/member.php?mod=logging&action=logout&XDEBUG_SESSION_START=13904&referer=http://localhost%23%40www.baidu.com&quickforward=1

最后的利用

整个攻击流程如下:

Exp内容(需要post方式,并且还有referer验证):

防止恶意利用

php为5.4的时候,需要去掉www.baidu.com的端口号.

formhash可以从首页的html中获取, home.php?mod=spacecp&ac=pm

Finally Exploit:


分享给小伙伴们:
本文标签: SSRFDiscuz

相关文章

发表评论愿您的每句评论,都能给大家的生活添色彩,带来共鸣,带来思索,带来快乐。

CopyRight © 2015-2016 QingPingShan.com , All Rights Reserved.

清屏网 版权所有 豫ICP备15026204号