Discuz x3.4前台SSRF

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

来源: www.cnblogs.com

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

本文转载自:https://www.cnblogs.com/iamstudy/articles/discuz_x34_ssrf_1.html,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有。

补丁: 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是在 php 5.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


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

关注码农网公众号

关注我们,获取更多IT资讯^_^


查看所有标签

猜你喜欢:

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

The Haskell School of Music

The Haskell School of Music

Paul Hudak、Donya Quick / Cambridge University Press / 2018-10-4 / GBP 42.99

This book teaches functional programming through creative applications in music and sound synthesis. Readers will learn the Haskell programming language and explore numerous ways to create music and d......一起来看看 《The Haskell School of Music》 这本书的介绍吧!

html转js在线工具
html转js在线工具

html转js在线工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具