Discuz x3.4前台SSRF

栏目: 编程工具 · 发布时间: 5年前

内容简介:补丁: https://gitee.com/ComsenzDiscuz/DiscuzX/commit/41eb5bb0a3a716f84b0ce4e4feb41e6f25a980a3可跨协议打缺点: 由于payload构造中有第二次跳转,所以要求对方服务器的127.0.0.1:80也是dz

补丁: 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

Discuz x3.4前台SSRF

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

Discuz x3.4前台SSRF

继续跟入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跳转

Discuz x3.4前台SSRF

其中跳转的地址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

Discuz x3.4前台SSRF

最后的利用

整个攻击流程如下:

Discuz x3.4前台SSRF

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

防止恶意利用

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

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

Discuz x3.4前台SSRF

Finally Exploit:

Discuz x3.4前台SSRF


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Clean Code

Clean Code

Robert C. Martin / Prentice Hall / 2008-8-11 / USD 49.99

Even bad code can function. But if code isn’t clean, it can bring a development organization to its knees. Every year, countless hours and significant resources are lost because of poorly written code......一起来看看 《Clean Code》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

在线进制转换器
在线进制转换器

各进制数互转换器

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具